From 361f579579ca9cfed40a9bb4fc322e0ea99d60e4 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 15 Jan 2017 17:36:59 +1100 Subject: [PATCH] Moved iCCP chunk before PLTE chunk when saving as PNG --- PIL/PngImagePlugin.py | 24 ++++++++++++------------ Tests/test_file_png.py | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py index dca8a456e..486162a38 100644 --- a/PIL/PngImagePlugin.py +++ b/PIL/PngImagePlugin.py @@ -715,6 +715,18 @@ def _save(im, fp, filename, chunk=putchunk, check=0): b'\0', # 11: filter category b'\0') # 12: interlace flag + icc = im.encoderinfo.get("icc_profile", im.info.get("icc_profile")) + if icc: + # ICC profile + # according to PNG spec, the iCCP chunk contains: + # Profile name 1-79 bytes (character string) + # Null separator 1 byte (null character) + # Compression method 1 byte (0) + # Compressed profile n bytes (zlib with deflate compression) + name = b"ICC Profile" + data = name + b"\0\0" + zlib.compress(icc) + chunk(fp, b"iCCP", data) + if im.mode == "P": palette_byte_number = (2 ** bits) * 3 palette_bytes = im.im.getpalette("RGB")[:palette_byte_number] @@ -764,18 +776,6 @@ def _save(im, fp, filename, chunk=putchunk, check=0): for cid, data in info.chunks: chunk(fp, cid, data) - icc = im.encoderinfo.get("icc_profile", im.info.get("icc_profile")) - if icc: - # ICC profile - # according to PNG spec, the iCCP chunk contains: - # Profile name 1-79 bytes (character string) - # Null separator 1 byte (null character) - # Compression method 1 byte (0) - # Compressed profile n bytes (zlib with deflate compression) - name = b"ICC Profile" - data = name + b"\0\0" + zlib.compress(icc) - chunk(fp, b"iCCP", data) - ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0)+im.size, 0, rawmode)]) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index cab0e01fa..fc6b07699 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -497,6 +497,25 @@ class TestFilePng(PillowTestCase): self.assertEqual(repr_png.format, 'PNG') self.assert_image_equal(im, repr_png) + def test_chunk_order(self): + im = Image.open("Tests/images/icc_profile.png") + test_file = self.tempfile("temp.png") + im.convert("P").save(test_file) + + chunks = [] + fp = open(test_file, "rb") + fp.read(8) + png = PngImagePlugin.PngStream(fp) + while True: + cid, pos, length = png.read() + chunks.append(cid) + try: + s = png.call(cid, pos, length) + except EOFError: + break + png.crc(cid, s) + self.assertLess(chunks.index(b"iCCP"), chunks.index(b"PLTE")) + if __name__ == '__main__': unittest.main()