|
1 | 1 | # Licensed under the GPL-3.0 License.
|
2 | 2 | # Created for TagStudio: https://github.com/CyanVoxel/TagStudio
|
3 | 3 |
|
4 |
| -import io |
5 | 4 | import time
|
6 | 5 | from pathlib import Path
|
7 | 6 | from typing import TYPE_CHECKING, override
|
8 | 7 |
|
9 | 8 | import cv2
|
10 | 9 | import structlog
|
11 |
| -from PIL import Image, UnidentifiedImageError |
| 10 | +from PIL import Image |
12 | 11 | from PySide6.QtCore import QBuffer, QByteArray, QSize, Qt
|
13 | 12 | from PySide6.QtGui import QAction, QMovie, QPixmap, QResizeEvent
|
14 | 13 | from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QStackedLayout, QWidget
|
@@ -277,62 +276,40 @@ def _display_audio(self, filepath: Path) -> FileAttributeData:
|
277 | 276 | self.__render_thumb(filepath)
|
278 | 277 | return FileAttributeData(duration=self.__update_media_player(filepath))
|
279 | 278 |
|
280 |
| - def _display_animated_image(self, filepath: Path) -> FileAttributeData | None: |
| 279 | + def _display_gif(self, gif_data: bytes, size: tuple[int, int]) -> FileAttributeData | None: |
281 | 280 | """Update the animated image preview from a filepath."""
|
282 |
| - ext = filepath.suffix.lower() |
283 | 281 | stats = FileAttributeData()
|
284 | 282 |
|
285 | 283 | # Ensure that any movie and buffer from previous animations are cleared.
|
286 | 284 | if self.__preview_gif.movie():
|
287 | 285 | self.__preview_gif.movie().stop()
|
288 | 286 | self.__gif_buffer.close()
|
289 | 287 |
|
290 |
| - try: |
291 |
| - image: Image.Image = Image.open(filepath) |
292 |
| - stats.width = image.width |
293 |
| - stats.height = image.height |
294 |
| - |
295 |
| - self.__image_ratio = image.width / image.height |
296 |
| - if ext == ".apng": |
297 |
| - image_bytes_io = io.BytesIO() |
298 |
| - image.save( |
299 |
| - image_bytes_io, |
300 |
| - "GIF", |
301 |
| - lossless=True, |
302 |
| - save_all=True, |
303 |
| - loop=0, |
304 |
| - disposal=2, |
305 |
| - ) |
306 |
| - image.close() |
307 |
| - image_bytes_io.seek(0) |
308 |
| - self.__gif_buffer.setData(image_bytes_io.read()) |
309 |
| - else: |
310 |
| - image.close() |
311 |
| - with open(filepath, "rb") as f: |
312 |
| - self.__gif_buffer.setData(f.read()) |
313 |
| - movie = QMovie(self.__gif_buffer, QByteArray()) |
314 |
| - self.__preview_gif.setMovie(movie) |
315 |
| - |
316 |
| - # If the animation only has 1 frame, display it like a normal image. |
317 |
| - if movie.frameCount() <= 1: |
318 |
| - self._display_image(filepath) |
319 |
| - return stats |
320 |
| - |
321 |
| - # The animation has more than 1 frame, continue displaying it as an animation |
322 |
| - self.__switch_preview(MediaType.IMAGE_ANIMATED) |
323 |
| - self.resizeEvent( |
324 |
| - QResizeEvent( |
325 |
| - QSize(stats.width, stats.height), |
326 |
| - QSize(stats.width, stats.height), |
327 |
| - ) |
328 |
| - ) |
329 |
| - movie.start() |
| 288 | + stats.width = size[0] |
| 289 | + stats.height = size[1] |
| 290 | + |
| 291 | + self.__image_ratio = stats.width / stats.height |
330 | 292 |
|
331 |
| - stats.duration = movie.frameCount() // 60 |
332 |
| - except (UnidentifiedImageError, FileNotFoundError) as e: |
333 |
| - logger.error("[PreviewThumb] Could not load animated image", filepath=filepath, error=e) |
| 293 | + self.__gif_buffer.setData(gif_data) |
| 294 | + movie = QMovie(self.__gif_buffer, QByteArray()) |
| 295 | + self.__preview_gif.setMovie(movie) |
| 296 | + |
| 297 | + # If the animation only has 1 frame, it isn't animated and shouldn't be treated as such |
| 298 | + if movie.frameCount() <= 1: |
334 | 299 | return None
|
335 | 300 |
|
| 301 | + # The animation has more than 1 frame, continue displaying it as an animation |
| 302 | + self.__switch_preview(MediaType.IMAGE_ANIMATED) |
| 303 | + self.resizeEvent( |
| 304 | + QResizeEvent( |
| 305 | + QSize(stats.width, stats.height), |
| 306 | + QSize(stats.width, stats.height), |
| 307 | + ) |
| 308 | + ) |
| 309 | + movie.start() |
| 310 | + |
| 311 | + stats.duration = movie.frameCount() // 60 |
| 312 | + |
336 | 313 | return stats
|
337 | 314 |
|
338 | 315 | def _display_image(self, filepath: Path):
|
|
0 commit comments