开发者

PIL- animating GIFs, but some frames are black

开发者 https://www.devze.com 2023-03-19 02:22 出处:网络
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

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, lambd开发者_开发问答a: self.animation(name))


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.

PIL- animating GIFs, but some frames are black

PIL- animating GIFs, but some frames are black

PIL- animating GIFs, but some frames are black

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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号