问题
tkinter显示GIF一般有两种方式。
- 一是使用tkinter自带的函数PhotoImage。可以直接显示透明原图,缺点是需要设置图像的帧数,太多了会报错,太少了缺少数据,显示效果不好。图像的大小也无法改变。
index = 6
PhotoImage(file='GIF.gif',format='gif -index %i'%index)
- 二是使用PIL库的函数。优点是图像处理很方便,也可以自动读取所有的图像帧,缺点是PIL默认把GIF透明背景改成了白色,结果就是原图无法完美显示。
from PIL import Image, ImageTk, ImageSequence
self.gif_flame_list = [[ImageTk.PhotoImage(im) for im in ImageSequence.Iterator(Image.open(path+'/'+gif))] for gif in self.gif_name_list]
目的
使用方法二,既能修改图像尺寸,又可以显示透明GIF图像。
代码
找了很多资料,要么没提到这个问题;要么使用方法一,严格要求GIF图像的尺寸和帧率;甚至有的博客瞎写,没有验证可行性。
最后是问了ChatGPT,改过来的,记录一下。
# python
import tkinter as tk
from PIL import Image, ImageTk
def update_image(index):
global img_label, frames
img = frames[index]
img_label.configure(image=img)
img_label.image = img
root.after(100, update_image, (index + 1) % len(frames))
root = tk.Tk()
root.title("Transparent GIF Animation")
gif_path = "path/to/your/transparent.gif"
gif = Image.open(gif_path)
frames = []
try:
for i in range(gif.n_frames):
gif.seek(i)
frame = gif.copy()
# 使用convert方法,将背景颜色设置为透明
frame = frame.convert("RGBA", palette=Image.ADAPTIVE, colors=256)
frames.append(ImageTk.PhotoImage(frame))
except Exception as e:
print("Error loading frames:", e)
exit()
img_label = tk.Label(root)
img_label.pack()
update_image(0)
root.mainloop()
在这个例子中,使用convert方法将图像转换为RGBA模式,并将palette参数设置为Image.ADAPTIVE,colors参数设置为256。这样可以确保透明通道被正确处理,并且图像的背景颜色保持透明。确保将"path/to/your/transparent.gif"替换为你的透明GIF文件的路径。
def load_gif_data(self):
self.gif_name_list = [n for n in os.listdir(self.pet_config['source'])]
print(self.gif_name_list)
# self.delay = im.info['duration'] # 获取GIF的帧延迟时间(毫秒)
# # 使用PIL
# 使用convert方法,将背景颜色设置为透明
# frame = frame.convert("RGBA", palette=Image.ADAPTIVE, colors=256)
self.gif_flame_list = [[ImageTk.PhotoImage(im.convert("RGBA", palette=Image.ADAPTIVE, colors=256)) for im in ImageSequence.Iterator(Image.open(self.pet_config['source']+'/'+gif))] for gif in self.gif_name_list]
# 使用 tkinter.PhotoImage
# self.gif_flame_list = [[tk.PhotoImage(file=self.pet_config['source'] + '/' + gif,format='gif -index %i'%(i)) for i in range(2)] for gif in self.gif_name_list]