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

发布于 2024-11-19 04:17:01 字数 3318 浏览 3 评论 0原文

我一直在尝试使用 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;dr.我会尝试缩短

一些代码:

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))

I've been trying to animate images inside a chat program automatically using PIL and Tkinter in Python. Sometimes they work, but most of the time they don't. I will provide images that work and ones that don't

Basically, I am animating the images by calling ImageTk.PhotoImage on each image in the GIF sequence, and the animations are run by updating the label widgets with a root.after call. The animation works pretty smoothly

My problem is, though, that most animated GIFs I try running are corrupted, or something. usually the first frame is fine, but the rest are either completely black or full of artifacts.

These are the images:

This one is one of the few that works:
http://fc02.deviantart.net/fs42/f/2009/061/d/8/d856ba6223c66ce347c6c814f67d307b.gif

These ones flash black:

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

EDIT: I see no one wants to help me. maybe it's because it's tl;dr. I'll try shortening it

some code:

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))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧竹 2024-11-26 04:17:01

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

我已将您的链接嵌入到此答案中,以便人们不必单击您的链接即可观看动画。

"Works"> Works

在此处输入图像描述

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

...

更新

好的,结果如下:

我使用的是 Windows XP。

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

所以,我无法在这里重现您的问题。我认为可以相当安全地假设这些动画将在人们的浏览器中按预期工作。

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

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

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

也许你可以在 Gif 动画工作室或类似的程序中打开 gif,看看有什么不同。也许你可以重新保存它们,让它们都能工作?

恐怕目前我能说的能帮助你的就这么多了。

Interesting.. I see them all animated.

I've embedded your links in this answer, so that people don't have to click your links to see the animations.

Works

Works

enter image description here

Note that I'm using chrome as a browser. I'll save this message and see how it looks in Internet explorer and FireFox, and report the results.

...

update

Ok, here are the results:

I'm on Windows XP.

  • Works with IE8
  • Works with Chrome 10.0.648.205
  • Works with Chrome 14.0.810.0
  • Works with FireFox 5.0

So, I cannot reproduce your problem here. I think it's fairly safe to assume that these animations will work as expected in people's browsers.

Maybe you should add some more information about how you view the animations.

From a technical point of view I don't see a problem, but the animations look sort of cheap, so I'd think twice before adding them to a site, but that's a matter of taste.

update 2
Ah, I reread your question. You're not using a browser, but you're creating an application. I'm sure that the problem lies in the libraries that you use.

Maybe you can open the gifs in something like Gif animation workshop or some program like that, to see the difference.. maybe you can re-save them in such a way that they all work?

That's about all I can say to help you for now I'm afraid.

澜川若宁 2024-11-26 04:17:01

这是我的工作版本(用于将 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 来寻找:)

This is my working version (for converting the gifs to a series of pngs):

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()

I think the solution is
a) seeking with img.tell() + 1
b) saving without the format parameter

In your actual code you probably don't have to cache the gif frames as pngs. Just seek with img.tell() + 1 :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文