图片压缩工具 JPG、PNG转webp 支持画质调节

支持转换并压缩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里执行就行。

© 版权声明

相关文章

司马阅(SmartRead),是一款AI文档阅读分析工具

暂无评论

暂无评论...

网址设置

网址样式切换

详细

网址卡片按钮

显示

布局设置

左侧边栏菜单

展开

页面最大宽度

1700px

搜索框设置

搜索框背景上下位置

仅对图片背景生效

50%

自定义搜索框背景

  • 未知类型

    4K壁纸

自定义搜索框高度

  • 聚焦
  • 信息
  • 默认
自定义设置