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.
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 :)
精彩评论