支持转换并压缩webp\jpg\png\svg,主要功能还是转换成webp,支持尺寸、画质调节。
代码:
import os
from PIL import Image
from concurrent.futures import ThreadPoolExecutor, as_completed
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
def convert_image(input_path, output_path, quality=85, size=None, format='WEBP'):
"""将单个图片转换为指定格式并保存,支持压缩质量和尺寸调整。"""
try:
with Image.open(input_path) as img:
if size:
img = img.resize(size, Image.ANTIALIAS)
img.save(output_path, format=format, quality=quality)
print(f"转换完成: {input_path} -> {output_path}")
except Exception as e:
print(f"转换失败: {input_path},错误: {e}")
def convert_folder(input_folder, output_folder, quality=85, size=None, format='WEBP', max_workers=8):
"""使用多线程将文件夹中的所有图片转换为指定格式。"""
if not os.path.exists(output_folder):
os.makedirs(output_folder)
images = [
filename for filename in os.listdir(input_folder)
if os.path.isfile(os.path.join(input_folder, filename)) and filename.lower().endswith(('png', 'jpg', 'jpeg', 'bmp', 'tiff', 'svg'))
]
tasks = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
for filename in images:
input_path = os.path.join(input_folder, filename)
output_filename = os.path.splitext(filename)[0] + f'.{format.lower()}'
output_path = os.path.join(output_folder, output_filename)
tasks.append(executor.submit(convert_image, input_path, output_path, quality, size, format))
for future in as_completed(tasks):
future.result()
class WebpConverterApp:
def __init__(self, root):
self.root = root
self.root.title("图片批量转换工具")
# 初始化变量
self.input_folder = tk.StringVar()
self.output_folder = tk.StringVar()
self.quality = tk.IntVar(value=85)
self.width = tk.StringVar()
self.height = tk.StringVar()
self.format = tk.StringVar(value='WEBP')
# 创建UI元素
self.create_widgets()
def create_widgets(self):
# 输入文件夹选择
ttk.Label(self.root, text="选择图片文件夹:").grid(row=0, column=0, padx=10, pady=10)
ttk.Entry(self.root, textvariable=self.input_folder, width=50).grid(row=0, column=1, padx=10, pady=10)
ttk.Button(self.root, text="浏览", command=self.select_input_folder).grid(row=0, column=2, padx=10, pady=10)
# 输出文件夹选择
ttk.Label(self.root, text="选择输出文件夹:").grid(row=1, column=0, padx=10, pady=10)
ttk.Entry(self.root, textvariable=self.output_folder, width=50).grid(row=1, column=1, padx=10, pady=10)
ttk.Button(self.root, text="浏览", command=self.select_output_folder).grid(row=1, column=2, padx=10, pady=10)
# 压缩质量设置
ttk.Label(self.root, text="设置WEBP压缩质量 (0-100):").grid(row=2, column=0, padx=10, pady=10)
quality_slider = ttk.Scale(self.root, from_=0, to=100, variable=self.quality, orient='horizontal', length=200)
quality_slider.grid(row=2, column=1, padx=10, pady=10)
quality_slider.bind("<Motion>", self.update_quality_label)
self.quality_label = ttk.Label(self.root, text=f"{self.quality.get()}")
self.quality_label.grid(row=2, column=2, padx=10, pady=10)
# 图片尺寸设置
ttk.Label(self.root, text="输出图片宽度 (px):").grid(row=3, column=0, padx=10, pady=10)
ttk.Entry(self.root, textvariable=self.width, width=10).grid(row=3, column=1, sticky='w', padx=10, pady=10)
ttk.Label(self.root, text="输出图片高度 (px):").grid(row=3, column=1, padx=10, pady=10)
ttk.Entry(self.root, textvariable=self.height, width=10).grid(row=3, column=1, sticky='e', padx=10, pady=10)
# 输出格式选择
ttk.Label(self.root, text="选择输出格式:").grid(row=4, column=0, padx=10, pady=10)
format_options = ['WEBP', 'JPG', 'PNG', 'SVG']
format_dropdown = ttk.OptionMenu(self.root, self.format, *format_options)
format_dropdown.grid(row=4, column=1, padx=10, pady=10)
# 开始转换按钮
ttk.Button(self.root, text="开始转换", command=self.start_conversion).grid(row=5, column=0, columnspan=3, padx=10, pady=20)
def update_quality_label(self, event):
"""更新滑杆旁边的质量显示标签。"""
self.quality_label.config(text=f"{self.quality.get()}")
def select_input_folder(self):
folder = filedialog.askdirectory()
if folder:
self.input_folder.set(folder)
def select_output_folder(self):
folder = filedialog.askdirectory()
if folder:
self.output_folder.set(folder)
def start_conversion(self):
input_folder = self.input_folder.get()
output_folder = self.output_folder.get()
quality = self.quality.get()
format = self.format.get()
# 尺寸输入检查
width = self.width.get()
height = self.height.get()
size = None
if width and height:
try:
size = (int(width), int(height))
except ValueError:
messagebox.showerror("错误", "请输入有效的尺寸数值!")
return
if not input_folder or not output_folder:
messagebox.showerror("错误", "请设置输入和输出文件夹!")
return
if not os.path.exists(input_folder):
messagebox.showerror("错误", "输入文件夹不存在!")
return
try:
convert_folder(input_folder, output_folder, quality=quality, size=size, format=format, max_workers=16)
messagebox.showinfo("完成", "所有图片已成功转换!")
except Exception as e:
messagebox.showerror("错误", f"转换过程中发生错误: {e}")
if __name__ == "__main__":
root = tk.Tk()
app = WebpConverterApp(root)
root.mainloop()
软件就不发了,自己打包或在IDE里执行就行。