From 6449cdc1a3d3c8ddc436aca766198d149add486a Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 17 May 2021 20:48:31 +1000 Subject: [PATCH] Added RGBA saving --- Tests/test_file_dds.py | 18 +++++++++++++----- src/PIL/DdsImagePlugin.py | 13 ++++++++----- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index b44afff3ab2..46ebcad0c1e 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -251,10 +251,18 @@ def test_save_unsupported_mode(tmp_path): im.save(out) -def test_save(tmp_path): +@pytest.mark.parametrize( + ("mode", "test_file"), + [ + ("RGB", "Tests/images/hopper.png"), + ("RGBA", "Tests/images/pil123rgba.png"), + ], +) +def test_save(mode, test_file, tmp_path): out = str(tmp_path / "temp.dds") - im = hopper() - im.save(out) + with Image.open(test_file) as im: + assert im.mode == mode + im.save(out) - with Image.open(out) as reloaded: - assert_image_equal(im, reloaded) + with Image.open(out) as reloaded: + assert_image_equal(im, reloaded) diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index e8a41c04504..260924fca0d 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -203,7 +203,7 @@ def load_seek(self, pos): def _save(im, fp, filename): - if im.mode != "RGB": + if im.mode not in ("RGB", "RGBA"): raise OSError(f"cannot write mode {im.mode} as DDS") fp.write( @@ -214,24 +214,27 @@ def _save(im, fp, filename): ) # flags + o32(im.height) + o32(im.width) - + o32((im.width * 24 + 7) // 8) # pitch + + o32((im.width * (32 if im.mode == "RGBA" else 24) + 7) // 8) # pitch + o32(0) # depth + o32(0) # mipmaps + o32(0) * 11 # reserved + o32(32) # pfsize - + o32(DDPF_RGB) # pfflags + + o32(DDS_RGBA if im.mode == "RGBA" else DDPF_RGB) # pfflags + o32(0) # fourcc - + o32(24) # bitcount + + o32(32 if im.mode == "RGBA" else 24) # bitcount + o32(0xFF0000) # rbitmask + o32(0xFF00) # gbitmask + o32(0xFF) # bbitmask - + o32(0) # abitmask + + o32(0xFF000000 if im.mode == "RGBA" else 0) # abitmask + o32(DDSCAPS_TEXTURE) # dwCaps + o32(0) # dwCaps2 + o32(0) # dwCaps3 + o32(0) # dwCaps4 + o32(0) # dwReserved2 ) + if im.mode == "RGBA": + r, g, b, a = im.split() + im = Image.merge("RGBA", (a, r, g, b)) ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (im.mode[::-1], 0, 1))])