学习定有收获
努力成为大神

Python实现合并图片拼图

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()
内容仅供参考:大神建站 - WordPress插件开发 » Python实现合并图片拼图

评论 1

  1. #-9

    这篇文章解决了我的大问题!

登录

找回密码

注册