15

(Python 3.4, PIL 1.1.7, Pillow 2.5.1)

I expected this to copy the original GIF.

from PIL import Image
im = Image.open(filename)
im.save('temp.gif')

Instead, it saves the first frame as a still.

What am I doing wrong?

leewz
  • 3,201
  • 1
  • 18
  • 38
  • 1
    I just answered the same question here ^^: http://stackoverflow.com/a/24688649/1144523. Basically, Image let's you work with gifs one image at a time. – machow Jul 11 '14 at 01:22
  • Hm, that's unfortunate. There doesn't seem to be a real GIF module for Python. – leewz Jul 11 '14 at 01:38
  • Since it's not an exact duplicate, I'm hesitant to close it as duplicate. Can you post your last sentence as an answer? – leewz Aug 21 '14 at 02:53
  • machow's question is about reading GIF, not writing GIF. – Damian Yerrick Feb 17 '16 at 16:15
  • @Damian, it answered the question of, "Why isn't this working?" Also, the last sentence in machow's answer in that question linked to an answer for saving GIFs. – leewz Feb 19 '16 at 09:17
  • Possible duplicate of [How to create a multiple frame image using Python PIL](https://stackoverflow.com/questions/19540119/how-to-create-a-multiple-frame-image-using-python-pil) – Cees Timmerman Sep 26 '18 at 10:42
  • @CeesTimmerman While one of the answers also addresses this question, that question was edited to ask for a TIFF. The question is related, but not exactly a duplicate (yet). – leewz Sep 27 '18 at 00:30
  • @leewz The code is the same, just replace "tiff" by "gif". – Cees Timmerman Sep 27 '18 at 12:22
  • @CeesTimmerman Your answer is the same, but the question doesn't quite overlap. Someone needs to edit that question. – leewz Sep 27 '18 at 18:53
  • Note that currently selected answer is not working. – reducing activity Jan 26 '19 at 14:27

4 Answers4

21

Version that requires only pillow and works:

from PIL import Image

width = 300
height = 300
im1 = Image.new("RGBA", (width, height), (255, 0, 0))
im2 = Image.new("RGBA", (width, height), (255, 255, 0))
im3 = Image.new("RGBA", (width, height), (255, 255, 255))
im1.save("out.gif", save_all=True, append_images=[im2, im3], duration=100, loop=0)

using existing images:

from PIL import Image

im1 = Image.open('a.png')
im2 = Image.open('b.png')
im3 = Image.open('c.png')
im1.save("out.gif", save_all=True, append_images=[im2, im3], duration=100, loop=0)

And, as too low versions of pillow are silently failing here is as a bonus version with a library version check:

from packaging import version
from PIL import Image

im1 = Image.open('a.png')
im2 = Image.open('b.png')
im3 = Image.open('c.png')
if version.parse(Image.PILLOW_VERSION) < version.parse("3.4"):
    print("Pillow in version not supporting making animated gifs")
    print("you need to upgrade library version")
    print("see release notes in")
    print("https://pillow.readthedocs.io/en/latest/releasenotes/3.4.0.html#append-images-to-gif")
else:
    im1.save("out.gif", save_all=True, append_images=[
             im2, im3], duration=100, loop=0)
Arturo Moncada-Torres
  • 1,236
  • 14
  • 23
reducing activity
  • 1,985
  • 2
  • 36
  • 64
13

One can see that the new version of gifmaker script simply uses save method with special kwargs for GIF.

As the documentation states (https://pillow.readthedocs.org/en/latest/handbook/image-file-formats.html#saving-sequences):

When calling save(), if a multiframe image is used, by default only the first frame will be saved. To save all frames, the save_all parameter must be present and set to True.

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 milliseconds between each frame.

Community
  • 1
  • 1
mr. Y
  • 187
  • 1
  • 5
  • But I couldn't find anything in the documentation about how to create a multiframe image from scratch rather than from another GIF. – Damian Yerrick Feb 16 '16 at 04:01
  • Yes, it is a problem. It appears that Pillow does not provide any interface to do that. – mr. Y Feb 17 '16 at 07:59
  • 7
    Actually now it does: https://pillow.readthedocs.io/en/latest/releasenotes/3.4.0.html#append-images-to-gif – cube Oct 20 '16 at 13:12
4

Use the script found on the Pillow Github, here.

 from PIL import ImageSequence
 from PIL import Image
 import gifmaker
 sequence = []

 im = Image.open(....)

 # im is your original image
 frames = [frame.copy() for frame in ImageSequence.Iterator(im)]
 
 # write GIF animation
 fp = open("out.gif", "wb")
 gifmaker.makedelta(fp, frames)
 fp.close()
Fnord
  • 5,365
  • 4
  • 31
  • 48
blakev
  • 4,154
  • 2
  • 32
  • 52
2

I just encountered same problem. I solved it by making save_all=True. So you don't need to use gifmaker library anymore.