mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +03:00
When saving multiple frames, convert to mode rather than raw mode
This commit is contained in:
parent
bbe1effd63
commit
f34360d1e3
|
@ -655,11 +655,12 @@ class TestFilePng:
|
|||
png.call(cid, 0, 0)
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
|
||||
def test_specify_bits(self, tmp_path: Path) -> None:
|
||||
@pytest.mark.parametrize("save_all", (True, False))
|
||||
def test_specify_bits(self, save_all: bool, tmp_path: Path) -> None:
|
||||
im = hopper("P")
|
||||
|
||||
out = str(tmp_path / "temp.png")
|
||||
im.save(out, bits=4)
|
||||
im.save(out, bits=4, save_all=save_all)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
assert len(reloaded.png.im_palette[1]) == 48
|
||||
|
|
|
@ -1104,7 +1104,7 @@ class _fdat:
|
|||
self.seq_num += 1
|
||||
|
||||
|
||||
def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images):
|
||||
def _write_multiple_frames(im, fp, chunk, mode, rawmode, default_image, append_images):
|
||||
duration = im.encoderinfo.get("duration", im.info.get("duration", 0))
|
||||
loop = im.encoderinfo.get("loop", im.info.get("loop", 0))
|
||||
disposal = im.encoderinfo.get("disposal", im.info.get("disposal", Disposal.OP_NONE))
|
||||
|
@ -1119,10 +1119,10 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
|
|||
frame_count = 0
|
||||
for im_seq in chain:
|
||||
for im_frame in ImageSequence.Iterator(im_seq):
|
||||
if im_frame.mode == rawmode:
|
||||
if im_frame.mode == mode:
|
||||
im_frame = im_frame.copy()
|
||||
else:
|
||||
im_frame = im_frame.convert(rawmode)
|
||||
im_frame = im_frame.convert(mode)
|
||||
encoderinfo = im.encoderinfo.copy()
|
||||
if isinstance(duration, (list, tuple)):
|
||||
encoderinfo["duration"] = duration[frame_count]
|
||||
|
@ -1184,8 +1184,8 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
|
|||
|
||||
# default image IDAT (if it exists)
|
||||
if default_image:
|
||||
if im.mode != rawmode:
|
||||
im = im.convert(rawmode)
|
||||
if im.mode != mode:
|
||||
im = im.convert(mode)
|
||||
ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)])
|
||||
|
||||
seq_num = 0
|
||||
|
@ -1262,6 +1262,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
|||
size = im.size
|
||||
mode = im.mode
|
||||
|
||||
outmode = mode
|
||||
if mode == "P":
|
||||
#
|
||||
# attempt to minimize storage requirements for palette images
|
||||
|
@ -1282,7 +1283,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
|||
bits = 2
|
||||
else:
|
||||
bits = 4
|
||||
mode = f"{mode};{bits}"
|
||||
outmode += f";{bits}"
|
||||
|
||||
# encoder options
|
||||
im.encoderconfig = (
|
||||
|
@ -1294,7 +1295,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
|||
|
||||
# get the corresponding PNG mode
|
||||
try:
|
||||
rawmode, bit_depth, color_type = _OUTMODES[mode]
|
||||
rawmode, bit_depth, color_type = _OUTMODES[outmode]
|
||||
except KeyError as e:
|
||||
msg = f"cannot write mode {mode} as PNG"
|
||||
raise OSError(msg) from e
|
||||
|
@ -1415,7 +1416,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
|||
|
||||
if save_all:
|
||||
im = _write_multiple_frames(
|
||||
im, fp, chunk, rawmode, default_image, append_images
|
||||
im, fp, chunk, mode, rawmode, default_image, append_images
|
||||
)
|
||||
if im:
|
||||
ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)])
|
||||
|
|
Loading…
Reference in New Issue
Block a user