|
6 | 6 | import contextlib |
7 | 7 | import hashlib |
8 | 8 | import math |
| 9 | +import os |
9 | 10 | import zipfile |
10 | 11 | from copy import deepcopy |
11 | 12 | from io import BytesIO |
|
72 | 73 | from tagstudio.qt.resource_manager import ResourceManager |
73 | 74 |
|
74 | 75 | ImageFile.LOAD_TRUNCATED_IMAGES = True |
| 76 | +os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1" |
75 | 77 |
|
76 | 78 | logger = structlog.get_logger(__name__) |
77 | 79 | Image.MAX_IMAGE_PIXELS = None |
@@ -988,6 +990,36 @@ def _image_raw_thumb(filepath: Path) -> Image.Image: |
988 | 990 | logger.error("Couldn't render thumbnail", filepath=filepath, error=type(e).__name__) |
989 | 991 | return im |
990 | 992 |
|
| 993 | + @staticmethod |
| 994 | + def _image_exr_thumb(filepath: Path) -> Image.Image | None: |
| 995 | + """Render a thumbnail for a EXR image type. |
| 996 | +
|
| 997 | + Args: |
| 998 | + filepath (Path): The path of the file. |
| 999 | + """ |
| 1000 | + im: Image.Image | None = None |
| 1001 | + try: |
| 1002 | + # Load the EXR data to an array and rotate the color space from BGRA -> RGBA |
| 1003 | + raw_array = cv2.imread(str(filepath), cv2.IMREAD_UNCHANGED) |
| 1004 | + raw_array[..., :3] = raw_array[..., 2::-1] |
| 1005 | + |
| 1006 | + # Correct the gamma of the raw array |
| 1007 | + gamma = 2.2 |
| 1008 | + array_gamma = np.power(np.clip(raw_array, 0, 1), 1 / gamma) |
| 1009 | + array = (array_gamma * 255).astype(np.uint8) |
| 1010 | + |
| 1011 | + im = Image.fromarray(array, mode="RGBA") |
| 1012 | + |
| 1013 | + # Paste solid background |
| 1014 | + if im.mode == "RGBA": |
| 1015 | + new_bg = Image.new("RGB", im.size, color="#1e1e1e") |
| 1016 | + new_bg.paste(im, mask=im.getchannel(3)) |
| 1017 | + im = new_bg |
| 1018 | + |
| 1019 | + except Exception as e: |
| 1020 | + logger.error("Couldn't render thumbnail", filepath=filepath, error=type(e).__name__) |
| 1021 | + return im |
| 1022 | + |
991 | 1023 | @staticmethod |
992 | 1024 | def _image_thumb(filepath: Path) -> Image.Image: |
993 | 1025 | """Render a thumbnail for a standard image type. |
@@ -1544,6 +1576,9 @@ def _render( |
1544 | 1576 | ext, MediaCategories.IMAGE_VECTOR_TYPES, mime_fallback=True |
1545 | 1577 | ): |
1546 | 1578 | image = self._image_vector_thumb(_filepath, adj_size) |
| 1579 | + # EXR Images ----------------------------------------------- |
| 1580 | + if ext in [".exr"]: |
| 1581 | + image = self._image_exr_thumb(_filepath) |
1547 | 1582 | # Normal Images -------------------------------------------- |
1548 | 1583 | else: |
1549 | 1584 | image = self._image_thumb(_filepath) |
|
0 commit comments