Added append_images parameter to GIF saving

This commit is contained in:
Andrew Murray 2016-09-11 12:04:01 +10:00
parent be7a191b6e
commit b346ed36f1
3 changed files with 51 additions and 28 deletions

View File

@ -351,15 +351,18 @@ 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", [])
for imSequence in [im]+append_images:
for im_frame in ImageSequence.Iterator(imSequence):
encoderinfo = im.encoderinfo.copy()
im_frame = _convert_mode(im_frame) 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: else:
if first_frame: if first_frame:
for s in first_frame: for s in first_frame:
@ -374,7 +377,7 @@ def _save(im, fp, filename, save_all=False):
# compress difference # compress difference
encoderinfo['include_color_table'] = True encoderinfo['include_color_table'] = True
for s in getdata(im_frame.crop(bbox), for s in getdata(im_frame.crop(bbox),
bbox[:2], **im.encoderinfo): bbox[:2], **encoderinfo):
fp.write(s) fp.write(s)
else: else:
# FIXME: what should we do in this case? # FIXME: what should we do in this case?

View File

@ -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()

View File

@ -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