mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-24 17:06:16 +03:00
Merge pull request #6610 from radarhere/png_save_all
This commit is contained in:
commit
3d491663ba
|
@ -647,6 +647,16 @@ def test_seek_after_close():
|
||||||
im.seek(0)
|
im.seek(0)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("mode", ("RGBA", "RGB", "P"))
|
||||||
|
def test_different_modes_in_later_frames(mode, tmp_path):
|
||||||
|
test_file = str(tmp_path / "temp.png")
|
||||||
|
|
||||||
|
im = Image.new("L", (1, 1))
|
||||||
|
im.save(test_file, save_all=True, append_images=[Image.new(mode, (1, 1))])
|
||||||
|
with Image.open(test_file) as reloaded:
|
||||||
|
assert reloaded.mode == mode
|
||||||
|
|
||||||
|
|
||||||
def test_constants_deprecation():
|
def test_constants_deprecation():
|
||||||
for enum, prefix in {
|
for enum, prefix in {
|
||||||
PngImagePlugin.Disposal: "APNG_DISPOSE_",
|
PngImagePlugin.Disposal: "APNG_DISPOSE_",
|
||||||
|
|
|
@ -1089,28 +1089,28 @@ class _fdat:
|
||||||
self.seq_num += 1
|
self.seq_num += 1
|
||||||
|
|
||||||
|
|
||||||
def _write_multiple_frames(im, fp, chunk, rawmode):
|
def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images):
|
||||||
default_image = im.encoderinfo.get("default_image", im.info.get("default_image"))
|
|
||||||
duration = im.encoderinfo.get("duration", im.info.get("duration", 0))
|
duration = im.encoderinfo.get("duration", im.info.get("duration", 0))
|
||||||
loop = im.encoderinfo.get("loop", im.info.get("loop", 0))
|
loop = im.encoderinfo.get("loop", im.info.get("loop", 0))
|
||||||
disposal = im.encoderinfo.get("disposal", im.info.get("disposal", Disposal.OP_NONE))
|
disposal = im.encoderinfo.get("disposal", im.info.get("disposal", Disposal.OP_NONE))
|
||||||
blend = im.encoderinfo.get("blend", im.info.get("blend", Blend.OP_SOURCE))
|
blend = im.encoderinfo.get("blend", im.info.get("blend", Blend.OP_SOURCE))
|
||||||
|
|
||||||
if default_image:
|
if default_image:
|
||||||
chain = itertools.chain(im.encoderinfo.get("append_images", []))
|
chain = itertools.chain(append_images)
|
||||||
else:
|
else:
|
||||||
chain = itertools.chain([im], im.encoderinfo.get("append_images", []))
|
chain = itertools.chain([im], append_images)
|
||||||
|
|
||||||
im_frames = []
|
im_frames = []
|
||||||
frame_count = 0
|
frame_count = 0
|
||||||
for im_seq in chain:
|
for im_seq in chain:
|
||||||
for im_frame in ImageSequence.Iterator(im_seq):
|
for im_frame in ImageSequence.Iterator(im_seq):
|
||||||
im_frame = im_frame.copy()
|
if im_frame.mode == rawmode:
|
||||||
if im_frame.mode != im.mode:
|
im_frame = im_frame.copy()
|
||||||
if im.mode == "P":
|
else:
|
||||||
im_frame = im_frame.convert(im.mode, palette=im.palette)
|
if rawmode == "P":
|
||||||
|
im_frame = im_frame.convert(rawmode, palette=im.palette)
|
||||||
else:
|
else:
|
||||||
im_frame = im_frame.convert(im.mode)
|
im_frame = im_frame.convert(rawmode)
|
||||||
encoderinfo = im.encoderinfo.copy()
|
encoderinfo = im.encoderinfo.copy()
|
||||||
if isinstance(duration, (list, tuple)):
|
if isinstance(duration, (list, tuple)):
|
||||||
encoderinfo["duration"] = duration[frame_count]
|
encoderinfo["duration"] = duration[frame_count]
|
||||||
|
@ -1221,7 +1221,26 @@ def _save_all(im, fp, filename):
|
||||||
def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
||||||
# save an image to disk (called by the save method)
|
# save an image to disk (called by the save method)
|
||||||
|
|
||||||
mode = im.mode
|
if save_all:
|
||||||
|
default_image = im.encoderinfo.get(
|
||||||
|
"default_image", im.info.get("default_image")
|
||||||
|
)
|
||||||
|
modes = set()
|
||||||
|
append_images = im.encoderinfo.get("append_images", [])
|
||||||
|
if default_image:
|
||||||
|
chain = itertools.chain(append_images)
|
||||||
|
else:
|
||||||
|
chain = itertools.chain([im], append_images)
|
||||||
|
for im_seq in chain:
|
||||||
|
for im_frame in ImageSequence.Iterator(im_seq):
|
||||||
|
modes.add(im_frame.mode)
|
||||||
|
for mode in ("RGBA", "RGB", "P"):
|
||||||
|
if mode in modes:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
mode = modes.pop()
|
||||||
|
else:
|
||||||
|
mode = im.mode
|
||||||
|
|
||||||
if mode == "P":
|
if mode == "P":
|
||||||
|
|
||||||
|
@ -1373,7 +1392,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
||||||
chunk(fp, b"eXIf", exif)
|
chunk(fp, b"eXIf", exif)
|
||||||
|
|
||||||
if save_all:
|
if save_all:
|
||||||
_write_multiple_frames(im, fp, chunk, rawmode)
|
_write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
|
||||||
else:
|
else:
|
||||||
ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)])
|
ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user