Python 使用Tkinter的动画gif中没有透明度
我想用Tkinter显示动画gif。我尝试使用提出的解决方案 问题是在我的gif中,只有第一帧是完整的。所有其他帧都由一个几乎透明的区域组成,其中只有少数改变w.r.t的像素。前一帧是不透明的 我能告诉Tkinter这些帧的背景应该是透明的吗Python 使用Tkinter的动画gif中没有透明度,python,tkinter,transparency,animated-gif,Python,Tkinter,Transparency,Animated Gif,我想用Tkinter显示动画gif。我尝试使用提出的解决方案 问题是在我的gif中,只有第一帧是完整的。所有其他帧都由一个几乎透明的区域组成,其中只有少数改变w.r.t的像素。前一帧是不透明的 我能告诉Tkinter这些帧的背景应该是透明的吗 from Tkinter import * from PIL import Image, ImageTk class MyLabel(Label): def __init__(self, master, filename):
from Tkinter import *
from PIL import Image, ImageTk
class MyLabel(Label):
def __init__(self, master, filename):
im = Image.open(filename)
seq = []
try:
while 1:
seq.append(im.copy())
im.seek(len(seq)) # skip to next frame
except EOFError:
pass # we're done
try:
self.delay = im.info['duration']
except KeyError:
self.delay = 100
first = seq[0].convert('RGBA')
self.frames = [ImageTk.PhotoImage(first)]
Label.__init__(self, master, image=self.frames[0])
temp = seq[0]
for image in seq[1:]:
temp.paste(image)
frame = temp.convert('RGBA')
self.frames.append(ImageTk.PhotoImage(frame))
self.idx = 0
self.cancel = self.after(self.delay, self.play)
def play(self):
self.config(image=self.frames[self.idx])
self.idx += 1
if self.idx == len(self.frames):
self.idx = 0
self.cancel = self.after(self.delay, self.play)
root = Tk()
anim = MyLabel(root, 'animated.gif')
anim.pack()
def stop_it():
anim.after_cancel(anim.cancel)
Button(root, text='stop', command=stop_it).pack()
root.mainloop()
看起来您需要为粘贴操作提供掩码:
from Tkinter import *
from PIL import Image, ImageTk
class MyLabel(Label):
def __init__(self, master, filename):
im = Image.open(filename)
seq = []
try:
while 1:
seq.append(im.copy())
im.seek(len(seq)) # skip to next frame
except EOFError:
pass # we're done
try:
self.delay = im.info['duration']
except KeyError:
self.delay = 100
first = seq[0].convert('RGBA')
self.frames = [ImageTk.PhotoImage(first)]
Label.__init__(self, master, image=self.frames[0])
lut = [1] * 256
lut[im.info["transparency"]] = 0
temp = seq[0]
for image in seq[1:]:
mask = image.point(lut, "1")
# point() is used to map image pixels into mask pixels
# via the lookup table (lut), creating a mask
# with value 0 at transparent pixels and
# 1 elsewhere
temp.paste(image, None, mask) #paste with mask
frame = temp.convert('RGBA')
self.frames.append(ImageTk.PhotoImage(frame))
self.idx = 0
self.cancel = self.after(1000, self.play)
def play(self):
self.config(image=self.frames[self.idx])
self.idx += 1
if self.idx == len(self.frames):
self.idx = 0
self.cancel = self.after(self.delay, self.play)
root = Tk()
anim = MyLabel(root, 'tumblr_m3i10ma4fI1qe0eclo1_r9_500.gif')
anim.pack()
def stop_it():
anim.after_cancel(anim.cancel)
Button(root, text='stop', command=stop_it).pack()
root.mainloop()
我不明白你在问什么。在某一点上,你说除了改变的像素外,所有的东西都是透明的,然后你问如何使背景透明。这是如何结合在一起的?另外,你可以链接到一个动画,透明的gif进行测试,这样我们就不必自己搜索了吗?以这个gif为例:像素应该是透明的。但是当我用TKinter加载单个帧时,透明像素只是黑色的。我想我必须告诉Tkinter,在某一点上,帧中某一颜色的所有像素都应该是透明的。我自己就试过了。对于GIF,我看到了同样的问题,除了“透明”像素不是黑色,而是标签的
bg
,因此“主”帧似乎在此处被覆盖(但保留在边框处)。另外,当我用GIMP(一个带有透明背景的简单旋转十字)创建一个简单的动画GIF时,效果很好,但是在第一帧不透明的情况下(就像你的例子),我又遇到了同样的问题。我的猜测是,Tkinter不是将图像堆叠在一起,而是替换新的部分,即没有“累积”模式。是的,我也这么想。这可能是Panel小部件的一个限制。我现在正在尝试使用画布小部件,但迄今为止没有成功。也许你可以在画布上绘制第一帧,然后在画布上绘制其他帧,也就是说,不替换第一帧。