From 622a4f979e0e043740f1e0ee30f13084fa06ccb0 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Fri, 30 Sep 2022 23:24:23 -0500 Subject: [PATCH] Added PIL support for images like webp --- src/shellfm/windows/tabs/icons/icon.py | 39 +++++++++++++++---- .../tabs/icons/mixins/videoiconmixin.py | 4 +- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/shellfm/windows/tabs/icons/icon.py b/src/shellfm/windows/tabs/icons/icon.py index a503f61..94a9b2e 100644 --- a/src/shellfm/windows/tabs/icons/icon.py +++ b/src/shellfm/windows/tabs/icons/icon.py @@ -2,10 +2,17 @@ import os, subprocess, threading, hashlib from os.path import isfile -# Gtk imports +# Lib imports import gi gi.require_version('GdkPixbuf', '2.0') -from gi.repository import GdkPixbuf +from gi.repository import GdkPixbuf, GLib + + +try: + from PIL import Image as PImage +except Exception as e: + PImage = None + # Application imports from .mixins.desktopiconmixin import DesktopIconMixin @@ -30,7 +37,7 @@ class Icon(DesktopIconMixin, VideoIconMixin): if file.lower().endswith(self.fvideos): # Video icon thumbnl = self.create_thumbnail(dir, file) elif file.lower().endswith(self.fimages): # Image Icon - thumbnl = self.create_scaled_image(full_path, self.video_icon_wh) + thumbnl = self.create_scaled_image(full_path) elif full_path.lower().endswith( ('.desktop',) ): # .desktop file parsing thumbnl = self.parse_desktop_files(full_path) @@ -38,13 +45,13 @@ class Icon(DesktopIconMixin, VideoIconMixin): except Exception as e: return None - def create_thumbnail(self, dir, file): + def create_thumbnail(self, dir, file, scrub_percent = "65%"): full_path = f"{dir}/{file}" try: file_hash = hashlib.sha256(str.encode(full_path)).hexdigest() hash_img_pth = f"{self.ABS_THUMBS_PTH}/{file_hash}.jpg" if isfile(hash_img_pth) == False: - self.generate_video_thumbnail(full_path, hash_img_pth) + self.generate_video_thumbnail(full_path, hash_img_pth, scrub_percent) thumbnl = self.create_scaled_image(hash_img_pth, self.video_icon_wh) if thumbnl == None: # If no icon whatsoever, return internal default @@ -57,19 +64,37 @@ class Icon(DesktopIconMixin, VideoIconMixin): return GdkPixbuf.Pixbuf.new_from_file(f"{self.DEFAULT_ICONS}/video.png") - def create_scaled_image(self, path, wxh): + def create_scaled_image(self, path, wxh = None): + if not wxh: + wxh = self.video_icon_wh + try: if path.lower().endswith(".gif"): return GdkPixbuf.PixbufAnimation.new_from_file(path) \ .get_static_image() \ .scale_simple(wxh[0], wxh[1], GdkPixbuf.InterpType.BILINEAR) else: - return GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], True) + if PImage and path.lower().endswith(".webp"): + return self.image2pixbuf(path, wxh) + else: + return GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], True) except Exception as e: print("Image Scaling Issue:") print( repr(e) ) return None + def image2pixbuf(self, path, wxh): + """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(wxh[0], wxh[1], 2) # BILINEAR = 2 + def create_from_file(self, path): try: return GdkPixbuf.Pixbuf.new_from_file(path) diff --git a/src/shellfm/windows/tabs/icons/mixins/videoiconmixin.py b/src/shellfm/windows/tabs/icons/mixins/videoiconmixin.py index fc35e9d..a1cc2eb 100644 --- a/src/shellfm/windows/tabs/icons/mixins/videoiconmixin.py +++ b/src/shellfm/windows/tabs/icons/mixins/videoiconmixin.py @@ -7,9 +7,9 @@ import subprocess class VideoIconMixin: - def generate_video_thumbnail(self, full_path, hash_img_pth): + def generate_video_thumbnail(self, full_path, hash_img_pth, scrub_percent = "65%"): try: - proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", "65%", "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_pth]) + proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", scrub_percent, "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_pth]) proc.wait() except Exception as e: self.logger.debug(repr(e))