使用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()
  • 我们可以使用 PyInstaller 进行打包:
  • 字体问题:如果打包后字体显示异常,建议把字体文件放到项目里,使用绝对路径加载。 水印透明度:可在代码中调整 (255, 0, 0, 128) 中最后的 128 控制透明度,范围 0~255。 图片大小限制:上传图片尺寸过大时,合成 GIF 文件会很大,建议做图片缩放。 帧间隔调整:duration=1000 单位为毫秒,可根据需求调整动画速度。
  • 本项目展示了如何使用 Python 构建一个实用的 GIF 动图生成工具,并加入水印功能,最终打包成 Windows 可执行文件,真正做到“一键使用、无需安装”。 以上就是使用Python制作GIF动图并打包为exe可执行程序的详细内容,更多关于Python制作GIF并打包为exe的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: 基于Python制作GIF表情包生成工具 利用Python实现无损GIF动图的制作 基于Python实现傻瓜式GIF制作工具 Python如何使用PIL Image制作GIF图片 利用Python如何制作好玩的GIF动图详解
  • 目录
    • 使用 Python 制作 GIF 动图,并打包为 EXE 可执行程序(含图形界面)
    • 环境准备
    • 功能预览
    • 完整代码(图形界面 + 功能)
    • 如何打包成 Windows 可执行程序(.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()
        
        

        我们可以使用 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的资料请关注风君子博客其它相关文章!

        您可能感兴趣的文章:

        • 基于Python制作GIF表情包生成工具
        • 利用Python实现无损GIF动图的制作
        • 基于Python实现傻瓜式GIF制作工具
        • Python如何使用PIL Image制作GIF图片
        • 利用Python如何制作好玩的GIF动图详解

        站内搜索