From 3fc6fbae86735274c7b0b5c6cf2a1fccfabdb3d1 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Thu, 27 Apr 2023 20:01:53 -0500 Subject: [PATCH] WebP support, smal refactor of image_view --- src/core/widgets/image.py | 19 +--- src/core/widgets/image_view.py | 136 +++++++++------------------ src/core/widgets/image_view_mixin.py | 91 ++++++++++++++++++ 3 files changed, 139 insertions(+), 107 deletions(-) create mode 100644 src/core/widgets/image_view_mixin.py diff --git a/src/core/widgets/image.py b/src/core/widgets/image.py index 82f8cae..a72df90 100644 --- a/src/core/widgets/image.py +++ b/src/core/widgets/image.py @@ -8,12 +8,9 @@ from gi.repository import Gtk from gi.repository import GLib from gi.repository import GdkPixbuf -try: - from PIL import Image as PImage -except Exception as e: - PImage = None # Application imports +from .image_view import ImageView, PImage @@ -64,7 +61,7 @@ class Image(Gtk.EventBox): pixbuf = None if PImage and path.endswith(".webp"): - return self.image2pixbuf(path, w, h) + return ImageView.image2pixbuf(path, w, h) if path.endswith(".gif"): pixbuf = GdkPixbuf.PixbufAnimation.new_from_file(path).get_static_image() @@ -76,15 +73,3 @@ class Image(Gtk.EventBox): pixbuf = Gtk.Image.new_from_resource(path).get_pixbuf() return pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default - - def image2pixbuf(self, path, _w, _h): - """Convert Pillow image to GdkPixbuf""" - im = PImage.open(path) - data = im.tobytes() - data = GLib.Bytes.new(data) - w, h = im.size - - pixbuf = GdkPixbuf.Pixbuf.new_from_bytes(data, GdkPixbuf.Colorspace.RGB, - False, 8, w, h, w * 3) - - return pixbuf.scale_simple(_w, _h, 2) # 2 = BILINEAR and is best by default diff --git a/src/core/widgets/image_view.py b/src/core/widgets/image_view.py index 6c75566..e581617 100644 --- a/src/core/widgets/image_view.py +++ b/src/core/widgets/image_view.py @@ -8,12 +8,22 @@ gi.require_version('GdkPixbuf', '2.0') from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf +from gi.repository.GLib import Bytes + + +try: + from PIL import Image as PImage + logger.debug("Pillow library exists. Loading PIL as PImage...") +except Exception as e: + logger.debug("No Pillow library found. Loading PImage as None...") + PImage = None # Application imports +from .image_view_mixin import ImageViewMixin -class ImageView(Gtk.Image): +class ImageView(ImageViewMixin, Gtk.Image): def __init__(self): super(ImageView, self).__init__() @@ -65,108 +75,54 @@ class ImageView(Gtk.Image): self.work_pixbuf = None self.animation = None + event_system.emit("update_path_label", (path,)) if path.endswith(".gif"): - self.work_pixbuf = GdkPixbuf.PixbufAnimation.new_from_file(path).get_static_image() - try: - self.animation = Gtk.Image.new_from_file(path).get_animation() - except Exception: - self.animation = Gtk.Image.new_from_resource(path).get_animation() + self.set_as_gif(path) + if PImage and path.endswith(".webp"): + self.set_as_webp(path) if not self.work_pixbuf: - try: - self.work_pixbuf = Gtk.Image.new_from_file(path).get_pixbuf() - except Exception: - self.work_pixbuf = Gtk.Image.new_from_resource(path).get_pixbuf() + self.set_as_static(path) self.pixbuf = self.work_pixbuf - self.set_from_pixbuf(self.work_pixbuf) + if self.animation: + ... + else: + self.set_from_pixbuf(self.work_pixbuf) if self.fit_to_win: self._fit_to_container() - event_system.emit("update_path_label", (path,)) + def set_as_gif(self, path): + self.work_pixbuf = GdkPixbuf.PixbufAnimation.new_from_file(path).get_static_image() + try: + self.animation = Gtk.Image.new_from_file(path).get_animation() + except Exception: + self.animation = Gtk.Image.new_from_resource(path).get_animation() - def _zoom_out(self): - if self.work_pixbuf and self.pixbuf: - # TODO: Setup scale factor setting to pull from settings... - stepx = self.work_pixbuf.get_width() * 0.05 - stepy = self.work_pixbuf.get_height() * 0.05 + def set_as_static(self, path): + try: + self.work_pixbuf = Gtk.Image.new_from_file(path).get_pixbuf() + except Exception: + self.work_pixbuf = Gtk.Image.new_from_resource(path).get_pixbuf() - w = self.work_pixbuf.get_width() - stepx - h = self.work_pixbuf.get_height() - stepy + def set_as_webp(self, path): + w = settings.get_thumbnail_with() + h = settings.get_thumbnail_height() + print("shit") + self.work_pixbuf = self.image2pixbuf(path, w, h) - self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default - self.set_from_pixbuf(self.work_pixbuf) + @staticmethod + def image2pixbuf(path, _w, _h): + """Convert Pillow image to GdkPixbuf""" + im = PImage.open(path) + data = im.tobytes() + data = Bytes.new(data) + w, h = im.size - def _rotate_left(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) - self.pixbuf = self.pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) - self.set_from_pixbuf(self.work_pixbuf) + pixbuf = GdkPixbuf.Pixbuf.new_from_bytes(data, GdkPixbuf.Colorspace.RGB, + False, 8, w, h, w * 3) - def _vertical_flip(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.flip(True) - self.pixbuf = self.pixbuf.flip(True) - self.set_from_pixbuf(self.work_pixbuf) - - def _scale_1_two_1(self): - self.fit_to_win = False - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.pixbuf - self.set_from_pixbuf(self.work_pixbuf) - - def _fit_to_container(self): - self.fit_to_win = True - if self.work_pixbuf and self.pixbuf: - parent_aloc = self.get_parent().get_parent().get_allocation() - pw = parent_aloc.width - ph = parent_aloc.height - iw = self.pixbuf.get_width() - ih = self.pixbuf.get_height() - w = 0 - h = 0 - - if iw == 0 or ih == 0: - return - - w = pw; - h = ((ih * w) / iw + 0.5) - - if h > ph: - h = ph - w = (iw * h) / ih + 0.5 - - - self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default - self.set_from_pixbuf(self.work_pixbuf) - - def _horizontal_flip(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.flip(False) - self.pixbuf = self.pixbuf.flip(False) - self.set_from_pixbuf(self.work_pixbuf) - - def _rotate_right(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) - self.pixbuf = self.pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) - self.set_from_pixbuf(self.work_pixbuf) - - def _zoom_in(self): - if self.work_pixbuf and self.pixbuf: - # TODO: Setup scale factor setting to pull from settings... - stepx = self.work_pixbuf.get_width() * 0.05 - stepy = self.work_pixbuf.get_height() * 0.05 - - w = self.work_pixbuf.get_width() + stepx - h = self.work_pixbuf.get_height() + stepy - - self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default - self.set_from_pixbuf(self.work_pixbuf) - - def _size_allocate(self): - if self.fit_to_win: - self._fit_to_container() + return pixbuf.scale_simple(_w, _h, 2) # 2 = BILINEAR and is best by default diff --git a/src/core/widgets/image_view_mixin.py b/src/core/widgets/image_view_mixin.py new file mode 100644 index 0000000..0d14264 --- /dev/null +++ b/src/core/widgets/image_view_mixin.py @@ -0,0 +1,91 @@ +# Python imports + +# Lib imports + +# Application imports + + + +class ImageViewMixin: + def _zoom_out(self): + if self.work_pixbuf and self.pixbuf: + # TODO: Setup scale factor setting to pull from settings... + stepx = self.work_pixbuf.get_width() * 0.05 + stepy = self.work_pixbuf.get_height() * 0.05 + + w = self.work_pixbuf.get_width() - stepx + h = self.work_pixbuf.get_height() - stepy + + self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default + self.set_from_pixbuf(self.work_pixbuf) + + def _rotate_left(self): + if self.work_pixbuf and self.pixbuf: + self.work_pixbuf = self.work_pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) + self.pixbuf = self.pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) + self.set_from_pixbuf(self.work_pixbuf) + + def _vertical_flip(self): + if self.work_pixbuf and self.pixbuf: + self.work_pixbuf = self.work_pixbuf.flip(True) + self.pixbuf = self.pixbuf.flip(True) + self.set_from_pixbuf(self.work_pixbuf) + + def _scale_1_two_1(self): + self.fit_to_win = False + if self.work_pixbuf and self.pixbuf: + self.work_pixbuf = self.pixbuf + self.set_from_pixbuf(self.work_pixbuf) + + def _fit_to_container(self): + self.fit_to_win = True + if self.work_pixbuf and self.pixbuf: + parent_aloc = self.get_parent().get_parent().get_allocation() + pw = parent_aloc.width + ph = parent_aloc.height + iw = self.pixbuf.get_width() + ih = self.pixbuf.get_height() + w = 0 + h = 0 + + if iw == 0 or ih == 0: + return + + w = pw; + h = ((ih * w) / iw + 0.5) + + if h > ph: + h = ph + w = (iw * h) / ih + 0.5 + + + self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default + self.set_from_pixbuf(self.work_pixbuf) + + def _horizontal_flip(self): + if self.work_pixbuf and self.pixbuf: + self.work_pixbuf = self.work_pixbuf.flip(False) + self.pixbuf = self.pixbuf.flip(False) + self.set_from_pixbuf(self.work_pixbuf) + + def _rotate_right(self): + if self.work_pixbuf and self.pixbuf: + self.work_pixbuf = self.work_pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) + self.pixbuf = self.pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) + self.set_from_pixbuf(self.work_pixbuf) + + def _zoom_in(self): + if self.work_pixbuf and self.pixbuf: + # TODO: Setup scale factor setting to pull from settings... + stepx = self.work_pixbuf.get_width() * 0.05 + stepy = self.work_pixbuf.get_height() * 0.05 + + w = self.work_pixbuf.get_width() + stepx + h = self.work_pixbuf.get_height() + stepy + + self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default + self.set_from_pixbuf(self.work_pixbuf) + + def _size_allocate(self): + if self.fit_to_win: + self._fit_to_container()