图片压缩.exe
import tkinter as tk
from tkinter import filedialog, messagebox
import cv2
import numpy as np
import os
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def normalize_path(path):
"""将路径中的所有反斜杠替换为正斜杠,用于显示或记录日志"""
return path.replace('\\', '/')
def compress_image(img_path, quality):
try:
normalized_path = normalize_path(img_path)
logging.info(f"开始压缩图片: {normalized_path}")
img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
if img is None:
logging.error(f"无法从 {normalized_path} 加载图片")
return f"无法从 {normalized_path} 加载图片"
_, im_encoded = cv2.imencode('.jpg', img, [int(cv2.IMWRITE_JPEG_QUALITY), quality])
im_bytes = im_encoded.tobytes()
logging.info(f"图片 {normalized_path} 压缩成功")
return im_bytes
except Exception as e:
logging.error(f"压缩图片 {normalized_path} 时发生错误: {e}")
return f"压缩图片 {normalized_path} 时发生错误: {e}"
def save_compressed_image(img_bytes, output_path):
try:
normalized_path = normalize_path(output_path)
with open(normalized_path, 'wb') as f:
f.write(img_bytes)
logging.info(f"图片已压缩并保存到 {normalized_path}")
return f"图片已压缩并保存到 {normalized_path}"
except Exception as e:
logging.error(f"保存压缩后的图片到 {normalized_path} 时发生错误: {e}")
return f"保存压缩后的图片到 {normalized_path} 时发生错误: {e}"
def select_input_path():
global input_entry, input_path
input_path = filedialog.askdirectory(title="选择图片文件夹")
if input_path:
input_entry.delete(0, tk.END)
input_entry.insert(0, normalize_path(input_path))
logging.info(f"输入路径设置为: {normalize_path(input_path)}")
def select_output_path():
global output_entry, output_path
output_path = filedialog.askdirectory(title="选择输出目录")
if output_path:
output_entry.delete(0, tk.END)
output_entry.insert(0, normalize_path(output_path))
logging.info(f"输出路径设置为: {normalize_path(output_path)}")
def compress_files():
global quality_entry, input_path, output_path, process_text
quality = int(quality_entry.get())
if not input_path or not output_path:
messagebox.showerror("错误", "请选择输入文件夹和输出目录")
logging.error("未选择输入文件夹或输出目录")
return
if quality < 1 or quality > 100:
messagebox.showerror("错误", "压缩质量必须在1到100之间")
logging.error("压缩质量设置错误")
return
process_text.delete(1.0, tk.END)
process_text.insert(tk.END, "开始压缩图片...\n")
img_list = [os.path.join(input_path, f) for f in os.listdir(input_path) if f.lower().endswith(('.jpg', '.png', '.jpeg'))]
for img_path in img_list:
img_bytes = compress_image(img_path, quality)
if isinstance(img_bytes, bytes):
file_name = os.path.basename(img_path)
output_img_path = os.path.join(output_path, file_name)
save_compressed_image(img_bytes, output_img_path)
process_text.insert(tk.END, f"图片 {normalize_path(file_name)} 已压缩并保存到 {normalize_path(output_img_path)}\n")
else:
process_text.insert(tk.END, img_bytes + "\n")
def main():
global input_entry, output_entry, quality_entry, process_text, input_path, output_path
input_path, output_path = "", ""
root = tk.Tk()
root.title("图片批量压缩工具")
# 设置字体为支持中文的字体
root.option_add("*Font", ("SimHei", 10))
tk.Label(root, text="输入图片文件夹路径:").pack()
input_entry = tk.Entry(root, width=50)
input_entry.pack()
input_button = tk.Button(root, text="浏览", command=select_input_path)
input_button.pack()
tk.Label(root, text="输出目录:").pack()
output_entry = tk.Entry(root, width=50)
output_entry.pack()
output_button = tk.Button(root, text="浏览", command=select_output_path)
output_button.pack()
tk.Label(root, text="压缩质量 (1-100):").pack()
quality_entry = tk.Entry(root, width=10)
quality_entry.pack()
compress_button = tk.Button(root, text="开始压缩", command=compress_files)
compress_button.pack()
process_text = tk.Text(root, height=10, width=50)
process_text.pack()
logging.info("程序启动")
root.mainloop()
logging.info("程序退出")
if __name__ == "__main__":
main()