This commit is contained in:
Andrew Murray 2025-05-27 22:20:59 +00:00 committed by GitHub
commit 1d21bbdf41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 11 deletions

View File

@ -293,16 +293,18 @@ def test_save_all() -> None:
assert_image_similar(im, im_reloaded, 30) assert_image_similar(im, im_reloaded, 30)
im = Image.new("RGB", (1, 1)) im = Image.new("RGB", (1, 1))
im2 = Image.new("RGB", (1, 1), "#f00") for colors in (("#f00",), ("#f00", "#0f0")):
im_reloaded = roundtrip(im, save_all=True, append_images=[im2]) append_images = (Image.new("RGB", (1, 1), color) for color in colors)
im_reloaded = roundtrip(im, save_all=True, append_images=append_images)
assert_image_equal(im, im_reloaded) assert_image_equal(im, im_reloaded)
assert isinstance(im_reloaded, MpoImagePlugin.MpoImageFile) assert isinstance(im_reloaded, MpoImagePlugin.MpoImageFile)
assert im_reloaded.mpinfo is not None assert im_reloaded.mpinfo is not None
assert im_reloaded.mpinfo[45056] == b"0100" assert im_reloaded.mpinfo[45056] == b"0100"
im_reloaded.seek(1) for im_expected in append_images:
assert_image_similar(im2, im_reloaded, 1) im_reloaded.seek(im_reloaded.tell() + 1)
assert_image_similar(im_reloaded, im_expected, 1)
# Test that a single frame image will not be saved as an MPO # Test that a single frame image will not be saved as an MPO
jpg = roundtrip(im, save_all=True) jpg = roundtrip(im, save_all=True)

View File

@ -19,7 +19,6 @@
# #
from __future__ import annotations from __future__ import annotations
import itertools
import os import os
import struct import struct
from typing import IO, Any, cast from typing import IO, Any, cast
@ -47,12 +46,20 @@ def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
mpf_offset = 28 mpf_offset = 28
offsets: list[int] = [] offsets: list[int] = []
for imSequence in itertools.chain([im], append_images): total = 0
imSequences = [im] + list(append_images)
for imSequence in imSequences:
total += getattr(imSequence, "n_frames", 1)
for imSequence in imSequences:
for im_frame in ImageSequence.Iterator(imSequence): for im_frame in ImageSequence.Iterator(imSequence):
if not offsets: if not offsets:
# APP2 marker # APP2 marker
ifd_length = 66 + 16 * total
im_frame.encoderinfo["extra"] = ( im_frame.encoderinfo["extra"] = (
b"\xff\xe2" + struct.pack(">H", 6 + 82) + b"MPF\0" + b" " * 82 b"\xff\xe2"
+ struct.pack(">H", 6 + ifd_length)
+ b"MPF\0"
+ b" " * ifd_length
) )
exif = im_frame.encoderinfo.get("exif") exif = im_frame.encoderinfo.get("exif")
if isinstance(exif, Image.Exif): if isinstance(exif, Image.Exif):