feat: add JXL thumbnail and animated APNG + WEBP support (port #344 and partially port #357) (#549)

* feat: add JXL image thumbnail support

Co-Authored-By: BPplays <58504799+bpplays@users.noreply.github.com>

* feat: add animated previews for webp and apng

Co-Authored-By: BPplays <58504799+bpplays@users.noreply.github.com>

---------

Co-authored-by: BPplays <58504799+bpplays@users.noreply.github.com>
This commit is contained in:
Travis Abendshien
2024-11-07 15:12:57 -08:00
committed by GitHub
parent 96026b66bc
commit f21d49df7f
4 changed files with 44 additions and 28 deletions

View File

@@ -1,19 +1,20 @@
humanfriendly==10.0
opencv_python>=4.8.0.74,<=4.9.0.80
Pillow==10.3.0
PySide6==6.7.1
PySide6_Addons==6.7.1
PySide6_Essentials==6.7.1
typing_extensions>=3.10.0.0,<=4.11.0
ujson>=5.8.0,<=5.9.0
numpy==1.26.4
rawpy==0.21.0
pillow-heif==0.16.0
chardet==5.2.0
structlog==24.4.0
SQLAlchemy==2.0.34
pydub==0.25.1
ffmpeg-python==0.2.0
humanfriendly==10.0
mutagen==1.47.0
numpy==1.26.4
ffmpeg-python==0.2.0
vtf2img==0.1.0
numpy==1.26.4
opencv_python>=4.8.0.74,<=4.9.0.80
pillow-heif==0.16.0
pillow-jxl-plugin==1.2.6
Pillow==10.3.0
pydub==0.25.1
PySide6_Addons==6.7.1
PySide6_Essentials==6.7.1
PySide6==6.7.1
rawpy==0.21.0
SQLAlchemy==2.0.34
structlog==24.4.0
typing_extensions>=3.10.0.0,<=4.11.0
ujson>=5.8.0,<=5.9.0
vtf2img==0.1.0

View File

@@ -193,7 +193,6 @@ class MediaCategories:
".apng",
".gif",
".webp",
".jxl",
}
_IMAGE_RAW_SET: set[str] = {
".arw",

View File

@@ -1,6 +1,8 @@
# Copyright (C) 2024 Travis Abendshien (CyanVoxel).
# Licensed under the GPL-3.0 License.
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
import io
import os
import platform
import sys
@@ -601,19 +603,32 @@ class PreviewPanel(QWidget):
# TODO: Do this all somewhere else, this is just here temporarily.
ext: str = filepath.suffix.lower()
try:
if filepath.suffix.lower() in [".gif"]:
with open(filepath, mode="rb") as file:
if self.preview_gif.movie():
self.preview_gif.movie().stop()
self.gif_buffer.close()
if MediaCategories.is_ext_in_category(
ext, MediaCategories.IMAGE_ANIMATED_TYPES, mime_fallback=True
):
if self.preview_gif.movie():
self.preview_gif.movie().stop()
self.gif_buffer.close()
ba = file.read()
self.gif_buffer.setData(ba)
movie = QMovie(self.gif_buffer, QByteArray())
self.preview_gif.setMovie(movie)
movie.start()
image: Image.Image = Image.open(filepath)
anim_image: Image.Image = image
image_bytes_io: io.BytesIO = io.BytesIO()
anim_image.save(
image_bytes_io,
"GIF",
lossless=True,
save_all=True,
loop=0,
disposal=2,
)
image_bytes_io.seek(0)
ba: bytes = image_bytes_io.read()
self.gif_buffer.setData(ba)
movie = QMovie(self.gif_buffer, QByteArray())
self.preview_gif.setMovie(movie)
movie.start()
image = Image.open(str(filepath))
self.resizeEvent(
QResizeEvent(
QSize(image.width, image.height),

View File

@@ -12,6 +12,7 @@ from pathlib import Path
import cv2
import numpy as np
import pillow_jxl # noqa: F401
import rawpy
import structlog
from mutagen import MutagenError, flac, id3, mp4