If append_images is populated, default save_all to True

This commit is contained in:
Andrew Murray 2025-03-01 11:29:13 +11:00
parent d7d48df9af
commit 14e924d127
4 changed files with 26 additions and 15 deletions

View File

@ -1134,6 +1134,12 @@ def test_append_images(tmp_path: Path) -> None:
ims = [Image.new("RGB", (100, 100), color) for color in ["#0f0", "#00f"]] ims = [Image.new("RGB", (100, 100), color) for color in ["#0f0", "#00f"]]
im.copy().save(out, save_all=True, append_images=ims) im.copy().save(out, save_all=True, append_images=ims)
with Image.open(out) as reread:
assert reread.n_frames == 3
# Test append_images without save_all
im.copy().save(out, append_images=ims)
with Image.open(out) as reread: with Image.open(out) as reread:
assert reread.n_frames == 3 assert reread.n_frames == 3

View File

@ -229,8 +229,9 @@ following options are available::
im.save(out, save_all=True, append_images=[im1, im2, ...]) im.save(out, save_all=True, append_images=[im1, im2, ...])
**save_all** **save_all**
If present and true, all frames of the image will be saved. If If present and true, or if ``append_images`` is not empty, all frames of
not, then only the first frame of a multiframe image will be saved. the image will be saved. Otherwise, only the first frame of a multiframe
image will be saved.
**append_images** **append_images**
A list of images to append as additional frames. Each of the A list of images to append as additional frames. Each of the
@ -716,8 +717,8 @@ Saving
When calling :py:meth:`~PIL.Image.Image.save` to write an MPO file, by default When calling :py:meth:`~PIL.Image.Image.save` to write an MPO file, by default
only the first frame of a multiframe image will be saved. If the ``save_all`` only the first frame of a multiframe image will be saved. If the ``save_all``
argument is present and true, then all frames will be saved, and the following argument is present and true, or if ``append_images`` is not empty, all frames
option will also be available. will be saved.
**append_images** **append_images**
A list of images to append as additional pictures. Each of the A list of images to append as additional pictures. Each of the
@ -927,7 +928,8 @@ Saving
When calling :py:meth:`~PIL.Image.Image.save`, by default only a single frame PNG file When calling :py:meth:`~PIL.Image.Image.save`, by default only a single frame PNG file
will be saved. To save an APNG file (including a single frame APNG), the ``save_all`` will be saved. To save an APNG file (including a single frame APNG), the ``save_all``
parameter must be set to ``True``. The following parameters can also be set: parameter should be set to ``True`` or ``append_images`` should not be empty. The
following parameters can also be set:
**default_image** **default_image**
Boolean value, specifying whether or not the base image is a default image. Boolean value, specifying whether or not the base image is a default image.
@ -1156,7 +1158,8 @@ Saving
The :py:meth:`~PIL.Image.Image.save` method can take the following keyword arguments: The :py:meth:`~PIL.Image.Image.save` method can take the following keyword arguments:
**save_all** **save_all**
If true, Pillow will save all frames of the image to a multiframe tiff document. If true, or if ``append_images`` is not empty, Pillow will save all frames of the
image to a multiframe tiff document.
.. versionadded:: 3.4.0 .. versionadded:: 3.4.0
@ -1308,8 +1311,8 @@ Saving sequences
When calling :py:meth:`~PIL.Image.Image.save` to write a WebP file, by default When calling :py:meth:`~PIL.Image.Image.save` to write a WebP file, by default
only the first frame of a multiframe image will be saved. If the ``save_all`` only the first frame of a multiframe image will be saved. If the ``save_all``
argument is present and true, then all frames will be saved, and the following argument is present and true, or if ``append_images`` is not empty, all frames
options will also be available. will be saved, and the following options will also be available.
**append_images** **append_images**
A list of images to append as additional frames. Each of the A list of images to append as additional frames. Each of the
@ -1611,15 +1614,14 @@ The :py:meth:`~PIL.Image.Image.save` method can take the following keyword argum
**save_all** **save_all**
If a multiframe image is used, by default, only the first image will be saved. If a multiframe image is used, by default, only the first image will be saved.
To save all frames, each frame to a separate page of the PDF, the ``save_all`` To save all frames, each frame to a separate page of the PDF, the ``save_all``
parameter must be present and set to ``True``. parameter should be present and set to ``True`` or ``append_images`` should not be
empty.
.. versionadded:: 3.0.0 .. versionadded:: 3.0.0
**append_images** **append_images**
A list of :py:class:`PIL.Image.Image` objects to append as additional pages. Each A list of :py:class:`PIL.Image.Image` objects to append as additional pages. Each
of the images in the list can be single or multiframe images. The ``save_all`` of the images in the list can be single or multiframe images.
parameter must be present and set to ``True`` in conjunction with
``append_images``.
.. versionadded:: 4.2.0 .. versionadded:: 4.2.0

View File

@ -534,7 +534,6 @@ You can create animated GIFs with Pillow, e.g.
# Save the images as an animated GIF # Save the images as an animated GIF
images[0].save( images[0].save(
"animated_hopper.gif", "animated_hopper.gif",
save_all=True,
append_images=images[1:], append_images=images[1:],
duration=500, # duration of each frame in milliseconds duration=500, # duration of each frame in milliseconds
loop=0, # loop forever loop=0, # loop forever

View File

@ -2500,7 +2500,7 @@ class Image:
# may mutate self! # may mutate self!
self._ensure_mutable() self._ensure_mutable()
save_all = params.pop("save_all", False) save_all = params.pop("save_all", None)
self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params} self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params}
self.encoderconfig: tuple[Any, ...] = () self.encoderconfig: tuple[Any, ...] = ()
@ -2520,7 +2520,11 @@ class Image:
if format.upper() not in SAVE: if format.upper() not in SAVE:
init() init()
if save_all: if save_all or (
save_all is None
and params.get("append_images")
and format.upper() in SAVE_ALL
):
save_handler = SAVE_ALL[format.upper()] save_handler = SAVE_ALL[format.upper()]
else: else:
save_handler = SAVE[format.upper()] save_handler = SAVE[format.upper()]