PIL-动画GIF,但有些帧是黑色的

时间:2011-07-11 07:00:34

标签: tkinter python-imaging-library gif

我一直在尝试使用Python中的PIL和Tkinter自动为聊天程序中的图像添加动画效果。有时他们会工作,但大多数时候他们没有。我将提供有效的图像和

的图像

基本上,我通过在GIF序列中的每个图像上调用ImageTk.PhotoImage来为图像设置动画,并通过root.after调用更新标签窗口小部件来运行动画。动画非常流畅

我的问题是,我尝试运行的大多数动画GIF都已损坏,或者其他东西。通常第一帧很好,但其余的都是完全黑色或充满了文物。

这些是图片:

这是少数几个有效之一: http://fc02.deviantart.net/fs42/f/2009/061/d/8/d856ba6223c66ce347c6c814f67d307b.gif

这些闪现黑色:

http://fc02.deviantart.net/fs70/f/2010/007/c/3/_mekolai__by_Pyritie.gif http://e.deviantart.com/emoticons/s/shakefist.gif

编辑:我看到没有人愿意帮助我。也许是因为它是tl;博士。我会尝试缩短它

一些代码:

def ExtHandler(self, widget, url): # sorts out what to do with each file extensions
    name = url.split('/')[-1].split('?')[0]
    path = './Storage/Temp/Images/'+name
    try:
        if name.endswith('.gif'):
            img = Image.open(path)
            animation = []
            x = 0
            print name
            while True:
                try:
                    img.seek(x)

                    newpath = './Storage/Temp/Images/{0}__{1}.png'.format(x, name.split('.', 1)[0])
                    img.save(newpath, transparency = img.info['transparency'], format='PNG')

                    newimg = Image.open(path)
                    newimg.load()
                    newimg = newimg.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)

                    dur = img.info['duration']
                    if dur < 50: dur = 50
                    newimg = Image.open(newpath)

                    animation.append((PhotoImage2(newimg), dur))
                    x += 1
                except EOFError:
                    break #no more images in the animation!
                except Exception as e:
                    print traceback.format_exc()
                    break
            if len(animation) > 1:
                self.animations[name] = animation

        elif name.endswith('.jpg'):
            img = Image.open(path)
            img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)

        elif name.endswith('.png'):
            img = Image.open(path)
            img.load()
            try:
                alpha = img.split()[3]
                img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
                mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0)
                img.paste(255, mask)
            except:
                img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)

        height, width = img.size[0], img.size[1]
        if width > 100 or height > 100:
            img = maxSize(img, (100, 100), Image.ANTIALIAS) # resize thumbnails

        self.images[name] = PhotoImage2(img)
        if name in self.animations:
            self.animation(name)
        else:
            self.update_frames(name, self.images[name])
    except:
        print name
        traceback.print_exc()

def animation(self, name):
    if name not in self.animations:
        return
    x = self.animations[name].pop(0)
    self.animations[name].append(x)
    img, time = x

    self.images[name] = img
    self.update_frames(name, self.images[name])
    self.root.after(time, lambda: self.animation(name))

2 个答案:

答案 0 :(得分:0)

有趣......我看到它们都是动画的。

我已将您的链接嵌入到此答案中,以便人们无需点击您的链接即可查看动画。

Works

Works

enter image description here

请注意,我使用chrome作为浏览器。我将保存此消息并查看它在Internet Explorer和FireFox中的外观,并报告结果。

...

<强>更新

好的,结果如下:

我在Windows XP上。

  • 适用于IE8
  • 适用于Chrome 10.0.648.205
  • 适用于Chrome 14.0.810.0
  • 适用于FireFox 5.0

所以,我不能在这里重现你的问题。我认为假设这些动画在人们的浏览器中按预期工作是相当安全的。

也许您应该添加一些有关如何查看动画的信息。

从技术角度来看,我没有看到问题,但动画看起来很便宜,所以在将它们添加到网站之前我会三思而后行,但这只是一种品味问题。

更新2 啊,我重读了你的问题。您没有使用浏览器,但是您正在创建应用程序。我确定问题出在您使用的库中。

也许你可以像Gif动画工作室或类似的程序那样打开GIF,看看它们之间的区别......也许你可以用它们全部工作的方式重新保存它们?

这就是我现在可以说的所有帮助你,我害怕。

答案 1 :(得分:0)

这是我的工作版本(用于将gif转换为一系列png):

import traceback
import Image

class Test:

    def __init__(self):
        self.ExtHandler("", "http://fc02.deviantart.net/fs42/f/2009/061/d/8/d856ba6223c66ce347c6c814f67d307b.gif")
        self.ExtHandler("", "http://fc02.deviantart.net/fs70/f/2010/007/c/3/_mekolai__by_Pyritie.gif")
        self.ExtHandler("", "http://e.deviantart.com/emoticons/s/shakefist.gif")

    def ExtHandler(self, widget, url): # sorts out what to do with each file extensions
        name = url.split('/')[-1].split('?')[0]
        path = 'C:\\Temp\\'+name
        try:
            if name.endswith('.gif'):
                img = Image.open(path)
                print name
                while True:
                    try:
                        x = img.tell() + 1
                        img.seek(x)

                        newpath = 'C:\\Temp\\{1}_{0}.png'.format(x, name.split('.', 1)[0])
                        img.save(newpath, transparency = img.info['transparency'])
                    except EOFError:
                        break #no more images in the animation!
                    except Exception as e:
                        print traceback.format_exc()
                        break

            elif name.endswith('.jpg'):
                img = Image.open(path)
                img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)

            elif name.endswith('.png'):
                img = Image.open(path)
                img.load()
                try:
                    alpha = img.split()[3]
                    img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
                    mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0)
                    img.paste(255, mask)
                except:
                    img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
        except:
            print name
            traceback.print_exc()

Test()

我认为解决方案是 a)用img.tell()+ 1寻找 b)在没有格式参数的情况下保存

在您的实际代码中,您可能不必将gif帧缓存为png。只需用img.tell()+ 1来寻求:)