最近学习python想用自己喜欢的图片做图标还得去网站上转换,突发奇想不如自己做一个转换工具,
该工具支持6种主流图片格式进行互转,转为ICO格式时需要强制选择分辨率。
附上源码和软件,希望大家喜欢。
https://thebzk.lanzn.com/inuVD2pucl9a
密码:en0p
[Python] 纯文本查看 复制代码
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}\n")
self.log_area.see(tk.END)
def main():
root = ttk.Window(themename="cosmo")
app = ImageConverterGUI(root)
root.mainloop()
if __name__ == "__main__":
main()