使用 python 制作 gif 动图,并打包为 exe 可执行程序(含图形界面)
在工作或个人项目中,常常会遇到需要将多张图片合成 gif 动图的需求,同时添加版权水印保护作品。本文分享一个使用 python 和 pillow 库实现的 gif 生成工具,配备简单的 tkinter 图形界面,支持:
- 批量上传图片,合成 gif 动图
- 固定文字水印自动添加
- 可选图片水印(logo)叠加
- 一键生成,操作简单
- 使用 pyinstaller 打包为 windows 独立 exe
无论你是 python 初学者,还是想快速做一个实用小工具,这篇文章都会帮你搞定。
环境准备
python 3.6+
pillow:图像处理库,安装命令:
pip install pillow
- tkinter:python 内置图形界面库(windows 下默认包含)
- pyinstaller:后续将介绍如何打包
功能预览
功能 | 说明 |
---|---|
多图片上传 | 支持多选 png/jpg/jpeg/bmp 等常见格式 |
gif 动画生成 | 支持循环播放,帧间隔可自定义 |
简洁图形界面 | 按钮操作:选择图片、生成 gif |
一键生成 | 直接点击按钮即可生成 |
exe 打包 | 使用 pyinstaller 一键打包,免 python 环境 |
完整代码(图形界面 + 功能)
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 动图生成器") 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) # 帧间隔时间 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) # 进度条 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("未选择图片", "请先选择图片!") return try: duration = int(self.duration_var.get()) except valueerror: messagebox.showerror("无效间隔", "请输入合法的帧间隔(整数)") return output_path = self.output_path_var.get().strip() if not output_path: messagebox.showerror("路径错误", "请输入有效的保存路径") return try: frames = [] self.progress["maximum"] = len(self.image_paths) self.progress["value"] = 0 from pil import imagefont, imagedraw # ...在循环中每次读取图片时 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("错误", f"生成失败:\n{str(e)}") if __name__ == "__main__": root = tk.tk() app = gifmakerapp(root) root.mainloop()
如何打包成 windows 可执行程序(.exe)
我们可以使用 pyinstaller 进行打包:
安装命令
pip install pyinstaller
打包命令
pyinstaller --noconsole --onefile --icon=app.ico gif_creator.py
参数 | 说明 |
---|---|
--noconsole | 不显示黑色终端窗口(适用于 gui 程序) |
--onefile | 打包为一个独立 .exe 文件 |
--icon=app.ico | 自定义图标(可选) |
生成后可在 dist/
目录找到 gif_creator.exe
,可直接发送给他人使用,无需安装 python。
小贴士与拓展建议
- 字体问题:如果打包后字体显示异常,建议把字体文件放到项目里,使用绝对路径加载。
- 水印透明度:可在代码中调整
(255, 0, 0, 128)
中最后的128
控制透明度,范围 0~255。 - 图片大小限制:上传图片尺寸过大时,合成 gif 文件会很大,建议做图片缩放。
- 帧间隔调整:
duration=1000
单位为毫秒,可根据需求调整动画速度。
总结
本项目展示了如何使用 python 构建一个实用的 gif 动图生成工具,并加入水印功能,最终打包成 windows 可执行文件,真正做到“一键使用、无需安装”。
以上就是使用python制作gif动图并打包为exe可执行程序的详细内容,更多关于python制作gif并打包为exe的资料请关注代码网其它相关文章!
发表评论