图片格式转换工具

最近学习python想用自己喜爱的图片做图标还得去网站上转换,突发奇想不如自己做一个转换工具,

该工具支持6种主流图片格式进行互转,转为ICO格式时需要强制选择分辨率。

附上源码和软件,希望大家喜爱。

https://thebzk.lanzn.com/inuVD2pucl9a

密码:en0p

import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk, UnidentifiedImageError

formats = {
    "ICO": ".ico",
    "PNG": ".png",
    "JPEG": ".jpg",
    "GIF": ".gif",
    "BMP": ".bmp",
    "TIFF": ".tiff"
}

ico_resolutions = {
    "16x16": (16, 16),
    "24x24": (24, 24),
    "32x32": (32, 32),
    "48x48": (48, 48),
    "64x64": (64, 64),
    "128x128": (128, 128),
    "256x256": (256, 256)
}

class ImageConverterGUI:
    def __init__(self, master):
        self.master = master
        self.master.title("图片格式转换工具 v1.0 — Thebzk")
        self.master.geometry("600x700")
        self.master.resizable(False, False)
        
        main_frame = ttk.Frame(self.master, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)

        input_frame = ttk.Labelframe(main_frame, text="输入文件", padding=10)
        input_frame.pack(fill=tk.X, pady=5)
        
        input_grid = ttk.Frame(input_frame)
        input_grid.pack(fill=tk.X)
        
        ttk.Label(input_grid, text="选择图片文件:").grid(row=0, column=0, padx=5)
        self.input_var = tk.StringVar()
        ttk.Entry(input_grid, textvariable=self.input_var, width=40).grid(row=0, column=1, padx=5)
        ttk.Button(
            input_grid,
            text="选择文件",
            command=self.choose_input_file,
            bootstyle="primary",
            width=12
        ).grid(row=0, column=2, padx=5)

        settings_frame = ttk.Labelframe(main_frame, text="转换设置", padding=10)
        settings_frame.pack(fill=tk.X, pady=5)
        
        settings_grid = ttk.Frame(settings_frame)
        settings_grid.pack(fill=tk.X)
        
        ttk.Label(settings_grid, text="输出格式:").grid(row=0, column=0, padx=5)
        self.format_var = tk.StringVar(value='')
        format_combobox = ttk.Combobox(
            settings_grid,
            textvariable=self.format_var,
            values=list(formats.keys()),
            bootstyle="primary",
            state="readonly",
            width=12
        )
        format_combobox.grid(row=0, column=1, padx=5)
        
        self.ico_resolution_var = tk.StringVar(value='')
        self.ico_resolution_box = ttk.Combobox(
            settings_grid,
            textvariable=self.ico_resolution_var,
            values=list(ico_resolutions.keys()),
            bootstyle="primary",
            state="disabled",
            width=12
        )
        self.ico_resolution_box.grid(row=0, column=2, padx=5)
        format_combobox.bind("<<ComboboxSelected>>", self.toggle_ico_resolution)

        ttk.Button(
            settings_grid,
            text="开始转换",
            command=self.convert,
            bootstyle="success",
            width=12
        ).grid(row=0, column=3, padx=5)

        preview_frame = ttk.Labelframe(main_frame, text="图片预览", padding=10)
        preview_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.preview_canvas = ttk.Canvas(preview_frame, bg='#f8f9fa')
        self.preview_canvas.pack(fill=tk.BOTH, expand=True)
        self.preview_image = None

        log_frame = ttk.Labelframe(main_frame, text="操作日志", padding=10)
        log_frame.pack(fill=tk.X, pady=5)
        
        self.log_area = ttk.Text(
            log_frame,
            wrap=tk.WORD,
            font=("Consolas", 9),
            height=22,
            bg="#f8f9fa",
            fg="#495057"
        )
        self.log_area.pack(fill=tk.BOTH)

    def toggle_ico_resolution(self, event):
        """切换ICO分辨率下拉框状态"""
        if self.format_var.get() == "ICO":
            self.ico_resolution_box.configure(state="readonly")
        else:
            self.ico_resolution_box.configure(state="disabled")

    def choose_input_file(self):
        file_path = filedialog.askopenfilename(
            filetypes=[("图片文件", "*.png;*.jpg;*.jpeg;*.gif;*.bmp;*.tiff")]
        )
        if file_path:
            self.input_var.set(file_path)
            self.show_preview(file_path)

    def show_preview(self, file_path):
        try:
            self.preview_canvas.delete("all")
            
            img = Image.open(file_path)
            canvas_width = self.preview_canvas.winfo_width() - 20
            canvas_height = self.preview_canvas.winfo_height() - 20
            img_ratio = img.width / img.height
            canvas_ratio = canvas_width / canvas_height
            
            if img_ratio > canvas_ratio:
                new_width = min(img.width, canvas_width)
                new_height = int(new_width / img_ratio)
            else:
                new_height = min(img.height, canvas_height)
                new_width = int(new_height * img_ratio)
                
            img = img.resize((new_width, new_height), Image.LANCZOS)
            self.preview_image = ImageTk.PhotoImage(img)
            
            x = (self.preview_canvas.winfo_width() - new_width) // 2
            y = (self.preview_canvas.winfo_height() - new_height) // 2
            self.preview_canvas.create_image(x, y, anchor=tk.NW, image=self.preview_image)
            
        except Exception as e:
            messagebox.showerror("错误", f"预览失败: {str(e)}")

    def convert(self):
        input_path = self.input_var.get()
        output_format = self.format_var.get()
        ico_resolution = self.ico_resolution_var.get()
        
        if not input_path:
            messagebox.showwarning("提示", "请选择输入文件!")
            return
        if not output_format:
            messagebox.showwarning("提示", "请选择输出格式!")
            return
        
        output_dir = filedialog.askdirectory(title="选择输出目录")
        if not output_dir:
            messagebox.showwarning("提示", "请选择输出目录!")
            return
        
        try:
            img = Image.open(input_path)
            
            format_lower = output_format.lower()
            if format_lower == 'ico':
                if not ico_resolution:
                    messagebox.showwarning("提示", "请选择ICO分辨率!")
                    return
                
                sizes = [ico_resolutions[ico_resolution]]
                img.save(f"{output_dir}/output.{formats[output_format]}", format_lower.upper(), sizes=sizes)
            else:
                img.save(f"{output_dir}/output.{formats[output_format]}", format_lower.upper())
            
            messagebox.showinfo("成功", f"图片已成功转换并保存到 {output_dir}/output.{formats[output_format]}")
            self.log_message(f"成功保存到 {output_dir}/output.{formats[output_format]}")
        
        except UnidentifiedImageError:
            messagebox.showerror("错误", "无法识别图片格式!")
            self.log_message("无法识别图片格式!", level="ERROR")
        except Exception as e:
            messagebox.showerror("错误", f"转换失败: {str(e)}")
            self.log_message(f"转换失败: {str(e)}", level="ERROR")

    def log_message(self, message, level="INFO"):
        self.log_area.insert(tk.END, f"[{level}] {message}
")
        self.log_area.see(tk.END)

def main():
    root = ttk.Window(themename="cosmo")
    app = ImageConverterGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 共44条

请登录后发表评论

    暂无评论内容