From 2c4b6fbf9543427b2d601d6a24f4526120891825 Mon Sep 17 00:00:00 2001 From: yedpodtrzitko Date: Sat, 23 Nov 2024 22:51:40 +0700 Subject: [PATCH] cleanup thumbnail code --- tagstudio/src/qt/enums.py | 5 +++++ tagstudio/src/qt/thumbnailers/_base.py | 2 +- tagstudio/src/qt/thumbnailers/dummy.py | 2 +- tagstudio/src/qt/thumbnailers/epub.py | 19 ++++++------------- tagstudio/src/qt/thumbnailers/image.py | 2 +- tagstudio/src/qt/thumbnailers/opendoc.py | 2 +- tagstudio/src/qt/ts_qt.py | 5 ++--- tagstudio/src/qt/widgets/preview_panel.py | 7 ++++--- tagstudio/src/qt/widgets/thumb_renderer.py | 9 +++++---- 9 files changed, 26 insertions(+), 27 deletions(-) diff --git a/tagstudio/src/qt/enums.py b/tagstudio/src/qt/enums.py index 7f300459b..ddfd901ef 100644 --- a/tagstudio/src/qt/enums.py +++ b/tagstudio/src/qt/enums.py @@ -13,3 +13,8 @@ class ThumbSize(enum.IntEnum): MEDIUM = 128 LARGE = 192 X_LARGE = 256 + XX_LARGE = 512 + + @property + def tuple(self): + return self.value, self.value diff --git a/tagstudio/src/qt/thumbnailers/_base.py b/tagstudio/src/qt/thumbnailers/_base.py index ede1026f7..130a44729 100644 --- a/tagstudio/src/qt/thumbnailers/_base.py +++ b/tagstudio/src/qt/thumbnailers/_base.py @@ -9,5 +9,5 @@ class ThumbnailBase(ABC): @classmethod @abstractmethod - def render(cls, filepath: Path, size) -> Image: + def render(cls, filepath: Path, size: int) -> Image: raise NotImplementedError diff --git a/tagstudio/src/qt/thumbnailers/dummy.py b/tagstudio/src/qt/thumbnailers/dummy.py index e388ec9bd..3af00b75d 100644 --- a/tagstudio/src/qt/thumbnailers/dummy.py +++ b/tagstudio/src/qt/thumbnailers/dummy.py @@ -9,7 +9,7 @@ class DummyThumbnailer(ThumbnailBase): EXTENSIONS = ("__DUMMY__",) @classmethod - def render(cls, filepath: Path, size): + def render(cls, filepath: Path, size: int) -> Image.Image: # return dummy image return Image.new("RGB", (size, size), color="#1e1e1e") diff --git a/tagstudio/src/qt/thumbnailers/epub.py b/tagstudio/src/qt/thumbnailers/epub.py index d236ab02b..12c6ab690 100644 --- a/tagstudio/src/qt/thumbnailers/epub.py +++ b/tagstudio/src/qt/thumbnailers/epub.py @@ -13,19 +13,12 @@ class EpubThumbnail(ThumbnailBase): EXTENSIONS = ("epub",) @classmethod - def render(cls, filepath: Path, size) -> Image.Image | None: - try: - with zipfile.ZipFile(filepath, "r") as zip_file: - for file_name in zip_file.namelist(): - if file_name.lower().endswith( - (".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg") - ): - image_data = zip_file.read(file_name) - return Image.open(BytesIO(image_data)) - except Exception as e: - logger.error("Couldn't render thumbnail", filepath=filepath, error=e) - # TODO - add fallback image here? - + def render(cls, filepath: Path, size: int) -> Image.Image | None: + with zipfile.ZipFile(filepath, "r") as zip_file: + for file_name in zip_file.namelist(): + if file_name.lower().endswith((".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg")): + image_data = zip_file.read(file_name) + return Image.open(BytesIO(image_data)) return None diff --git a/tagstudio/src/qt/thumbnailers/image.py b/tagstudio/src/qt/thumbnailers/image.py index 6b0558837..892694df4 100644 --- a/tagstudio/src/qt/thumbnailers/image.py +++ b/tagstudio/src/qt/thumbnailers/image.py @@ -12,7 +12,7 @@ class ImageThumbnail(ThumbnailBase): EXTENSIONS = ("jpg", "jpeg", "png", "gif", "bmp", "tiff", "webp") @classmethod - def render(cls, filepath: Path, size): + def render(cls, filepath: Path, size: int) -> Image.Image: im = Image.open(filepath) if im.mode not in ("RGB", "RGBA"): im = im.convert(mode="RGBA") diff --git a/tagstudio/src/qt/thumbnailers/opendoc.py b/tagstudio/src/qt/thumbnailers/opendoc.py index a07ce7157..7d1d5db17 100644 --- a/tagstudio/src/qt/thumbnailers/opendoc.py +++ b/tagstudio/src/qt/thumbnailers/opendoc.py @@ -13,7 +13,7 @@ class OpendocThumbnail(ThumbnailBase): EXTENSIONS = ("odt", "ods") @classmethod - def render(cls, filepath: Path, size) -> Image.Image: + def render(cls, filepath: Path, size: int) -> Image.Image: file_path_within_zip = "Thumbnails/thumbnail.png" with zipfile.ZipFile(filepath, "r") as zip_file: if file_path_within_zip in zip_file.namelist(): diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 00203a7d9..d8dcb2501 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -988,7 +988,6 @@ def update_thumbs(self): ItemThumb.update_cutoff = time.time() ratio: float = self.main_window.devicePixelRatio() - base_size: tuple[int, int] = (self.thumb_size, self.thumb_size) # scrollbar: QScrollArea = self.main_window.scrollArea # scrollbar.verticalScrollBar().setValue(scrollbar_pos) @@ -1012,7 +1011,7 @@ def update_thumbs(self): self.thumb_job_queue.put( ( item_thumb.renderer.render, - (sys.float_info.max, None, base_size, ratio, True, True), + (sys.float_info.max, None, self.thumb_size, ratio, True, True), ) ) @@ -1041,7 +1040,7 @@ def update_thumbs(self): self.thumb_job_queue.put( ( item_thumb.renderer.render, - (time.time(), entry, base_size, ratio, False, True), + (time.time(), entry, self.thumb_size, ratio, False, True), ) ) diff --git a/tagstudio/src/qt/widgets/preview_panel.py b/tagstudio/src/qt/widgets/preview_panel.py index 3eea34459..a8bfe520f 100644 --- a/tagstudio/src/qt/widgets/preview_panel.py +++ b/tagstudio/src/qt/widgets/preview_panel.py @@ -42,6 +42,7 @@ ) from src.core.library.alchemy.library import Library from src.core.media_types import MediaCategories +from src.qt.enums import ThumbSize from src.qt.helpers.file_opener import FileOpenerHelper, FileOpenerLabel, open_file from src.qt.helpers.file_tester import is_readable_video from src.qt.helpers.qbutton_wrapper import QPushButtonWrapper @@ -409,7 +410,7 @@ def update_widgets(self) -> bool: self.thumb_renderer.render( time.time(), None, - (512, 512), + ThumbSize.XX_LARGE, ratio, is_loading=True, update_on_ratio_change=True, @@ -463,7 +464,7 @@ def update_widgets(self) -> bool: self.thumb_renderer.render( time.time(), item, - (512, 512), + ThumbSize.XX_LARGE, ratio, update_on_ratio_change=True, ) @@ -655,7 +656,7 @@ def update_widgets(self) -> bool: self.thumb_renderer.render( time.time(), None, - (512, 512), + ThumbSize.XX_LARGE, ratio, is_loading=True, update_on_ratio_change=True, diff --git a/tagstudio/src/qt/widgets/thumb_renderer.py b/tagstudio/src/qt/widgets/thumb_renderer.py index e058febbe..b8a66d3bb 100644 --- a/tagstudio/src/qt/widgets/thumb_renderer.py +++ b/tagstudio/src/qt/widgets/thumb_renderer.py @@ -849,7 +849,7 @@ def render( self, timestamp: float, entry: Entry | None, - base_size: tuple[int, int], + base_size: ThumbSize, pixel_ratio: float, is_loading: bool = False, is_grid_thumb: bool = False, @@ -860,7 +860,7 @@ def render( Args: timestamp (float): The timestamp for which this job was dispatched. entry (Entry | None): The path of the file to render a thumbnail for. - base_size (tuple[int,int]): The unmodified base size of the thumbnail. + base_size (ThumbSize): The unmodified base size of the thumbnail. pixel_ratio (float): The screen pixel ratio. is_loading (bool): Is this a loading graphic? is_grid_thumb (bool): Is this a thumbnail for the thumbnail grid? @@ -868,7 +868,7 @@ def render( update_on_ratio_change (bool): Should an updated ratio signal be sent? """ - adj_size = math.ceil(max(base_size[0], base_size[1]) * pixel_ratio) + adj_size = math.ceil(base_size.value * pixel_ratio) pixmap: QPixmap = None image = None @@ -876,6 +876,7 @@ def render( ext = _filepath.suffix.lower() if _filepath else None + # TODO - use proper thumbnail size has_thumbnail, final = self.library.get_thumbnail(entry, size=ThumbSize.MEDIUM) if has_thumbnail: qim = ImageQt.ImageQt(final) @@ -963,7 +964,7 @@ def render( resampling_method = ( Image.Resampling.NEAREST - if max(image.size[0], image.size[1]) < max(base_size[0], base_size[1]) + if max(image.size[0], image.size[1]) < base_size.value else Image.Resampling.BILINEAR ) image = image.resize((new_x, new_y), resample=resampling_method)