mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-27 17:54:32 +03:00
Added append_images parameter to GIF saving
This commit is contained in:
parent
be7a191b6e
commit
b346ed36f1
|
@ -351,35 +351,38 @@ def _save(im, fp, filename, save_all=False):
|
||||||
previous = None
|
previous = None
|
||||||
|
|
||||||
first_frame = None
|
first_frame = None
|
||||||
for im_frame in ImageSequence.Iterator(im):
|
append_images = im.encoderinfo.get("append_images", [])
|
||||||
im_frame = _convert_mode(im_frame)
|
for imSequence in [im]+append_images:
|
||||||
|
for im_frame in ImageSequence.Iterator(imSequence):
|
||||||
|
encoderinfo = im.encoderinfo.copy()
|
||||||
|
im_frame = _convert_mode(im_frame)
|
||||||
|
|
||||||
# To specify duration, add the time in milliseconds to getdata(),
|
# To specify duration, add the time in milliseconds to getdata(),
|
||||||
# e.g. getdata(im_frame, duration=1000)
|
# e.g. getdata(im_frame, duration=1000)
|
||||||
if not previous:
|
if not previous:
|
||||||
# global header
|
# global header
|
||||||
first_frame = getheader(im_frame, palette, im.encoderinfo)[0]
|
first_frame = getheader(im_frame, palette, encoderinfo)[0]
|
||||||
first_frame += getdata(im_frame, (0, 0), **im.encoderinfo)
|
first_frame += getdata(im_frame, (0, 0), **encoderinfo)
|
||||||
else:
|
|
||||||
if first_frame:
|
|
||||||
for s in first_frame:
|
|
||||||
fp.write(s)
|
|
||||||
first_frame = None
|
|
||||||
|
|
||||||
# delta frame
|
|
||||||
delta = ImageChops.subtract_modulo(im_frame, previous.copy())
|
|
||||||
bbox = delta.getbbox()
|
|
||||||
|
|
||||||
if bbox:
|
|
||||||
# compress difference
|
|
||||||
encoderinfo['include_color_table'] = True
|
|
||||||
for s in getdata(im_frame.crop(bbox),
|
|
||||||
bbox[:2], **im.encoderinfo):
|
|
||||||
fp.write(s)
|
|
||||||
else:
|
else:
|
||||||
# FIXME: what should we do in this case?
|
if first_frame:
|
||||||
pass
|
for s in first_frame:
|
||||||
previous = im_frame
|
fp.write(s)
|
||||||
|
first_frame = None
|
||||||
|
|
||||||
|
# delta frame
|
||||||
|
delta = ImageChops.subtract_modulo(im_frame, previous.copy())
|
||||||
|
bbox = delta.getbbox()
|
||||||
|
|
||||||
|
if bbox:
|
||||||
|
# compress difference
|
||||||
|
encoderinfo['include_color_table'] = True
|
||||||
|
for s in getdata(im_frame.crop(bbox),
|
||||||
|
bbox[:2], **encoderinfo):
|
||||||
|
fp.write(s)
|
||||||
|
else:
|
||||||
|
# FIXME: what should we do in this case?
|
||||||
|
pass
|
||||||
|
previous = im_frame
|
||||||
if first_frame:
|
if first_frame:
|
||||||
save_all = False
|
save_all = False
|
||||||
if not save_all:
|
if not save_all:
|
||||||
|
|
|
@ -306,6 +306,24 @@ class TestFileGif(PillowTestCase):
|
||||||
reread = Image.open(out)
|
reread = Image.open(out)
|
||||||
self.assertEqual(reread.info["version"], b"GIF87a")
|
self.assertEqual(reread.info["version"], b"GIF87a")
|
||||||
|
|
||||||
|
def test_append_images(self):
|
||||||
|
out = self.tempfile('temp.gif')
|
||||||
|
|
||||||
|
# Test appending single frame images
|
||||||
|
im = Image.new('RGB', (100, 100), '#f00')
|
||||||
|
ims = [Image.new('RGB', (100, 100), color) for color in ['#0f0', '#00f']]
|
||||||
|
im.save(out, save_all=True, append_images=ims)
|
||||||
|
|
||||||
|
reread = Image.open(out)
|
||||||
|
self.assertEqual(reread.n_frames, 3)
|
||||||
|
|
||||||
|
# Tests appending single and multiple frame images
|
||||||
|
im = Image.open("Tests/images/dispose_none.gif")
|
||||||
|
ims = [Image.open("Tests/images/dispose_prev.gif")]
|
||||||
|
im.save(out, save_all=True, append_images=ims)
|
||||||
|
|
||||||
|
reread = Image.open(out)
|
||||||
|
self.assertEqual(reread.n_frames, 10)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -103,7 +103,9 @@ Saving sequences
|
||||||
|
|
||||||
When calling :py:meth:`~PIL.Image.Image.save`, if a multiframe image is used,
|
When calling :py:meth:`~PIL.Image.Image.save`, if a multiframe image is used,
|
||||||
by default only the first frame will be saved. To save all frames, the
|
by default only the first frame will be saved. To save all frames, the
|
||||||
``save_all`` parameter must be present and set to ``True``.
|
``save_all`` parameter must be present and set to ``True``. To append
|
||||||
|
additional frames when saving, the ``append_images`` parameter can be set to a
|
||||||
|
list of images containing the extra frames.
|
||||||
|
|
||||||
If present, the ``loop`` parameter can be used to set the number of times
|
If present, the ``loop`` parameter can be used to set the number of times
|
||||||
the GIF should loop, and the ``duration`` parameter can set the number of
|
the GIF should loop, and the ``duration`` parameter can set the number of
|
||||||
|
|
Loading…
Reference in New Issue
Block a user