Skip to content

Commit 9255a86

Browse files
CyanVoxelTyrannicodinyedpodtrzitko
authored
feat: add svg thumbnail support (port #442) (#540)
* feat: add svg thumbnail support Co-Authored-By: Tyrannicodin <[email protected]> * flip `svg.isValid()` logic check * tests: add test comparing svg to png snapshot Co-Authored-By: yed <[email protected]> --------- Co-authored-by: Tyrannicodin <[email protected]> Co-authored-by: yed <[email protected]>
1 parent 5b85462 commit 9255a86

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

tagstudio/src/qt/widgets/thumb_renderer.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
from PIL.Image import DecompressionBombError
2929
from pillow_heif import register_avif_opener, register_heif_opener
3030
from pydub import exceptions
31-
from PySide6.QtCore import QObject, QSize, Qt, Signal
32-
from PySide6.QtGui import QGuiApplication, QPixmap
31+
from PySide6.QtCore import QBuffer, QObject, QSize, Qt, Signal
32+
from PySide6.QtGui import QGuiApplication, QImage, QPainter, QPixmap
33+
from PySide6.QtSvg import QSvgRenderer
3334
from src.core.constants import FONT_SAMPLE_SIZES, FONT_SAMPLE_TEXT
3435
from src.core.media_types import MediaCategories, MediaType
3536
from src.core.palette import ColorType, UiColor, get_ui_color
@@ -750,8 +751,33 @@ def _image_vector_thumb(self, filepath: Path, size: int) -> Image.Image:
750751
filepath (Path): The path of the file.
751752
size (tuple[int,int]): The size of the thumbnail.
752753
"""
753-
# TODO: Implement.
754754
im: Image.Image = None
755+
# Create an image to draw the svg to and a painter to do the drawing
756+
image: QImage = QImage(size, size, QImage.Format.Format_ARGB32)
757+
image.fill("#1e1e1e")
758+
759+
# Create an svg renderer, then render to the painter
760+
svg: QSvgRenderer = QSvgRenderer(str(filepath))
761+
762+
if not svg.isValid():
763+
raise UnidentifiedImageError
764+
765+
painter: QPainter = QPainter(image)
766+
svg.setAspectRatioMode(Qt.AspectRatioMode.KeepAspectRatio)
767+
svg.render(painter)
768+
painter.end()
769+
770+
# Write the image to a buffer as png
771+
buffer: QBuffer = QBuffer()
772+
buffer.open(QBuffer.OpenModeFlag.ReadWrite)
773+
image.save(buffer, "PNG")
774+
775+
# Load the image from the buffer
776+
im = Image.new("RGB", (size, size), color="#1e1e1e")
777+
im.paste(Image.open(BytesIO(buffer.data().data())))
778+
im = im.convert(mode="RGB")
779+
780+
buffer.close()
755781
return im
756782

757783
def _model_stl_thumb(self, filepath: Path, size: int) -> Image.Image:
@@ -924,6 +950,7 @@ def render(
924950
ext, MediaCategories.IMAGE_RAW_TYPES, mime_fallback=True
925951
):
926952
image = self._image_raw_thumb(_filepath)
953+
# Vector Images --------------------------------------------
927954
elif MediaCategories.is_ext_in_category(
928955
ext, MediaCategories.IMAGE_VECTOR_TYPES, mime_fallback=True
929956
):

tagstudio/tests/fixtures/sample.svg

Lines changed: 8 additions & 0 deletions
Loading
5.13 KB
Loading
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright (C) 2024 Travis Abendshien (CyanVoxel).
2+
# Licensed under the GPL-3.0 License.
3+
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
4+
5+
import io
6+
from pathlib import Path
7+
8+
from PIL import Image
9+
from src.qt.widgets.thumb_renderer import ThumbRenderer
10+
from syrupy.extensions.image import PNGImageSnapshotExtension
11+
12+
13+
def test_svg_preview(cwd, snapshot):
14+
file_path: Path = cwd / "fixtures" / "sample.svg"
15+
renderer = ThumbRenderer()
16+
img: Image.Image = renderer._image_vector_thumb(file_path, 200)
17+
18+
img_bytes = io.BytesIO()
19+
img.save(img_bytes, format="PNG")
20+
img_bytes.seek(0)
21+
assert img_bytes.read() == snapshot(extension_class=PNGImageSnapshotExtension)

0 commit comments

Comments
 (0)