Потеря данных при извлечении кадров из GIF в PNG?

Когда я пытаюсь использовать ответ fraxel на

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

на изображении http://24.media.tumblr.com/fffcc2d8e980fbba4f87d51ed4916b87/tumblr_mh8uaqMo2I1rkp3avo2_250.gif

Я получаю данные ok для некоторых, но затем для некоторых я получаю отсутствующие данные, это похоже, например.

Правильный

Correct_1Correct_2

Отсутствует

Missing_1enter image description here

Чтобы отобразить их, я использую imagemagick display foo*, а затем использую пространство для перемещения по изображениям... возможно ли, что imagemagick читает их неправильно?

Изменить:

Даже при использовании преобразования и последующего отображения через display foo* я получаю следующее

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

Может ли это быть характеристикой gif тогда?

Ответ 1

Если вы можете придерживаться ImageMagick, то это очень просто решить:

convert input.gif -coalesce output.png

В противном случае вам нужно будет рассмотреть различные формы того, как можно построить каждый кадр GIF. Для этого конкретного типа GIF, а также другого, показанного в вашем другом вопросе, работает следующий код (обратите внимание, что в вашем предыдущем вопросе принятый ответ фактически не делает все частичные части прозрачными - по крайней мере, с последними выпущен 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)

В конечном итоге вам придется воссоздать то, что делает -coalesce, так как вполне вероятно, что указанный выше код может не работать с определенными изображениями GIF.

Ответ 2

Вы должны попытаться сохранить всю историю кадров в "background", а не:

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

Просто создайте "фон" один раз перед циклом, а затем на него вставьте только рамку paste(), он должен работать.