WordPress 原创插件 国人习惯、简约实用、容易上手【点击了解】
基于具体图片处理需求(3 张竖图按最大高度等比缩放横向拼接、横图不处理、复制重命名),下面放Python代码
import os
import json
from PIL import Image
from tkinter import Tk, Button, Label, Entry, filedialog, messagebox, Text, Scrollbar, END
from tkinter.ttk import Progressbar
# 配置文件路径
CONFIG_FILE = "config.json"
# 选择文件夹的函数
def select_folder(entry_widget):
folder_path = filedialog.askdirectory()
if folder_path:
entry_widget.delete(0, "end")
entry_widget.insert(0, folder_path)
# 加载图片的函数
def load_images_from_folder(folder):
images = []
valid_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.gif']
for filename in os.listdir(folder):
ext = os.path.splitext(filename)[1].lower()
if ext in valid_extensions:
img_path = os.path.join(folder, filename)
try:
img = Image.open(img_path)
images.append(img)
except Exception as e:
log_message(f"无法加载图片 {filename}: {e}")
return images
# 调整图片大小的函数
def resize_images_to_max_height(images):
max_height = max(img.height for img in images)
resized_images = []
for img in images:
if img.height < max_height:
ratio = max_height / img.height
new_width = int(img.width * ratio)
resized_img = img.resize((new_width, max_height), Image.Resampling.LANCZOS)
resized_images.append(resized_img)
else:
resized_images.append(img)
return resized_images
# 横向拼接图片的函数
def merge_images_horizontally(images):
total_width = sum(img.width for img in images)
max_height = max(img.height for img in images)
merged_image = Image.new('RGB', (total_width, max_height))
x_offset = 0
for img in images:
merged_image.paste(img, (x_offset, 0))
x_offset += img.width
return merged_image
# 保存图片的函数
def save_image(image, folder, index):
output_path = os.path.join(folder, f'merged_{index}.jpg')
image.save(output_path)
log_message(f"图片已保存到 {output_path}")
# 处理图片的函数
def process_images(input_folder, output_folder, start_index):
images = load_images_from_folder(input_folder)
total_images = len(images)
if total_images == 0:
log_message("输入文件夹中没有图片!")
return
index = start_index
processed_count = 0
while images:
if len(images) >= 3:
three_images = images[:3]
images = images[3:]
# 检查是否有图片是长度大于高度的
if any(img.width > img.height for img in three_images):
# 如果有长度大于高度的图片,直接复制到输出文件夹
for img in three_images:
if img.width > img.height:
save_image(img, output_folder, index)
index += 1
processed_count += 1
update_progress(processed_count, total_images)
else:
# 否则,进行合并
resized_images = resize_images_to_max_height(three_images)
merged_image = merge_images_horizontally(resized_images)
save_image(merged_image, output_folder, index)
index += 1
processed_count += 3
update_progress(processed_count, total_images)
else:
# 处理剩余的图片
for img in images:
save_image(img, output_folder, index)
index += 1
processed_count += 1
update_progress(processed_count, total_images)
break
# 确保进度条显示为 100%
update_progress(total_images, total_images)
log_message("图片合并完成!")
messagebox.showinfo("完成", "图片合并完成!")
save_config(input_folder, output_folder, index) # 保存配置,记录结束序号
# 日志显示函数
def log_message(message):
log_text.insert(END, message + "\n") # 在日志区域追加消息
log_text.see(END) # 自动滚动到底部
log_text.update() # 更新日志区域
# 更新进度条的函数
def update_progress(processed, total):
progress = int((processed / total) * 100)
progress_bar['value'] = progress
progress_label.config(text=f"进度: {progress}%")
root.update_idletasks() # 更新界面
# 保存配置的函数
def save_config(input_folder, output_folder, last_index):
config = {
"input_folder": input_folder,
"output_folder": output_folder,
"last_index": last_index # 记录结束序号
}
with open(CONFIG_FILE, "w") as f:
json.dump(config, f)
# 加载配置的函数
def load_config():
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r") as f:
config = json.load(f)
return (
config.get("input_folder", ""),
config.get("output_folder", ""),
config.get("last_index", 0) # 加载上一次的结束序号
)
return "", "", 0
# 开始按钮点击事件
def start_processing():
input_folder = input_entry.get()
output_folder = output_entry.get()
try:
start_index = int(start_index_entry.get()) # 获取用户输入的开始序号
except ValueError:
messagebox.showerror("错误", "开始序号必须是整数!")
return
# 立即保存配置
save_config(input_folder, output_folder, start_index)
if not input_folder or not output_folder:
messagebox.showerror("错误", "请选择输入和输出文件夹!")
return
if not os.path.exists(input_folder):
messagebox.showerror("错误", "输入文件夹不存在!")
return
if not os.path.exists(output_folder):
os.makedirs(output_folder)
log_message("开始处理图片...")
progress_bar['value'] = 0 # 重置进度条
progress_label.config(text="进度: 0%")
process_images(input_folder, output_folder, start_index)
# 创建主窗口
root = Tk()
root.title("图片合并工具 by DeepSeek")
# 设置窗口大小
window_width = 550
window_height = 450
root.geometry(f"{window_width}x{window_height}")
# 获取屏幕尺寸
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# 计算窗口居中的位置
x_position = (screen_width - window_width) // 2
y_position = (screen_height - window_height) // 2
# 设置窗口位置
root.geometry(f"+{x_position}+{y_position}")
# 加载上次的配置
input_folder, output_folder, last_index = load_config()
# 输入文件夹选择
input_label = Label(root, text="输入文件夹:")
input_label.grid(row=0, column=0, padx=10, pady=10)
input_entry = Entry(root, width=30)
input_entry.grid(row=0, column=1, padx=10, pady=10)
input_entry.insert(0, input_folder) # 自动填充上次选择的输入文件夹
input_button = Button(root, text="选择", command=lambda: select_folder(input_entry))
input_button.grid(row=0, column=2, padx=10, pady=10)
# 输出文件夹选择
output_label = Label(root, text="输出文件夹:")
output_label.grid(row=1, column=0, padx=10, pady=10)
output_entry = Entry(root, width=30)
output_entry.grid(row=1, column=1, padx=10, pady=10)
output_entry.insert(0, output_folder) # 自动填充上次选择的输出文件夹
output_button = Button(root, text="选择", command=lambda: select_folder(output_entry))
output_button.grid(row=1, column=2, padx=10, pady=10)
# 开始序号
start_index_label = Label(root, text="开始序号:")
start_index_label.grid(row=2, column=0, padx=10, pady=10)
start_index_entry = Entry(root, width=10)
start_index_entry.grid(row=2, column=1, padx=10, pady=10, sticky="w")
start_index_entry.insert(0, str(last_index + 1)) # 默认加载上一次的结束序号并加一
# 开始按钮
start_button = Button(root, text="开始合并", command=start_processing)
start_button.grid(row=2, column=2, padx=10, pady=10)
# 进度条
progress_label = Label(root, text="进度: 0%")
progress_label.grid(row=3, column=0, padx=10, pady=10, sticky="w")
progress_bar = Progressbar(root, orient="horizontal", length=400, mode="determinate")
progress_bar.grid(row=3, column=1, columnspan=2, padx=10, pady=10)
# 日志显示区域
log_label = Label(root, text="合并日志:")
log_label.grid(row=4, column=0, padx=10, pady=10, sticky="w")
log_text = Text(root, height=10, width=50)
log_text.grid(row=5, column=0, columnspan=3, padx=10, pady=10)
# 添加滚动条
scrollbar = Scrollbar(root, command=log_text.yview)
scrollbar.grid(row=5, column=3, sticky="ns")
log_text.config(yscrollcommand=scrollbar.set)
# 运行主循环
root.mainloop()
这篇文章解决了我的大问题!