Python實現(xiàn)播放gif動圖文件工具(增強版)
使用Python實現(xiàn)播放“.gif”文件增強版
使用Python和第三方庫Pillow實現(xiàn)實現(xiàn)播放gif文件,以前介紹過一個簡單實現(xiàn),那個功能比較簡單,實用意義不大?,F(xiàn)在介紹一個增強版的。
關(guān)于“.gif”文件
GIF(Graphics Interchange Format,圖形交換格式)是一種由CompuServe公司開發(fā)的圖像格式,通過連續(xù)幀實現(xiàn)動畫效果,文件體積小且畫面連貫 。GIF本質(zhì)是靜態(tài)圖片的無損壓縮格式,雖支持動畫效果,但缺乏音頻流且色彩深度有限(僅8位)。
下面介紹用Python實現(xiàn)的控制播放器,用戶可細致的控制,包括:打開、播放、暫停、停止,設置播放速度,逐幀控制——前一幀、后一幀。
界面截圖:

打開:停止當前播放,加載新GIF文件。
播放:啟動動畫循環(huán)。
暫停:停止動畫循環(huán)。
停止:暫停播放并重置到第一幀。
前一幀:允許用戶逐步后退到前一幀,自動暫停播放。
后一幀:允許用戶逐步前進到后一幀,自動暫停播放。
循環(huán)處理,當?shù)竭_第一幀時后退會跳轉(zhuǎn)到最后一幀,反之亦然。
滑動條控制:添加了速度滑動條,允許用戶在10ms到500ms之間調(diào)整幀延遲。
使用GIF原始速度:可以自動設置GIF的原始平均延遲時間。
狀態(tài)欄:顯示播放中還是暫停狀態(tài),當前設置的延遲時間,顯示當前幀位置和總幀數(shù)(例如:"幀 5/24"),當前設置的幀延遲時間。
這個GIF播放器基于以下三個核心庫構(gòu)建:
Tkinter - Python的標準GUI庫,用于創(chuàng)建窗口、按鈕等界面元素。
PIL/Pillow - Python圖像處理庫,用于讀取和處理GIF文件。
tkinter.filedialog - 文件選擇對話框,用于選擇GIF文件。
源碼如下:
import tkinter as tk
from tkinter import filedialog, ttk
from PIL import Image, ImageTk
class GifPlayer:
def __init__(self, master):
self.master = master
self.master.title("GIF Player")
self.master.geometry("500x550") # 增加高度以容納新控件 ☆
#self.master.minsize(400, 450)
# 初始化變量
self.frames = [] # 存儲GIF的所有幀
self.current_frame = 0 # 當前幀索引
self.is_playing = False # 播放狀態(tài)
self.gif_image = None # PIL Image對象
self.frame_delay = 100 # 默認幀延遲(毫秒)
self.original_delays = [] # 存儲原始GIF幀延遲
# 創(chuàng)建主框架,用于管理布局
main_frame = tk.Frame(self.master)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 創(chuàng)建顯示GIF的標簽
self.label = tk.Label(main_frame, text="請打開一個GIF文件", bg="white",
relief=tk.SUNKEN, bd=1)
self.label.pack(fill=tk.BOTH, expand=True)
# 創(chuàng)建狀態(tài)顯示標簽
self.status_label = tk.Label(main_frame, text="狀態(tài): 未加載", relief=tk.SUNKEN, bd=1)
self.status_label.pack(fill=tk.X, pady=(5, 0))
# 創(chuàng)建控制面板框架
control_frame = tk.Frame(main_frame)
control_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=10)
# 基本控制部分
basic_control_frame = tk.Frame(control_frame)
basic_control_frame.pack(fill=tk.X, pady=5)
# 打開按鈕
self.open_button = tk.Button(basic_control_frame, text="打開", command=self.open_gif)
self.open_button.pack(side=tk.LEFT, padx=5)
# 播放按鈕
self.play_button = tk.Button(basic_control_frame, text="播放", command=self.play_gif)
self.play_button.pack(side=tk.LEFT, padx=5)
# 暫停按鈕
self.pause_button = tk.Button(basic_control_frame, text="暫停", command=self.pause_gif)
self.pause_button.pack(side=tk.LEFT, padx=5)
# 停止按鈕
self.stop_button = tk.Button(basic_control_frame, text="停止", command=self.stop_gif)
self.stop_button.pack(side=tk.LEFT, padx=5)
# 前一幀按鈕
self.prev_frame_button = tk.Button(basic_control_frame, text="前一幀", command=self.prev_frame)
self.prev_frame_button.pack(side=tk.LEFT, padx=5)
# 后一幀按鈕
self.next_frame_button = tk.Button(basic_control_frame, text="后一幀", command=self.next_frame)
self.next_frame_button.pack(side=tk.LEFT, padx=5)
# 速度控制部分
speed_control_frame = tk.Frame(control_frame)
speed_control_frame.pack(fill=tk.X, pady=5)
# 速度標簽
tk.Label(speed_control_frame, text="速度:").pack(side=tk.LEFT, padx=5)
# 速度滑動條
self.speed_scale = tk.Scale(
speed_control_frame,
from_=10, to=500,
orient=tk.HORIZONTAL,
showvalue=False, # 不顯示默認數(shù)值False, 否者用 True
command=self.set_speed
)
self.speed_scale.set(self.frame_delay) # 設置初始值
self.speed_scale.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
# 使用原始延遲按鈕
self.use_original_delay_button = tk.Button(
speed_control_frame,
text="使用GIF原始速度",
command=self.use_original_delay
)
self.use_original_delay_button.pack(side=tk.LEFT, padx=5)
# 初始化按鈕狀態(tài)
self.update_button_state()
def open_gif(self):
"""打開文件對話框選擇GIF文件并加載"""
# 打開文件對話框,只顯示GIF文件
file_path = filedialog.askopenfilename(
title="選擇GIF文件",
filetypes=[("GIF文件", "*.gif"), ("所有文件", "*.*")]
)
# 如果用戶選擇了文件
if file_path:
# 停止當前播放
self.stop_gif()
try:
# 打開新的GIF文件
self.gif_image = Image.open(file_path)
# 獲取屏幕尺寸,用于限制GIF顯示大小
screen_width = self.master.winfo_screenwidth()
screen_height = self.master.winfo_screenheight()
# 設置最大顯示尺寸(留出空間給窗口邊框和按鈕)
max_width = int(screen_width * 0.7)
max_height = int(screen_height * 0.7) # ☆
# 提取所有幀和原始延遲
self.frames = []
self.original_delays = []
try:
for frame in range(self.gif_image.n_frames):
self.gif_image.seek(frame) # 定位到指定幀
# 獲取幀延遲時間(毫秒)
delay = self.gif_image.info.get('duration', 100)
self.original_delays.append(delay)
frame_image = self.gif_image.copy().convert("RGBA") # 復制并轉(zhuǎn)換幀
# 如果GIF尺寸過大,則進行縮放
if frame_image.width > max_width or frame_image.height > max_height:
# 計算縮放比例,保持寬高比
ratio = min(max_width / frame_image.width, max_height / frame_image.height)
new_width = int(frame_image.width * ratio)
new_height = int(frame_image.height * ratio)
frame_image = frame_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
photo = ImageTk.PhotoImage(frame_image) # 轉(zhuǎn)換為Tkinter可用的格式
self.frames.append(photo)
except EOFError:
pass # 處理幀讀取完畢的情況
# 重置當前幀索引
self.current_frame = 0
# 顯示第一幀
if self.frames:
self.label.config(image=self.frames[0], text="")
# 調(diào)整窗口大小以適應GIF,但不超過最大尺寸
img_width = self.frames[0].width()
img_height = self.frames[0].height()
# 設置窗口大小,考慮按鈕區(qū)域
window_width = min(img_width + 50, max_width)
window_height = min(img_height + 150, max_height) # 增加高度以容納新控件 ☆
self.master.geometry(f"{window_width}x{window_height}")
# 更新窗口標題顯示文件名
self.master.title(f"GIF Player - {file_path.split('/')[-1]}")
# 更新狀態(tài)顯示
self.update_status()
# 更新按鈕狀態(tài)
self.update_button_state()
except Exception as e:
# 如果加載失敗,顯示錯誤信息
self.label.config(image="", text=f"無法加載GIF文件:\n{str(e)}")
self.frames = []
self.update_button_state()
self.status_label.config(text="狀態(tài): 加載失敗")
def update_button_state(self):
"""根據(jù)當前狀態(tài)更新按鈕的可用性"""
has_frames = len(self.frames) > 0
# 只有在有幀的情況下,播放、暫停和停止按鈕才可用
self.play_button.config(state=tk.NORMAL if has_frames else tk.DISABLED)
self.pause_button.config(state=tk.NORMAL if has_frames else tk.DISABLED)
self.stop_button.config(state=tk.NORMAL if has_frames else tk.DISABLED)
self.prev_frame_button.config(state=tk.NORMAL if has_frames else tk.DISABLED)
self.next_frame_button.config(state=tk.NORMAL if has_frames else tk.DISABLED)
self.speed_scale.config(state=tk.NORMAL if has_frames else tk.DISABLED)
self.use_original_delay_button.config(state=tk.NORMAL if has_frames else tk.DISABLED)
def update_status(self):
"""更新狀態(tài)顯示"""
if self.frames:
status = f"狀態(tài): 幀 {self.current_frame+1}/{len(self.frames)}"
if self.is_playing:
status += " - 播放中"
else:
status += " - 暫停"
status += f" - 延遲: {self.frame_delay}ms"
self.status_label.config(text=status)
else:
self.status_label.config(text="狀態(tài): 未加載")
def set_speed(self, value):
"""設置播放速度"""
self.frame_delay = int(value)
self.update_status()
def use_original_delay(self):
"""使用GIF的原始延遲時間"""
if self.frames and self.original_delays:
# 計算平均延遲
avg_delay = sum(self.original_delays) // len(self.original_delays)
self.frame_delay = avg_delay
self.speed_scale.set(avg_delay)
self.update_status()
def play_gif(self):
"""開始播放GIF動畫"""
if not self.is_playing and self.frames:
self.is_playing = True
self.update_status()
self.play_next_frame() # 開始播放循環(huán)
def pause_gif(self):
"""暫停播放GIF動畫"""
self.is_playing = False
self.update_status()
def stop_gif(self):
"""停止播放GIF動畫并回到第一幀"""
self.is_playing = False
if self.frames:
self.current_frame = 0
self.label.config(image=self.frames[self.current_frame])
self.update_status()
def prev_frame(self):
"""顯示前一幀"""
if self.frames:
self.is_playing = False
self.current_frame = (self.current_frame - 1) % len(self.frames)
self.label.config(image=self.frames[self.current_frame])
self.update_status()
def next_frame(self):
"""顯示后一幀"""
if self.frames:
self.is_playing = False
self.current_frame = (self.current_frame + 1) % len(self.frames)
self.label.config(image=self.frames[self.current_frame])
self.update_status()
def play_next_frame(self):
"""播放下一幀并設置定時器播放后續(xù)幀"""
if self.is_playing and self.frames:
# 顯示當前幀
self.label.config(image=self.frames[self.current_frame])
# 更新到下一幀(循環(huán)播放)
self.current_frame = (self.current_frame + 1) % len(self.frames)
# 更新狀態(tài)顯示
self.update_status()
# 設置定時器,使用當前延遲時間播放下一幀
self.master.after(self.frame_delay, self.play_next_frame)
if __name__ == "__main__":
# 創(chuàng)建主窗口并啟動GIF播放器
root = tk.Tk()
player = GifPlayer(root)
root.mainloop()
以上就是Python實現(xiàn)播放gif動圖文件工具(增強版)的詳細內(nèi)容,更多關(guān)于Python播放gif動圖的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Python進行同期群分析(Cohort?Analysis)
同期群(Cohort)的字面意思(有共同特點或舉止類同的)一群人,比如不同性別,不同年齡。這篇文章主要介紹了用Python語言來進行同期群分析,感興趣的同學可以閱讀參考一下本文2023-03-03
flask的orm框架SQLAlchemy查詢實現(xiàn)解析
這篇文章主要介紹了flask的orm框架SQLAlchemy查詢實現(xiàn)解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12
Python+wxPython實現(xiàn)合并多個文本文件
在?Python?編程中,我們經(jīng)常需有時候,我們可能需要將多個文本文件合并成一個文件,要處理文本文件,本文就來介紹下如何使用?wxPython?模塊編寫一個簡單的程序,能夠讓用戶選擇多個文本文件,感興趣的可以了解下2023-08-08
Django框架cookie和session方法及參數(shù)設置
這篇文章主要為大家介紹了Django框架cookie和session參數(shù)設置及介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-03-03

