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

3
我一直在尝试使用Python中的PIL和Tkinter自动地在聊天程序内部对图像进行动画处理。有时它们能够正常工作,但大多数情况下都不能。我将提供可用和不可用的图像。
基本上,我通过对GIF序列中的每个图像调用ImageTk.PhotoImage来制作动画,并通过更新标签小部件来运行动画。动画效果非常流畅。
然而,我的问题是,我尝试运行的大多数动态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
编辑:我看到没有人想帮助我。也许是因为它太长了。我会尝试缩短它。
一些代码:
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
这是我正在使用的版本(用于将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进行查找即可 :)


我想我找到了问题所在。我在保存图像后立即打开它们,我认为这可能会在I/O级别上出现故障。我将其改为循环两次:一次保存所有内容,并将所有路径和动画持续时间添加到列表中,第二个循环遍历该路径列表并打开它们。这起作用了。 - Blazer

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文件,以查看差异...也许您可以以这样的方式重新保存它们,使它们都能正常工作?

这就是我现在能为您提供的所有帮助了,恐怕没有更多了。


我正在使用Python中的PIL和Tkinter。抱歉,我没有意识到当我重新编辑我的问题时删除了那些信息。 - Blazer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接