From 92b01515016d2fde1203f7a2711eaef1619c8c40 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 8 Oct 2022 22:18:31 +1100 Subject: [PATCH 1/5] Simplified test code --- Tests/test_file_dds.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index cabf1e0a9f3..cdabf90e70d 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -286,6 +286,21 @@ def test_save_unsupported_mode(tmp_path): im.save(out) +@pytest.mark.parametrize( + ("mode", "test_file"), + ( + ("L", "Tests/images/l.dds"), + ("LA", "Tests/images/la.dds"), + ("RGB", "Tests/images/rgb.dds"), + ("RGBA", "Tests/images/rgba.dds"), + ), +) +def test_open(mode, test_file): + with Image.open(test_file) as im: + assert im.mode == mode + assert_image_equal_tofile(im, test_file.replace(".dds", ".png")) + + @pytest.mark.parametrize( ("mode", "test_file"), [ @@ -303,19 +318,3 @@ def test_save(mode, test_file, tmp_path): with Image.open(out) as reloaded: assert_image_equal(im, reloaded) - - -@pytest.mark.parametrize( - ("mode", "expected_file", "input_file"), - [ - ("L", "Tests/images/l.png", "Tests/images/l.dds"), - ("LA", "Tests/images/la.png", "Tests/images/la.dds"), - ("RGB", "Tests/images/rgb.png", "Tests/images/rgb.dds"), - ("RGBA", "Tests/images/rgba.png", "Tests/images/rgba.dds"), - ], -) -def test_open(mode, expected_file, input_file): - with Image.open(input_file) as im: - assert im.mode == mode - with Image.open(expected_file) as im2: - assert_image_equal(im, im2) From ac99e6d7e3acc2ace0a665e12a76b5fff2cf39bd Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 8 Oct 2022 22:27:53 +1100 Subject: [PATCH 2/5] Fixed typo --- src/PIL/DdsImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index bc36f1cb3b2..10c8678a732 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -433,7 +433,7 @@ def _save(im, fp, filename): stride = (im.width * bit_count + 7) // 8 fp.write( o32(DDS_MAGIC) - # header size, flags, height, width, pith, depth, mipmaps + # header size, flags, height, width, pitch, depth, mipmaps + struct.pack(" Date: Sat, 8 Oct 2022 22:33:49 +1100 Subject: [PATCH 3/5] Restored formatting --- src/PIL/DdsImagePlugin.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 10c8678a732..fffbc2dc2d7 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -277,7 +277,6 @@ class DdsImageFile(ImageFile.ImageFile): format = "DDS" format_description = "DirectDraw Surface" - # fmt: off def _open(self): if not _accept(self.fp.read(4)): raise SyntaxError("not a DDS file") @@ -313,10 +312,12 @@ def _open(self): 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]) + rawmode = ( + masks[0xFF000000] + + masks[0x00FF0000] + + masks[0x0000FF00] + + masks[0x000000FF] + ) self.tile = [("raw", extents, 0, (rawmode[::-1], 0, 1))] else: raise OSError(f"Unsupported bitcount {bitcount} for {pfflags}") @@ -398,15 +399,12 @@ def _open(self): else: raise NotImplementedError(f"Unknown pixel format flags {repr(pfflags)}") - # fmt: on - def load_seek(self, pos): pass -# fmt: off def _save(im, fp, filename): - if im.mode not in ("RGB", "RGBA", "L", 'LA'): + if im.mode not in ("RGB", "RGBA", "L", "LA"): raise OSError(f"cannot write mode {im.mode} as DDS") pixel_flags = DDPF.RGB @@ -419,7 +417,7 @@ def _save(im, fp, filename): bit_count = 32 r, g, b, a = im.split() im = Image.merge("RGBA", (a, r, g, b)) - elif im.mode == 'LA': + elif im.mode == "LA": pixel_flags = DDPF.LUMINANCE | DDPF.ALPHAPIXELS rgba_mask = struct.pack("<4I", 0x000000FF, 0x000000FF, 0x000000FF, 0x0000FF00) bit_count = 16 @@ -433,8 +431,16 @@ def _save(im, fp, filename): stride = (im.width * bit_count + 7) // 8 fp.write( o32(DDS_MAGIC) - # header size, flags, height, width, pitch, depth, mipmaps - + struct.pack(" Date: Sat, 8 Oct 2022 22:56:58 +1100 Subject: [PATCH 4/5] Fixed big-endian bug --- src/PIL/DdsImagePlugin.py | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index fffbc2dc2d7..24d89546669 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -15,6 +15,7 @@ from io import BytesIO from . import Image, ImageFile +from ._binary import i32le as i32 from ._binary import o32le as o32 # Magic ("DDS ") @@ -191,10 +192,6 @@ def _missing_(cls, value: object): return cls.INVALID -def make_fourcc(name): - return struct.unpack("I", name.encode("ascii"))[0] - - class D3DFMT(IntEnum): UNKNOWN = 0 R8G8B8 = 20 @@ -252,20 +249,20 @@ class D3DFMT(IntEnum): A2B10G10R10_XR_BIAS = 119 BINARYBUFFER = 199 - UYVY = make_fourcc("UYVY") - R8G8_B8G8 = make_fourcc("RGBG") - YUY2 = make_fourcc("YUY2") - G8R8_G8B8 = make_fourcc("GRGB") - DXT1 = make_fourcc("DXT1") - DXT2 = make_fourcc("DXT2") - DXT3 = make_fourcc("DXT3") - DXT4 = make_fourcc("DXT4") - DXT5 = make_fourcc("DXT5") - DX10 = make_fourcc("DX10") - BC5S = make_fourcc("BC5S") - ATI1 = make_fourcc("ATI1") - ATI2 = make_fourcc("ATI2") - MULTI2_ARGB8 = make_fourcc("MET1") + UYVY = i32(b"UYVY") + R8G8_B8G8 = i32(b"RGBG") + YUY2 = i32(b"YUY2") + G8R8_G8B8 = i32(b"GRGB") + DXT1 = i32(b"DXT1") + DXT2 = i32(b"DXT2") + DXT3 = i32(b"DXT3") + DXT4 = i32(b"DXT4") + DXT5 = i32(b"DXT5") + DX10 = i32(b"DX10") + BC5S = i32(b"BC5S") + ATI1 = i32(b"ATI1") + ATI2 = i32(b"ATI2") + MULTI2_ARGB8 = i32(b"MET1") INVALID = -1 @classmethod From e49420c93b5ccd82e66337996fcf8f6ab2d7c75e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 8 Oct 2022 23:06:39 +1100 Subject: [PATCH 5/5] Simplified imports --- src/PIL/DdsImagePlugin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 24d89546669..4c4090658e4 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -12,7 +12,6 @@ import io import struct from enum import IntEnum, IntFlag -from io import BytesIO from . import Image, ImageFile from ._binary import i32le as i32 @@ -283,7 +282,7 @@ def _open(self): header_bytes = self.fp.read(header_size - 4) if len(header_bytes) != 120: raise OSError(f"Incomplete header: {len(header_bytes)} bytes") - header = BytesIO(header_bytes) + header = io.BytesIO(header_bytes) flags_, height, width = struct.unpack("<3I", header.read(12)) flags = DDSD(flags_)