From c322a2f63378c04bf1203bab5e3e9e8ff59cbe9e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 21 Feb 2024 19:39:29 +1100 Subject: [PATCH] Use maximum frame size in IHDR chunk when saving --- Tests/test_file_apng.py | 10 ++++++++++ src/PIL/PngImagePlugin.py | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Tests/test_file_apng.py b/Tests/test_file_apng.py index 395165b3657..1b393a3ff5d 100644 --- a/Tests/test_file_apng.py +++ b/Tests/test_file_apng.py @@ -668,6 +668,16 @@ def test_apng_save_blend(tmp_path: Path) -> None: assert im.getpixel((0, 0)) == (0, 255, 0, 255) +def test_apng_save_size(tmp_path: Path) -> None: + test_file = str(tmp_path / "temp.png") + + im = Image.new("L", (100, 100)) + im.save(test_file, save_all=True, append_images=[Image.new("L", (200, 200))]) + + with Image.open(test_file) as reloaded: + assert reloaded.size == (200, 200) + + def test_seek_after_close() -> None: im = Image.open("Tests/images/apng/delay.png") im.seek(1) diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 823f1249285..203d962e35e 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -1232,16 +1232,20 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False): "default_image", im.info.get("default_image") ) modes = set() + sizes = set() append_images = im.encoderinfo.get("append_images", []) for im_seq in itertools.chain([im], append_images): for im_frame in ImageSequence.Iterator(im_seq): modes.add(im_frame.mode) + sizes.add(im_frame.size) for mode in ("RGBA", "RGB", "P"): if mode in modes: break else: mode = modes.pop() + size = tuple(max(frame_size[i] for frame_size in sizes) for i in range(2)) else: + size = im.size mode = im.mode if mode == "P": @@ -1289,8 +1293,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False): chunk( fp, b"IHDR", - o32(im.size[0]), # 0: size - o32(im.size[1]), + o32(size[0]), # 0: size + o32(size[1]), mode, # 8: depth/type b"\0", # 10: compression b"\0", # 11: filter category