PIL - Convert GIF Frames to JPG

gif, image-processing, jpeg, python, python-imaging-library

Solution

First of all, `JPEG` doesn't support transparency! But that's not the only problem.. As you move to the next frame of the `GIF` the `palette` information is lost (problem witn PIL?) - so `PIL` is unable to correctly convert to the `RGBA` framework (Hence the first frame is okish, but all the others are screwy). So the work-around is to add the `palette` back in for every frame, (which is what you were doing in your last code example, but your trouble was that you were saving as `RGB` not `RGBA` so you had no alpha/ transparency channel. Also you were doing a few unnecessary things..). Anyhow, here are the .png's with transparency and the corrected code, hope its of some use :)

import Image
import sys

def processImage(infile):
    try:
        im = Image.open(infile)
    except IOError:
        print "Cant load", infile
        sys.exit(1)
    i = 0
    mypalette = im.getpalette()

    try:
        while 1:
            im.putpalette(mypalette)
            new_im = Image.new("RGBA", im.size)
            new_im.paste(im)
            new_im.save('foo'+str(i)+'.png')

            i += 1
            im.seek(im.tell() + 1)

    except EOFError:
        pass # end of sequence

processImage('gif_example.gif')

Problem

I tried to convert an gif to single images with Python Image Library, but it results in weird frames The Input gif is: Source Image http://longcat.de/gif_example.gif In my first try, i tried to convert the image with Image.new to an RGB image, with 255,255,255 as white background - like in any other example i've found on the internet: ``` def processImage( infile ): try: im = Image.open( infile ) except IOError: print "Cant load", infile sys.exit(1) i = 0 try: while 1: background = Image.new("RGB", im.size, (255, 255, 255)) background.paste(im) background.save('foo'+str(i)+'.jpg', 'JPEG', quality=80) i += 1 im.seek( im.tell() + 1 ) except EOFError: pass # end of sequence ``` but it results in weird output files: Example #1 http://longcat.de/gif_example1.jpg My second try was, to convert the gif in an RGBA first, and then use its transparency mask, to make the transparent pieces white: ``` def processImage( infile ): try: im = Image.open( infile ) except IOError: print "Cant load", infile sys.exit(1) i = 0 try: while 1: im2 = im.convert('RGBA') im2.load() background = Image.new("RGB", im2.size, (255, 255, 255)) background.paste(im2, mask = im2.split()[3] ) background.save('foo'+str(i)+'.jpg', 'JPEG', quality=80) i += 1 im.seek( im.tell() + 1 ) except EOFError: pass # end of sequence ``` which results in an output like this: Example #2 http://longcat.de/gif_example2.jpg The advantage over the first try was, that the first frame looks pretty good But as you can see, the rest is broken What should i try next? Edit: I think i came a lot closer to the solution Example #3 http://longcat.de/gif_example3.png I had to use the palette of the first image for the other images, and merge it with the previous frame (for gif animations which use diff-images) ``` def processImage( infile ): try: im = Image.open( infile ) except IOError: print "Cant load", infile sys.exit(1) i = 0 size = im.size lastframe = im.convert('RGBA') mypalette = im.getpalette() try: while 1: im2 = im.copy() im2.putpalette( mypalette ) background = Image.new("RGB", size, (255,255,255)) background.paste( lastframe ) background.paste( im2 ) background.save('foo'+str(i)+'.png', 'PNG', quality=80) lastframe = background i += 1 im.seek( im.tell() + 1 ) except EOFError: pass # end of sequence ``` But i actually dont know, why my transparency is black, instead of white Even if i modify the palette (change the transparency channel to white) or use the transparency mask, the background is still black

Original source