Search code examples
pythonpython-imaging-librarytransparencyanimated-gif

Animated GIFs are only transparent on their first frame (Python PIL)


The following code creates a GIF from two images:

# GIFs are always palette images so they would be converted later anyway
im1 = PIL.Image.open('grin-emoji-by-twitter-rgba.png').convert('P')
im2 = PIL.Image.open('grin-emoji-by-twitter-rgba-2.png').convert('P')

im1.save('output.gif', save_all=True, append_images=[im2, im1, im2], loop=0, duration=200, transparency=255)

However the result is unexpectedly wrong. The first frame is fine, but subsequent frames contain a black rectangle around the updating region instead of transparency:

enter image description here

In my opinion the error is as follows: On the first image we specify the index 255 to be the index for completely transparent color. However the save function only seems to convert index 255 to transparency on the first frame, but skips this step on all other frames.

Is there any way to circumvent this?


Solution

  • As an alternative to my other answer, you can also just set the disposal value to 2:

    im1.save('output.gif', save_all=True, append_images=[im2, im1, im2], 
             loop=0, duration=200, transparency=255, disposal=2)
    

    Note that unlike my other answer this does not work 100% of the time, as the transparency channel can jump around to other indexes. :-/ This only seems to happen in longer GIFs with many colors in them however.

    Left: This answer, Right: Other answer with manual alignment

    example of bug persisting example of bug fixed

    Edit: Here it's claimed this got fixed in newer versions of pillow! (I think 8.1.2+)