From 8442a8541c486eb19a3bc3d940c43a45241f2e44 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 16 Mar 2026 22:12:58 +1100 Subject: [PATCH] Support saving images with non-RGB palettes as PNGs --- Tests/test_file_png.py | 10 ++++++++++ src/PIL/PngImagePlugin.py | 7 +++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 2e0af5041..3f08d1ad3 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -707,6 +707,16 @@ class TestFilePng: assert reloaded.png.im_palette is not None assert len(reloaded.png.im_palette[1]) == 3 + def test_plte_cmyk(self, tmp_path: Path) -> None: + im = Image.new("P", (1, 1)) + im.putpalette((0, 100, 150, 200), "CMYK") + + out = tmp_path / "temp.png" + im.save(out) + + with Image.open(out) as reloaded: + assert reloaded.convert("CMYK").getpixel((0, 0)) == (200, 222, 232, 0) + def test_getxmp(self) -> None: with Image.open("Tests/images/color_snakes.png") as im: if ElementTree is None: diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 572762e6c..4e082a293 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -1353,6 +1353,9 @@ def _save( mode = im.mode outmode = mode + palette = [] + if im.palette: + palette = im.getpalette() or [] if mode == "P": # # attempt to minimize storage requirements for palette images @@ -1362,7 +1365,7 @@ def _save( else: # check palette contents if im.palette: - colors = max(min(len(im.palette.getdata()[1]) // 3, 256), 1) + colors = max(min(len(palette) // 3, 256), 1) else: colors = 256 @@ -1435,7 +1438,7 @@ def _save( if im.mode == "P": palette_byte_number = colors * 3 - palette_bytes = im.im.getpalette("RGB")[:palette_byte_number] + palette_bytes = bytes(palette[:palette_byte_number]) while len(palette_bytes) < palette_byte_number: palette_bytes += b"\0" chunk(fp, b"PLTE", palette_bytes)