使用Python制作GIF動(dòng)圖并打包為exe可執(zhí)行程序
使用 Python 制作 GIF 動(dòng)圖,并打包為 EXE 可執(zhí)行程序(含圖形界面)
在工作或個(gè)人項(xiàng)目中,常常會(huì)遇到需要將多張圖片合成 GIF 動(dòng)圖的需求,同時(shí)添加版權(quán)水印保護(hù)作品。本文分享一個(gè)使用 Python 和 Pillow 庫(kù)實(shí)現(xiàn)的 GIF 生成工具,配備簡(jiǎn)單的 Tkinter 圖形界面,支持:
- 批量上傳圖片,合成 GIF 動(dòng)圖
- 固定文字水印自動(dòng)添加
- 可選圖片水?。↙ogo)疊加
- 一鍵生成,操作簡(jiǎn)單
- 使用 PyInstaller 打包為 Windows 獨(dú)立 EXE
無(wú)論你是 Python 初學(xué)者,還是想快速做一個(gè)實(shí)用小工具,這篇文章都會(huì)幫你搞定。
環(huán)境準(zhǔn)備
Python 3.6+
Pillow:圖像處理庫(kù),安裝命令:
pip install pillow
- Tkinter:Python 內(nèi)置圖形界面庫(kù)(Windows 下默認(rèn)包含)
- PyInstaller:后續(xù)將介紹如何打包
功能預(yù)覽
| 功能 | 說(shuō)明 |
|---|---|
| 多圖片上傳 | 支持多選 PNG/JPG/JPEG/BMP 等常見(jiàn)格式 |
| GIF 動(dòng)畫(huà)生成 | 支持循環(huán)播放,幀間隔可自定義 |
| 簡(jiǎn)潔圖形界面 | 按鈕操作:選擇圖片、生成 GIF |
| 一鍵生成 | 直接點(diǎn)擊按鈕即可生成 |
| EXE 打包 | 使用 PyInstaller 一鍵打包,免 Python 環(huán)境 |
完整代碼(圖形界面 + 功能)
gif_creator.py
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from PIL import Image, ImageTk
import os
import threading
import webbrowser
class GifMakerApp:
def __init__(self, root):
self.root = root
self.root.title("GIF 動(dòng)圖生成器")
self.image_paths = []
self.build_ui()
def build_ui(self):
# 圖片列表框
self.listbox = tk.Listbox(self.root, selectmode=tk.SINGLE, width=50, height=8)
self.listbox.grid(row=0, column=0, columnspan=3, padx=10, pady=5)
# 上移/下移按鈕
tk.Button(self.root, text="↑ 上移", command=self.move_up).grid(row=1, column=0, sticky="ew", padx=10)
tk.Button(self.root, text="↓ 下移", command=self.move_down).grid(row=1, column=1, sticky="ew", padx=10)
# 選擇圖片
tk.Button(self.root, text="選擇圖片", command=self.select_images).grid(row=2, column=0, columnspan=2, pady=5)
# 幀間隔時(shí)間
tk.Label(self.root, text="幀間隔 (ms):").grid(row=3, column=0, sticky="e")
self.duration_var = tk.IntVar(value=1000)
tk.Entry(self.root, textvariable=self.duration_var, width=8).grid(row=3, column=1, sticky="w")
# 選擇保存路徑
tk.Button(self.root, text="保存路徑", command=self.choose_output_path).grid(row=4, column=0, pady=5)
self.output_path_var = tk.StringVar(value="output.gif")
tk.Entry(self.root, textvariable=self.output_path_var, width=30).grid(row=4, column=1)
# 進(jìn)度條
self.progress = ttk.Progressbar(self.root, orient="horizontal", length=300, mode="determinate")
self.progress.grid(row=5, column=0, columnspan=3, pady=5)
# 生成按鈕
tk.Button(self.root, text="生成 GIF", command=self.generate_gif_thread).grid(row=6, column=0, columnspan=3, pady=10)
def select_images(self):
file_paths = filedialog.askopenfilenames(
title="選擇多張圖片",
filetypes=[("圖片文件", "*.png *.jpg *.jpeg *.bmp")]
)
if file_paths:
self.image_paths = list(file_paths)
self.refresh_listbox()
def refresh_listbox(self):
self.listbox.delete(0, tk.END)
for path in self.image_paths:
self.listbox.insert(tk.END, os.path.basename(path))
def move_up(self):
index = self.listbox.curselection()
if not index or index[0] == 0:
return
idx = index[0]
self.image_paths[idx-1], self.image_paths[idx] = self.image_paths[idx], self.image_paths[idx-1]
self.refresh_listbox()
self.listbox.select_set(idx-1)
def move_down(self):
index = self.listbox.curselection()
if not index or index[0] == len(self.image_paths) - 1:
return
idx = index[0]
self.image_paths[idx+1], self.image_paths[idx] = self.image_paths[idx], self.image_paths[idx+1]
self.refresh_listbox()
self.listbox.select_set(idx+1)
def choose_output_path(self):
path = filedialog.asksaveasfilename(
defaultextension=".gif",
filetypes=[("GIF 文件", "*.gif")],
title="選擇 GIF 保存路徑"
)
if path:
self.output_path_var.set(path)
def generate_gif_thread(self):
t = threading.Thread(target=self.generate_gif)
t.start()
def generate_gif(self):
if not self.image_paths:
messagebox.showwarning("未選擇圖片", "請(qǐng)先選擇圖片!")
return
try:
duration = int(self.duration_var.get())
except ValueError:
messagebox.showerror("無(wú)效間隔", "請(qǐng)輸入合法的幀間隔(整數(shù))")
return
output_path = self.output_path_var.get().strip()
if not output_path:
messagebox.showerror("路徑錯(cuò)誤", "請(qǐng)輸入有效的保存路徑")
return
try:
frames = []
self.progress["maximum"] = len(self.image_paths)
self.progress["value"] = 0
from PIL import ImageFont, ImageDraw
# ...在循環(huán)中每次讀取圖片時(shí)
for idx, path in enumerate(self.image_paths):
img = Image.open(path).convert("RGBA")
if idx == 0:
w, h = img.size
else:
img = img.resize((w, h))
# 添加水印
draw = ImageDraw.Draw(img)
text = "@ CSDN博主XMYX-0"
font_size = 50
try:
# Windows 通用字體路徑(可自定義)
# font = ImageFont.truetype("arial.ttf", font_size)
font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", font_size)
except:
font = ImageFont.load_default()
bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
position = (w - text_width - 10, h - text_height - 10) # 右下角
draw.text(position, text, font=font, fill=(255, 0, 0, 128)) # 半透明紅色水印
frames.append(img)
self.progress["value"] += 1
self.root.update_idletasks()
frames[0].save(
output_path,
save_all=True,
append_images=frames[1:],
duration=duration,
loop=0
)
messagebox.showinfo("成功", f"GIF 已生成:\n{output_path}")
webbrowser.open(output_path)
except Exception as e:
messagebox.showerror("錯(cuò)誤", f"生成失?。篭n{str(e)}")
if __name__ == "__main__":
root = tk.Tk()
app = GifMakerApp(root)
root.mainloop()
如何打包成 Windows 可執(zhí)行程序(.exe)
我們可以使用 PyInstaller 進(jìn)行打包:
安裝命令
pip install pyinstaller
打包命令
pyinstaller --noconsole --onefile --icon=app.ico gif_creator.py
| 參數(shù) | 說(shuō)明 |
|---|---|
| --noconsole | 不顯示黑色終端窗口(適用于 GUI 程序) |
| --onefile | 打包為一個(gè)獨(dú)立 .exe 文件 |
| --icon=app.ico | 自定義圖標(biāo)(可選) |
生成后可在 dist/ 目錄找到 gif_creator.exe,可直接發(fā)送給他人使用,無(wú)需安裝 Python。
小貼士與拓展建議
- 字體問(wèn)題:如果打包后字體顯示異常,建議把字體文件放到項(xiàng)目里,使用絕對(duì)路徑加載。
- 水印透明度:可在代碼中調(diào)整
(255, 0, 0, 128)中最后的128控制透明度,范圍 0~255。 - 圖片大小限制:上傳圖片尺寸過(guò)大時(shí),合成 GIF 文件會(huì)很大,建議做圖片縮放。
- 幀間隔調(diào)整:
duration=1000單位為毫秒,可根據(jù)需求調(diào)整動(dòng)畫(huà)速度。
總結(jié)
本項(xiàng)目展示了如何使用 Python 構(gòu)建一個(gè)實(shí)用的 GIF 動(dòng)圖生成工具,并加入水印功能,最終打包成 Windows 可執(zhí)行文件,真正做到“一鍵使用、無(wú)需安裝”。
以上就是使用Python制作GIF動(dòng)圖并打包為exe可執(zhí)行程序的詳細(xì)內(nèi)容,更多關(guān)于Python制作GIF并打包為exe的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在Python中實(shí)現(xiàn)shuffle給列表洗牌
今天小編就為大家分享一篇在Python中實(shí)現(xiàn)shuffle給列表洗牌,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
Python爬蟲(chóng)信息輸入及頁(yè)面的切換方法
今天小編就為大家分享一篇Python爬蟲(chóng)信息輸入及頁(yè)面的切換方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
安裝Keras,tensorflow,并實(shí)現(xiàn)將虛擬環(huán)境添加到j(luò)upyter?notebook
這篇文章主要介紹了安裝Keras,tensorflow,并實(shí)現(xiàn)將虛擬環(huán)境添加到j(luò)upyter?notebook,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
python中實(shí)現(xiàn)指定時(shí)間調(diào)用函數(shù)示例代碼
函數(shù)function是python編程核心內(nèi)容之一,也是比較重要的一塊。下面這篇文章主要給大家介紹了關(guān)于python中實(shí)現(xiàn)指定時(shí)間調(diào)用函數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-09-09
python?實(shí)現(xiàn)?redis?數(shù)據(jù)庫(kù)的操作
這篇文章主要介紹了python?包?redis?數(shù)據(jù)庫(kù)的操作教程,redis?是一個(gè)?Key-Value?數(shù)據(jù)庫(kù),下文基于python的相關(guān)資料展開(kāi)對(duì)redis?數(shù)據(jù)庫(kù)操作的詳細(xì)介紹,需要的小伙伴可以參考一下2022-04-04
matlab中imadjust函數(shù)的作用及應(yīng)用舉例
這篇文章主要介紹了matlab中imadjust函數(shù)的作用及應(yīng)用舉例,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Python使用matplotlib模塊繪制圖像并設(shè)置標(biāo)題與坐標(biāo)軸等信息示例
這篇文章主要介紹了Python使用matplotlib模塊繪制圖像并設(shè)置標(biāo)題與坐標(biāo)軸等信息,結(jié)合實(shí)例形式分析了Python中matplotlib模塊進(jìn)行坐標(biāo)系圖形繪制的相關(guān)操作技巧,需要的朋友可以參考下2018-05-05
使用Python給頭像戴上圣誕帽的圖像操作過(guò)程解析
這篇文章主要介紹了使用Python給頭像戴上圣誕帽的過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09

