5

When I try to use fraxel's answer on

http://stackoverflow.com/questions/10269099/pil-convert-gif-frames-to-jpg

on the image http://24.media.tumblr.com/fffcc2d8e980fbba4f87d51ed4916b87/tumblr_mh8uaqMo2I1rkp3avo2_250.gif

I get ok data for some, but then for some I get missing data it looks like, e.g.

Correct

Correct_1 Correct_2

Missing

Missing_1 enter image description here

To display these I use imagemagick's display foo* and then use space to move through the images ... is it possible imagemagick is reading them wrong?

Edit:

Even when using convert and then displaying via display foo* I get the following

enter image description here enter image description here enter image description here enter image description here

Could this be a characteristic of the gif then?

Community
  • 1
  • 1
Eiyrioü von Kauyf
  • 4,481
  • 7
  • 32
  • 41
  • It seems that each frame does not contains data that does not change from previous frame, kind of compression, so it's not a bug, it's a feature. – Julien Palard Jan 27 '13 at 17:51
  • From the Imagemagick website:OptimizeTransparency Given a GIF animation, replace any pixel in the sub-frame overlay images with transparency. Given a GIF animation, replace any pixel in the sub-frame overlay images with transparency, if it does not change the resulting animation by more than the current -fuzz factor. This should allow a existing frame optimized GIF animation to compress into a smaller file size due to larger areas of one (transparent) color rather than a pattern of multiple colors repeating the current disposed image of the last frame. – Bonzo Jan 27 '13 at 21:52

2 Answers2

3

If you can stick to ImageMagick then it is very simple to solve this:

convert input.gif -coalesce output.png

Otherwise, you will have to consider the different forms of how each GIF frame can be constructed. For this specific type of GIF, and also the other one shown in your other question, the following code works (note that in your earlier question, the accepted answer doesn't actually make all the split parts transparent -- at least with the latest released PIL):

import sys
from PIL import Image, ImageSequence

img = Image.open(sys.argv[1])

pal = img.getpalette()
prev = img.convert('RGBA')
prev_dispose = True
for i, frame in enumerate(ImageSequence.Iterator(img)):
    dispose = frame.dispose

    if frame.tile:
        x0, y0, x1, y1 = frame.tile[0][1]
        if not frame.palette.dirty:
            frame.putpalette(pal)
        frame = frame.crop((x0, y0, x1, y1))
        bbox = (x0, y0, x1, y1)
    else:
        bbox = None

    if dispose is None:
        prev.paste(frame, bbox, frame.convert('RGBA'))
        prev.save('foo%02d.png' % i)
        prev_dispose = False
    else:
        if prev_dispose:
            prev = Image.new('RGBA', img.size, (0, 0, 0, 0))
        out = prev.copy()
        out.paste(frame, bbox, frame.convert('RGBA'))
        out.save('foo%02d.png' % i)

Ultimately you will have to recreate what -coalesce does, since it is likely that the code above may not work with certain GIF images.

mmgp
  • 18,901
  • 3
  • 53
  • 80
-1

You should try keeping the whole history of frames in "background", instead of :

background = Image.new("RGB", size, (255,255,255))
background.paste( lastframe )
background.paste( im2 )

Just create the "background" once before the loop, then only paste() frame on it, it should work.

Julien Palard
  • 8,736
  • 2
  • 37
  • 44
  • can you elaborate - paste overwrites all previous data from what I see as in it puts white on top of the previous data... – Eiyrioü von Kauyf Jan 27 '13 at 23:14
  • I don't think it's white, I think it's transparent, so it stack correctly, generating a new image stacking only changes on the top the stack of images. – Julien Palard Jan 29 '13 at 17:09
  • so pasting iirc overwrites all previous data... why would i paste things on top ...? – Eiyrioü von Kauyf Jan 29 '13 at 18:43
  • @EiyrioüvonKauyf the idea here is nearly correct for the single GIF presented, it just needs to be a little more careful to use a RGBA frame as the mask. Using `paste` is fine here, you want to overwrite the possibly transparent areas (see the other answer). – mmgp Jan 29 '13 at 19:23
  • @mmgp yes... how does this do that. I understand how the other answer does that .. not sure what I'm missing here. Can you elaborate please? – Eiyrioü von Kauyf Jan 30 '13 at 02:09
  • @EiyrioüvonKauyf in the last comment I said "... the idea here is nearly correct ...", so it doesn't, but almost does. – mmgp Jan 30 '13 at 02:10