I'm trying to convert a list of PNG images with a transparent background to a GIF, while keeping the background transparency. I took this bit of code I found, and adapted it:
import os
from PIL import Image
# Create the frames
frames = []
path = "directory/to/my/png/images"
for frame in os.listdir(path):
new_frame = Image.open(path + "/" + frame)
frames.append(new_frame)
# Save into a GIF file
frames[0].save(path + "/../output/animation.gif", format='GIF',
append_images=frames[1:],
save_all=True,
duration=41, loop=1, transparency=0)
It is opening all the PNG images I have in a folder, and export them to a GIF, but the background is black. I have looked at the PIL documentation, but I don't seem to understand how the transparency
parameter works, or I think I am using it wrong.
First of all, the GIF format does not support alpha-channel transparency like PNG does. You can only select one out of the 256 possible colors in a GIF to be transparent. So, you also don't get any smooth transparencies, pixels are either fully transparent or opaque.
When dealing with Image
objects having mode RGBA
, try to convert all your images to mode PA
before saving. Maybe, that helps automagically.
Let's assume we have the following three images:
Your minimized code would look like this:
from PIL import Image
frames = [Image.open('red.png'), Image.open('green.png'), Image.open('blue.png')]
frames[0].save('test.gif', format='GIF',
append_images=frames[1:],
save_all=True,
duration=200, loop=0, transparency=0)
The resulting GIF in fact doesn't reflect the transparency from the single PNGs, the GIF is totally corrupted:
Adding the conversion to mode PA
, the code might look like this:
from PIL import Image
frames = [Image.open('red.png'), Image.open('green.png'), Image.open('blue.png')]
frames = [frame.convert('PA') for frame in frames]
frames[0].save('test.gif', format='GIF',
append_images=frames[1:],
save_all=True,
duration=200, loop=0, transparency=0)
And, the result is fine, transparency is maintained:
I don't know, if that route works for arbitrary PNGs, but it's worth testing with your images, isn't it? If that doesn't work, you need to provide some of your input images for further testing.
The final approach could be to replace all transparent pixels in your PNGs with a certain color, let's say solid yellow. When saving the GIF later, you'd need to make sure, that all images' palettes store that solid yellow at the same index, and then finally set transparency
to that index.
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.9.1
Pillow: 8.1.0
----------------------------------------