it编程 > 前端脚本 > Python

Python调用PIL库实现图片格式转换工具

8人参与 2025-04-25 Python

要运行该程序,需要使用第三方库pil(pillow),详情可见python的图像处理库pillow安装与使用教程

格式支持:

支持常见图片格式转换(jpeg, png, bmp, gif, tiff, webp)

转换设置:

输出选项:

使用方法:

(1)通过"添加文件"或"添加文件夹"按钮选择图片

(2)设置输出格式和保存路径(若不指定输出路径默认原文件路径)

(3)根据需要调整图片质量和尺寸

(4)点击"开始转换"按钮进行转换

若输出路径有同名文件提示提供三个选项:

是:覆盖当前文件

否:跳过当前文件

 取消:中止整个转换过程

注意事项:

运行界面如下:

源码如下:

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图片格式转换内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

通过Python快速获取Excel工作表名的方法示例

04-25

Python中数字类型内置方法详解

04-25

Python使用MinerU的简单的示例

04-25

Python Transformers库(NLP处理库)案例代码讲解

04-25

Python如何实现按文件夹加密解密其中文件

04-25

Python中锁Lock的类型举例详解

04-25

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论