由于网站的服务器与带宽性能有限,因此上传的图片被严格限制了边长和大小,使用脚本可以有效对想要上传的文件进行批处理,节省时间。
参考代码:
实现对jpg、png、webp等文件的压缩,限制最长边2560,大小2m以下,随机文件名且保留可能含有的EXIF信息。
暂不支持中文路径文件夹。
import os
import random
import string
from PIL import Image
import tkinter as tk
from tkinterdnd2 import TkinterDnD, DND_FILES
# 生成随机文件名
def generate_random_filename(length=10):
"""生成指定长度的随机文件名(字母和数字)"""
return ''.join(random.choices(string.ascii_letters + string.digits, k=length))
def compress_image(input_path, max_size=2560, max_file_size=2 * 1024 * 1024, quality=85):
"""对图片进行压缩和尺寸调整,保留EXIF信息"""
img = Image.open(input_path)
exif_data = img.info.get("exif") # 获取EXIF数据
width, height = img.size
file_size = os.path.getsize(input_path)
# 生成随机文件名前缀
random_prefix = generate_random_filename(10) # 10 位随机字符前缀
# 获取文件扩展名
file_extension = os.path.splitext(input_path)[1].lower()
# 如果图片是RGBA格式,将其转换为RGB格式,只对JPEG格式需要转换
if img.mode == 'RGBA' and file_extension not in ['.jpeg', '.jpg']:
output_path = os.path.join(os.path.dirname(input_path), f"{random_prefix}_已压缩{file_extension}")
if exif_data:
img.save(output_path, quality=quality, optimize=True, exif=exif_data)
else:
img.save(output_path, quality=quality, optimize=True)
else:
# 如果图片不需要压缩,直接保存为“无需压缩”版本
if max(width, height) <= max_size and file_size <= max_file_size:
output_path = os.path.join(os.path.dirname(input_path), f"{random_prefix}_无需压缩{file_extension}")
if exif_data:
img.save(output_path, exif=exif_data)
else:
img.save(output_path)
else:
# 如果需要调整大小
if max(width, height) > max_size:
scaling_factor = max_size / float(max(width, height))
new_size = (int(width * scaling_factor), int(height * scaling_factor))
img = img.resize(new_size, Image.LANCZOS)
# 保存为JPEG格式,质量为85
output_path = os.path.join(os.path.dirname(input_path), f"{random_prefix}_已压缩.jpg")
if exif_data:
img.save(output_path, quality=quality, optimize=True, exif=exif_data)
else:
img.save(output_path, quality=quality, optimize=True)
# 如果文件过大,继续降低质量,直到符合要求
while os.path.getsize(output_path) > max_file_size and quality > 10:
quality -= 10
if exif_data:
img.save(output_path, quality=quality, optimize=True, exif=exif_data)
else:
img.save(output_path, quality=quality, optimize=True)
return output_path
# 处理拖动的文件
def on_drop(event):
file_paths = event.data.split()
process_images(file_paths)
# 批量处理图片
def process_images(file_paths):
processed_files = []
for file_path in file_paths:
if is_image_file(file_path):
processed_file = compress_image(file_path)
processed_files.append(processed_file)
print(f"处理完成的文件: {processed_files}")
# 判断文件是否为图片
def is_image_file(file_path):
try:
img = Image.open(file_path)
return True
except IOError:
return False
# 创建GUI界面
root = TkinterDnD.Tk()
root.title("图片压缩工具")
root.geometry("600x400")
label = tk.Label(root, text="将图片拖到这里", padx=20, pady=20)
label.pack(padx=20, pady=20)
# 绑定拖拽事件
root.drop_target_register(DND_FILES)
root.dnd_bind('<<Drop>>', on_drop)
# 运行主循环
root.mainloop()