在日常的编程工作中,我们经常会遇到需要处理和转换图片格式的场景。无论是为了优化存储空间、提高加载速度,还是为了适应不同的应用需求,图片格式转换都是一项非常实用的功能。Python作为一种功能强大且易于学习的编程语言,拥有众多优秀的图像处理库,其中PIL(Python Imaging Library)及其升级版Pillow库提供了丰富的图像处理功能。本文将详细介绍如何利用Pillow库编写一个简单的图片格式转换工具,并通过详细的代码解析,帮助读者更好地理解和掌握这一实用技能。
要运行该程序,需要使用第三方库PIL(pillow),详情可见Python的图像处理库Pillow安装与使用教程
格式支持:
支持常见图片格式转换(JPEG, PNG, BMP, GIF, TIFF, WEBP)
转换设置:
可调整输出图片质量(1-100)
支持尺寸调整(可保持宽高比,保持宽高比时,只需输入宽度或高度中的一个即可自动计算另一个维度)
可选是否保留元数据(EXIF信息)
输出选项:
自定义输出路径
自动生成新文件名(保留原文件名)
使用方法:
(1)通过"添加文件"或"添加文件夹"按钮选择图片
(2)设置输出格式和保存路径(若不指定输出路径默认原文件路径)
(3)根据需要调整图片质量和尺寸
(4)点击"开始转换"按钮进行转换
若输出路径有同名文件提示提供三个选项:
是:覆盖当前文件
否:跳过当前文件
取消:中止整个转换过程
注意事项:
转换透明背景图片到不支持透明的格式(如JPEG)时,背景会被自动填充为白色
质量设置对不同的格式效果不同(JPEG使用标准质量参数,PNG使用压缩级别)
保持宽高比时,只需输入宽度或高度中的一个即可自动计算另一个维度
运行界面如下:
源码如下:
import os import tkinter as tk from tkinter import ttk, filedialog, messagebox from PIL import Image from pathlib import Path SUPPORTED_FORMATS = ["JPEG", "PNG", "BMP", "GIF", "TIFF", "WEBP"] class ImageConverterApp: def __init__(self, root): self.root = root self.root.title("图片格式转换工具") self.root.geometry("800x600") # 初始化变量 self.selected_files = [] self.output_format = tk.StringVar(value="JPEG") self.output_path = tk.StringVar() self.quality = tk.IntVar(value=85) self.resize_enabled = tk.BooleanVar(value=False) self.new_width = tk.IntVar(value=0) self.new_height = tk.IntVar(value=0) self.keep_ratio = tk.BooleanVar(value=True) self.keep_metadata = tk.BooleanVar(value=False) self.create_widgets() def create_widgets(self): # 文件选择区域 file_frame = ttk.LabelFrame(self.root, text="选择图片") file_frame.pack(padx=10, pady=5, fill="x") ttk.Button(file_frame, text="添加文件", command=self.add_files).pack(side="left", padx=5) ttk.Button(file_frame, text="添加文件夹", command=self.add_folder).pack(side="left", padx=5) ttk.Button(file_frame, text="清空列表", command=self.clear_files).pack(side="right", padx=5) # 文件列表 self.file_list = tk.Listbox(self.root, selectmode=tk.EXTENDED) self.file_list.pack(padx=10, pady=5, fill="both", expand=True) # 设置区域 settings_frame = ttk.LabelFrame(self.root, text="转换设置") settings_frame.pack(padx=10, pady=5, fill="x") # 输出格式 ttk.Label(settings_frame, text="输出格式:").grid(row=0, column=0, sticky="w") format_combo = ttk.Combobox(settings_frame, textvariable=self.output_format, values=SUPPORTED_FORMATS, state="readonly") format_combo.grid(row=0, column=1, padx=5, sticky="ew") # 输出路径 ttk.Label(settings_frame, text="输出路径:").grid(row=1, column=0, sticky="w") ttk.Entry(settings_frame, textvariable=self.output_path).grid(row=1, column=1, columnspan=2, padx=5, sticky="ew") ttk.Button(settings_frame, text="浏览...", command=self.select_output_path).grid(row=1, column=3, padx=5) # 质量设置 ttk.Label(settings_frame, text="图片质量 (1-100):").grid(row=2, column=0, sticky="w") ttk.Scale(settings_frame, from_=1, to=100, variable=self.quality, command=lambda v: self.quality.set(int(float(v)))).grid(row=2, column=1, padx=5, sticky="ew") ttk.Label(settings_frame, textvariable=self.quality).grid(row=2, column=2, padx=5) # 尺寸调整 resize_frame = ttk.Frame(settings_frame) resize_frame.grid(row=3, column=0, columnspan=3, sticky="ew", pady=5) ttk.Checkbutton(resize_frame, text="调整尺寸", variable=self.resize_enabled).pack(side="left", padx=5) ttk.Entry(resize_frame, textvariable=self.new_width, width=5).pack(side="left", padx=5) ttk.Label(resize_frame, text="x").pack(side="left") ttk.Entry(resize_frame, textvariable=self.new_height, width=5).pack(side="left", padx=5) ttk.Checkbutton(resize_frame, text="保持比例", variable=self.keep_ratio).pack(side="left", padx=5) # 其他选项 ttk.Checkbutton(settings_frame, text="保留元数据", variable=self.keep_metadata).grid(row=4, column=0, columnspan=3, sticky="w") # 操作按钮 button_frame = ttk.Frame(self.root) button_frame.pack(padx=10, pady=10, fill="x") ttk.Button(button_frame, text="开始转换", command=self.start_conversion).pack(side="right", padx=5) ttk.Button(button_frame, text="退出", command=self.root.destroy).pack(side="right", padx=5) def add_files(self): files = filedialog.askopenfilenames( filetypes=[("图片文件", "*.jpg *.jpeg *.png *.bmp *.gif *.tiff *.webp")] ) if files: self.selected_files.extend(files) self.update_file_list() def add_folder(self): folder = filedialog.askdirectory() if folder: for ext in ("*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.tiff", "*.webp"): self.selected_files.extend(Path(folder).glob(ext)) self.update_file_list() def clear_files(self): self.selected_files = [] self.file_list.delete(0, tk.END) def update_file_list(self): self.file_list.delete(0, tk.END) for f in self.selected_files: self.file_list.insert(tk.END, str(f)) def select_output_path(self): path = filedialog.askdirectory() if path: self.output_path.set(path) def start_conversion(self): if not self.selected_files: messagebox.showwarning("警告", "请先选择要转换的图片文件!") return output_path = self.output_path.get() or os.path.dirname(self.selected_files[0]) output_format = self.output_format.get() # 创建输出目录(如果不存在) os.makedirs(output_path, exist_ok=True) for file_path in self.selected_files: try: img = Image.open(file_path) # 处理尺寸调整 if self.resize_enabled.get(): width = self.new_width.get() height = self.new_height.get() original_width, original_height = img.size if self.keep_ratio.get(): if width > 0 and height == 0: ratio = width / original_width height = int(original_height * ratio) elif height > 0 and width == 0: ratio = height / original_height width = int(original_width * ratio) else: ratio = min(width/original_width, height/original_height) width = int(original_width * ratio) height = int(original_height * ratio) if width > 0 and height > 0: img = img.resize((width, height), Image.Resampling.LANCZOS) # 构建输出路径 filename = os.path.splitext(os.path.basename(file_path))[0] output_file = os.path.join(output_path, f"{filename}.{output_format.lower()}") # 检查文件是否存在并提示 if os.path.exists(output_file): response = messagebox.askyesnocancel( "文件已存在", f"目标文件已存在:\n{output_file}\n\n" "请选择操作:\n" "• 是:覆盖当前文件\n" "• 否:跳过当前文件\n" "• 取消:中止全部转换", parent=self.root ) if response is None: # 取消 return if not response: # 跳过 continue # 构建输出路径 filename = os.path.splitext(os.path.basename(file_path))[0] output_file = os.path.join(output_path, f"{filename}.{output_format.lower()}") # 保存参数 save_args = {'format': output_format} if output_format == 'JPEG': save_args['quality'] = self.quality.get() save_args['optimize'] = True elif output_format == 'PNG': save_args['compress_level'] = 9 - int(self.quality.get() / 11.1) # 保存图片 if not self.keep_metadata.get(): img.info.pop('exif', None) img.save(output_file, **save_args) except Exception as e: messagebox.showerror("错误", f"处理文件 {file_path} 时出错:\n{str(e)}") continue messagebox.showinfo("完成", "图片转换完成!") if __name__ == "__main__": root = tk.Tk() app = ImageConverterApp(root) root.mainloop()
到此这篇关于Python调用PIL库实现图片格式转换工具的文章就介绍到这了,更多相关Python PIL图片格式转换内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
总结
通过本文的学习,您已经了解了如何使用Pillow库来实现图片格式转换的基本功能。从安装Pillow库到编写转换代码,再到处理不同格式的图片,本文详细讲解了每一个步骤和关键知识点。希望本文能为您在图像处理领域的工作和学习提供有力的支持,让您能够更加灵活地处理各种图片格式转换需求。通过实践本文提供的代码示例,您将能够轻松构建自己的图片格式转换工具,提升工作效率和编程技能。
本文来源于#学习&实践爱好者,由@蜜芽 整理发布。如若内容造成侵权/违法违规/事实不符,请联系本站客服处理!
该文章观点仅代表作者本人,不代表本站立场。本站不承担相关法律责任。
如若转载,请注明出处:https://www.zhanid.com/biancheng/4003.html