From faebb96b17d2638b23caf30262ef45f7d2d2d0cc Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Thu, 25 Aug 2022 15:45:48 +0300 Subject: [PATCH] Small refactor --- Tests/helper.py | 36 +++++++++++++++++++++--------- src/PIL/DdsImagePlugin.py | 47 ++++++++++++++++++--------------------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 13c6955e41d..b9e91cde756 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -9,30 +9,33 @@ import sysconfig import tempfile from io import BytesIO +from typing import List import pytest from packaging.version import parse as parse_version -from PIL import Image, ImageMath, features +from PIL import Image, ImageMath, features, ImageChops logger = logging.getLogger(__name__) - HAS_UPLOADER = False if os.environ.get("SHOW_ERRORS", None): # local img.show for errors. HAS_UPLOADER = True + class test_image_results: @staticmethod def upload(a, b): - a.show() - b.show() + diff = ImageChops.difference(a.convert("RGB"), b.convert("RGB")) + c = concat_h([a, b, diff]) + c.show() elif "GITHUB_ACTIONS" in os.environ: HAS_UPLOADER = True + class test_image_results: @staticmethod def upload(a, b): @@ -52,6 +55,19 @@ def upload(a, b): pass +def concat_h(images: List[Image.Image]): + new_size = images[0].size + for image in images[1:]: + assert image.height == new_size[1] + new_size = (new_size[0] + image.width, new_size[1]) + dst = Image.new('RGBA', new_size) + x_offset = 0 + for image in images: + dst.paste(image, (x_offset, 0)) + x_offset += image.width + return dst + + def convert_to_comparable(a, b): new_a, new_b = a, b if a.mode == "P": @@ -75,12 +91,12 @@ def assert_deep_equal(a, b, msg=None): def assert_image(im, mode, size, msg=None): if mode is not None: assert im.mode == mode, ( - msg or f"got mode {repr(im.mode)}, expected {repr(mode)}" + msg or f"got mode {repr(im.mode)}, expected {repr(mode)}" ) if size is not None: assert im.size == size, ( - msg or f"got size {repr(im.size)}, expected {repr(size)}" + msg or f"got size {repr(im.size)}, expected {repr(size)}" ) @@ -119,8 +135,8 @@ def assert_image_similar(a, b, epsilon, msg=None): ave_diff = diff / (a.size[0] * a.size[1]) try: assert epsilon >= ave_diff, ( - (msg or "") - + f" average pixel value difference {ave_diff:.4f} > epsilon {epsilon:.4f}" + (msg or "") + + f" average pixel value difference {ave_diff:.4f} > epsilon {epsilon:.4f}" ) except Exception as e: if HAS_UPLOADER: @@ -179,8 +195,8 @@ def mark_if_feature_version(mark, feature, version_blacklist, reason=None): version_required = parse_version(version_blacklist) version_available = parse_version(features.version(feature)) if ( - version_available.major == version_required.major - and version_available.minor == version_required.minor + version_available.major == version_required.major + and version_available.minor == version_required.minor ): return mark(reason=reason) return pytest.mark.pil_noop_mark() diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 091bc64e6da..e186a1b8e97 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -9,7 +9,7 @@ Full text of the CC0 license: https://creativecommons.org/publicdomain/zero/1.0/ """ - +import io import struct from enum import IntEnum, IntFlag from io import BytesIO @@ -302,91 +302,88 @@ def _open(self): fourcc = D3DFMT(fourcc_) masks = struct.unpack("<4I", header.read(16)) if flags & DDSD.CAPS: - (caps1_, caps2_, caps3, caps4, _,) = struct.unpack("<5I", header.read(20)) - else: - (caps1_, caps2_, caps3, caps4, _,) = (0, 0, 0, 0, 0,) - _ = DDSCAPS(caps1_) - _ = DDSCAPS2(caps2_) + header.seek(20, io.SEEK_CUR) + extents = (0, 0) + self.size if pfflags & DDPF.RGB: # Texture contains uncompressed RGB data masks = {mask: ["R", "G", "B", "A"][i] for i, mask in enumerate(masks)} if bitcount == 24: rawmode = masks[0x00FF0000] + masks[0x0000FF00] + masks[0x000000FF] self.mode = "RGB" - self.tile = [("raw", (0, 0) + self.size, 0, (rawmode[::-1], 0, 1))] + self.tile = [("raw", extents, 0, (rawmode[::-1], 0, 1))] elif bitcount == 32 and pfflags & DDPF.ALPHAPIXELS: self.mode = "RGBA" rawmode = (masks[0xFF000000] + masks[0x00FF0000] + masks[0x0000FF00] + masks[0x000000FF]) - self.tile = [("raw", (0, 0) + self.size, 0, (rawmode[::-1], 0, 1))] + self.tile = [("raw", extents, 0, (rawmode[::-1], 0, 1))] else: - raise OSError(f"Unsupported bitcount {bitcount} for {pfflags} DDS texture") + raise OSError(f"Unsupported bitcount {bitcount} for {pfflags}") elif pfflags & DDPF.LUMINANCE: if bitcount == 8: self.mode = "L" - self.tile = [("raw", (0, 0) + self.size, 0, ("L", 0, 1))] + self.tile = [("raw", extents, 0, ("L", 0, 1))] elif bitcount == 16 and pfflags & DDPF.ALPHAPIXELS: self.mode = "LA" - self.tile = [("raw", (0, 0) + self.size, 0, ("LA", 0, 1))] + self.tile = [("raw", extents, 0, ("LA", 0, 1))] else: - raise OSError(f"Unsupported bitcount {bitcount} for {pfflags} DDS texture") + raise OSError(f"Unsupported bitcount {bitcount} for {pfflags}") elif pfflags & DDPF.FOURCC: - data_start = header_size + 4 + data_offs = header_size + 4 if fourcc == D3DFMT.DXT1: self.mode = "RGBA" self.pixel_format = "DXT1" - tile = Image.Tile("bcn", (0, 0) + self.size, data_start, (1, self.pixel_format)) + tile = Image.Tile("bcn", extents, data_offs, (1, self.pixel_format)) elif fourcc == D3DFMT.DXT3: self.mode = "RGBA" self.pixel_format = "DXT3" - tile = Image.Tile("bcn", (0, 0) + self.size, data_start, (2, self.pixel_format)) + tile = Image.Tile("bcn", extents, data_offs, (2, self.pixel_format)) elif fourcc == D3DFMT.DXT5: self.mode = "RGBA" self.pixel_format = "DXT5" - tile = Image.Tile("bcn", (0, 0) + self.size, data_start, (3, self.pixel_format)) + tile = Image.Tile("bcn", extents, data_offs, (3, self.pixel_format)) elif fourcc == D3DFMT.ATI1: self.mode = "L" self.pixel_format = "BC4" - tile = Image.Tile("bcn", (0, 0) + self.size, data_start, (4, self.pixel_format)) + tile = Image.Tile("bcn", extents, data_offs, (4, self.pixel_format)) elif fourcc == D3DFMT.BC5S: self.mode = "RGB" self.pixel_format = "BC5S" - tile = Image.Tile("bcn", (0, 0) + self.size, data_start, (5, self.pixel_format)) + tile = Image.Tile("bcn", extents, data_offs, (5, self.pixel_format)) elif fourcc == D3DFMT.ATI2: self.mode = "RGB" self.pixel_format = "BC5" - tile = Image.Tile("bcn", (0, 0) + self.size, data_start, (5, self.pixel_format)) + tile = Image.Tile("bcn", extents, data_offs, (5, self.pixel_format)) elif fourcc == D3DFMT.DX10: - data_start += 20 + data_offs += 20 # ignoring flags which pertain to volume textures and cubemaps (dxgi_format,) = struct.unpack("