Use save parameters as encoderinfo defaults

This commit is contained in:
Andrew Murray 2025-06-07 15:08:16 +10:00
parent f3b05d6fab
commit 0bb99e5561
5 changed files with 35 additions and 13 deletions

View File

@ -312,10 +312,20 @@ def test_save_all() -> None:
def test_save_xmp() -> None: def test_save_xmp() -> None:
im = Image.new("RGB", (1, 1)) im = Image.new("RGB", (1, 1))
im2 = Image.new("RGB", (1, 1), "#f00") im2 = Image.new("RGB", (1, 1), "#f00")
def roundtrip_xmp():
im_reloaded = roundtrip(im, xmp=b"Default", save_all=True, append_images=[im2])
xmp = [im_reloaded.info["xmp"]]
im_reloaded.seek(1)
return xmp + [im_reloaded.info["xmp"]]
# Use the save parameters for all frames by default
assert roundtrip_xmp() == [b"Default", b"Default"]
# Specify a value for the first frame
im.encoderinfo = {"xmp": b"First frame"}
assert roundtrip_xmp() == [b"First frame", b"Default"]
# Specify value for the second frame
im2.encoderinfo = {"xmp": b"Second frame"} im2.encoderinfo = {"xmp": b"Second frame"}
im_reloaded = roundtrip(im, xmp=b"First frame", save_all=True, append_images=[im2]) assert roundtrip_xmp() == [b"Default", b"Second frame"]
assert im_reloaded.info["xmp"] == b"First frame"
im_reloaded.seek(1)
assert im_reloaded.info["xmp"] == b"Second frame"

View File

@ -695,16 +695,21 @@ class TestFileTiff:
assert im.tag_v2[278] == 256 assert im.tag_v2[278] == 256
im = hopper() im = hopper()
im.encoderinfo = {"tiffinfo": {278: 100}}
im2 = Image.new("L", (128, 128)) im2 = Image.new("L", (128, 128))
im2.encoderinfo = {"tiffinfo": {278: 256}} im3 = im2.copy()
im.save(outfile, save_all=True, append_images=[im2]) im3.encoderinfo = {"tiffinfo": {278: 300}}
im.save(outfile, save_all=True, tiffinfo={278: 200}, append_images=[im2, im3])
with Image.open(outfile) as im: with Image.open(outfile) as im:
assert isinstance(im, TiffImagePlugin.TiffImageFile) assert isinstance(im, TiffImagePlugin.TiffImageFile)
assert im.tag_v2[278] == 128 assert im.tag_v2[278] == 100
im.seek(1) im.seek(1)
assert im.tag_v2[278] == 256 assert im.tag_v2[278] == 200
im.seek(2)
assert im.tag_v2[278] == 300
def test_strip_raw(self) -> None: def test_strip_raw(self) -> None:
infile = "Tests/images/tiff_strip_raw.tif" infile = "Tests/images/tiff_strip_raw.tif"

View File

@ -2555,7 +2555,8 @@ class Image:
self.load() self.load()
save_all = params.pop("save_all", None) save_all = params.pop("save_all", None)
self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params} self._default_encoderinfo = params
self._attach_default_encoderinfo(self)
self.encoderconfig: tuple[Any, ...] = () self.encoderconfig: tuple[Any, ...] = ()
if format.upper() not in SAVE: if format.upper() not in SAVE:
@ -2600,6 +2601,12 @@ class Image:
if open_fp: if open_fp:
fp.close() fp.close()
def _attach_default_encoderinfo(self, im: Image) -> Any:
self.encoderinfo = {
**im._default_encoderinfo,
**getattr(self, "encoderinfo", {}),
}
def seek(self, frame: int) -> None: def seek(self, frame: int) -> None:
""" """
Seeks to the given frame in this sequence file. If you seek Seeks to the given frame in this sequence file. If you seek

View File

@ -64,6 +64,7 @@ def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
JpegImagePlugin._save(im_frame, fp, filename) JpegImagePlugin._save(im_frame, fp, filename)
offsets.append(fp.tell()) offsets.append(fp.tell())
else: else:
im_frame._attach_default_encoderinfo(im)
im_frame.save(fp, "JPEG") im_frame.save(fp, "JPEG")
offsets.append(fp.tell() - offsets[-1]) offsets.append(fp.tell() - offsets[-1])

View File

@ -2310,8 +2310,7 @@ def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
try: try:
with AppendingTiffWriter(fp) as tf: with AppendingTiffWriter(fp) as tf:
for ims in [im] + append_images: for ims in [im] + append_images:
if not hasattr(ims, "encoderinfo"): ims._attach_default_encoderinfo(im)
ims.encoderinfo = {}
if not hasattr(ims, "encoderconfig"): if not hasattr(ims, "encoderconfig"):
ims.encoderconfig = () ims.encoderconfig = ()
nfr = getattr(ims, "n_frames", 1) nfr = getattr(ims, "n_frames", 1)