import os
import sys
import hashlib
from PIL import Image, ImageTk, ImageDraw, ImageFont
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

from tkinterdnd2 import DND_FILES, TkinterDnD  # 导入 tkinterdnd2

# 支持的图片格式
IMAGE_EXTENSIONS = ('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp','jfif')
# 支持转换的目标格式
TARGET_FORMATS = ('webp', 'jpg', 'jpeg', 'gif', 'png')

# 缓存已计算的文件哈希值
file_hash_cache = {}

def get_file_hash(file_path, force_recompute=False):
    """计算文件的MD5哈希值，用于精确比较文件内容"""
    if not force_recompute and file_path in file_hash_cache:
        return file_hash_cache[file_path]
    
    try:
        hash_md5 = hashlib.md5()
        with open(file_path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        file_hash = hash_md5.hexdigest()
        file_hash_cache[file_path] = file_hash
        return file_hash
    except Exception as e:
        print(f"计算文件哈希失败: {file_path}, 错误: {e}")
        return None

def get_image_files(root_dir):
    image_files = []
    for root, dirs, files in os.walk(root_dir):
        for file in files:
            if file.lower().endswith(IMAGE_EXTENSIONS):
                image_files.append(os.path.join(root, file))
    return image_files

def get_canonical_path(file_path):
    """获取文件的规范路径，用于比较"""
    try:
        # 获取真实路径（解析符号链接等）
        real_path = os.path.realpath(file_path)
        # 转换为小写（对于Windows系统）
        return real_path.lower()
    except Exception as e:
        print(f"获取规范路径失败: {file_path}, 错误: {e}")
        return file_path.lower()  # 退回到简单的小写处理

def resize_image(image_path, new_width, new_height, save_mode, save_dir, source_folder, target_format):
    try:
        img = Image.open(image_path)
        is_gif = img.format == 'GIF'
        is_webp = img.format == 'WEBP'
        
        # 检查目标格式是否支持动画
        target_format_lower = target_format.lower()
        target_supports_animation = target_format_lower in ('gif', 'webp')
        
        # 处理 JFIF 格式，将其视为 JPEG
        if target_format_lower == 'jfif':
            target_format_lower = 'jpeg'
        
        # 如果源格式和目标格式都支持动画，则保留所有帧
        if (is_gif or is_webp) and target_supports_animation:
            # 处理GIF/WebP之间的转换（保留所有帧）
            frames = []
            durations = []
            loop = 0  # 0表示无限循环
            
            try:
                while True:
                    frames.append(img.copy())
                    durations.append(img.info.get('duration', 100))
                    img.seek(len(frames))  # 移动到下一帧
            except EOFError:
                pass
            
            # 计算新尺寸（所有帧使用相同尺寸）
            width, height = frames[0].size
            if new_width.lower() == 'auto' and new_height.lower() == 'auto':
                new_width_val, new_height_val = width, height
            elif new_width.lower() == 'auto':
                new_width_val = int((int(new_height) / height) * width)
                new_height_val = int(new_height)
            elif new_height.lower() == 'auto':
                new_height_val = int((int(new_width) / width) * height)
                new_width_val = int(new_width)
            else:
                new_width_val, new_height_val = int(new_width), int(new_height)
            
            # 调整所有帧的尺寸
            resized_frames = []
            for frame in frames:
                if frame.mode != 'RGBA':
                    frame = frame.convert('RGBA')
                resized_frame = frame.resize((new_width_val, new_height_val), Image.LANCZOS)
                resized_frames.append(resized_frame)
            
            # 保存为动画
            if save_mode == "覆盖原图":
                base_name = os.path.splitext(image_path)[0]
                new_path = f"{base_name}.{target_format}"
            else:
                try:
                    relative_path = os.path.relpath(image_path, source_folder)
                    new_dir = os.path.join(save_dir, os.path.dirname(relative_path))
                    os.makedirs(new_dir, exist_ok=True)
                    base_name = os.path.splitext(os.path.basename(image_path))[0]
                    new_file_name = f"{base_name}_resized.{target_format}"
                    new_path = os.path.join(new_dir, new_file_name)
                except ValueError:
                    base_name = os.path.splitext(os.path.basename(image_path))[0]
                    new_file_name = f"{base_name}_resized.{target_format}"
                    new_path = os.path.join(save_dir, new_file_name)
                    
                    counter = 1
                    while os.path.exists(new_path):
                        new_file_name = f"{base_name}_resized_{counter}.{target_format}"
                        new_path = os.path.join(save_dir, new_file_name)
                        counter += 1
            
            # 根据目标格式保存动画
            if target_format_lower == 'gif':
                resized_frames[0].save(
                    new_path,
                    save_all=True,
                    append_images=resized_frames[1:],
                    duration=durations,
                    loop=loop,
                    disposal=2  # 背景处理方式
                )
            else:  # WebP
                resized_frames[0].save(
                    new_path,
                    save_all=True,
                    append_images=resized_frames[1:],
                    duration=durations,
                    loop=loop,
                    quality=80
                )
            
            print(f"成功保存动画: {new_path}")
            return True, new_path
            
        else:
            # 处理单帧图片或GIF/WebP转JPG/PNG（只取第一帧）
            if is_gif or is_webp:
                img.seek(0)
                frame = img.copy().convert('RGBA')
                width, height = frame.size
                
                # 计算新尺寸
                if new_width.lower() == 'auto' and new_height.lower() == 'auto':
                    new_width_val, new_height_val = width, height
                elif new_width.lower() == 'auto':
                    new_width_val = int((int(new_height) / height) * width)
                    new_height_val = int(new_height)
                elif new_height.lower() == 'auto':
                    new_height_val = int((int(new_width) / width) * height)
                    new_width_val = int(new_width)
                else:
                    new_width_val, new_height_val = int(new_width), int(new_height)
                
                # 调整尺寸
                resized_frame = frame.resize((new_width_val, new_height_val), Image.LANCZOS)
            
            else:
                # 处理非 GIF 和非 WebP 图片
                width, height = img.size
                if new_width.lower() == 'auto' and new_height.lower() == 'auto':
                    resized_img = img
                elif new_width.lower() == 'auto':
                    new_width = int((int(new_height) / height) * width)
                    resized_img = img.resize((new_width, int(new_height)), Image.LANCZOS)
                elif new_height.lower() == 'auto':
                    new_height = int((int(new_width) / width) * height)
                    resized_img = img.resize((int(new_width), new_height), Image.LANCZOS)
                else:
                    resized_img = img.resize((int(new_width), int(new_height)), Image.LANCZOS)
            
            # 保存路径处理
            if save_mode == "覆盖原图":
                base_name = os.path.splitext(image_path)[0]
                new_path = f"{base_name}.{target_format}"
            else:
                try:
                    relative_path = os.path.relpath(image_path, source_folder)
                    new_dir = os.path.join(save_dir, os.path.dirname(relative_path))
                    os.makedirs(new_dir, exist_ok=True)
                    base_name = os.path.splitext(os.path.basename(image_path))[0]
                    new_file_name = f"{base_name}_resized.{target_format}"
                    new_path = os.path.join(new_dir, new_file_name)
                except ValueError:
                    base_name = os.path.splitext(os.path.basename(image_path))[0]
                    new_file_name = f"{base_name}_resized.{target_format}"
                    new_path = os.path.join(save_dir, new_file_name)
                    
                    counter = 1
                    while os.path.exists(new_path):
                        new_file_name = f"{base_name}_resized_{counter}.{target_format}"
                        new_path = os.path.join(save_dir, new_file_name)
                        counter += 1
            
            # 根据目标格式保存图片
            if (is_gif or is_webp) and target_format_lower in ('jpg', 'jpeg'):
                resized_frame = resized_frame.convert('RGB')
                resized_frame.save(new_path, format='JPEG')
            elif (is_gif or is_webp):
                resized_frame.save(new_path, format=target_format.upper())
            elif target_format_lower in ('jpg', 'jpeg'):
                resized_img = resized_img.convert('RGB')
                resized_img.save(new_path, format='JPEG')
            else:
                resized_img.save(new_path, format=target_format.upper())
            
            print(f"成功保存: {new_path}")
            return True, new_path
            
    except Exception as e:
        error_msg = f"处理 {image_path} 时出错: {str(e)}"
        print(error_msg)
        return False, error_msg
def select_folder():
    global source_folders, selected_images, image_frame_map
    folder_path = filedialog.askdirectory()
    if folder_path:
        # 规范化文件夹路径
        folder_path = get_canonical_path(folder_path)
        
        # 清空之前的文件夹列表
        source_folders = []
        source_folders.append(folder_path)
        folder_entry.delete(0, tk.END)
        folder_entry.insert(0, folder_path)
        
        # 清空之前的图片选择信息
        selected_images = {}
        image_frame_map = {}
        
        # 扫描新文件夹中的图片
        new_image_files = get_image_files(folder_path)
        print(f"在文件夹 {folder_path} 中发现 {len(new_image_files)} 张图片")
        
        # 规范化并过滤掉已存在的图片
        new_images_count = 0
        existing_images_count = 0
        
        # 创建已存在图片的规范化路径集合和哈希集合
        existing_canonical_paths = {get_canonical_path(p) for p in selected_images.keys()}
        existing_hashes = {get_file_hash(p) for p in selected_images.keys() if get_file_hash(p)}
        
        for img in new_image_files:
            canonical_img = get_canonical_path(img)

            if canonical_img in existing_canonical_paths:
                existing_images_count += 1
                continue

            img_hash = get_file_hash(img)
            
            # 使用规范化路径作为 key 存入字典
            selected_images[canonical_img] = tk.IntVar(value=1)
            new_images_count += 1
            existing_canonical_paths.add(canonical_img)
            if img_hash:
                existing_hashes.add(img_hash)
        
        print(f"添加了 {new_images_count} 张新图片, 跳过了 {existing_images_count} 张已存在的图片")
            
        preview_images()
        update_selected_count()

def preview_images():
    global image_frame_map
    if not selected_images:
        return
    for widget in preview_frame.winfo_children():
        widget.destroy()

    image_frame_map = {}
    row = 0
    col = 0
    existing_paths = set()  # 用于去重

    for index, image_path in enumerate(selected_images.keys()):
        try:
            normalized_path = get_canonical_path(image_path)
            if normalized_path in existing_paths:
                continue  # 跳过重复项
            existing_paths.add(normalized_path)

            img = Image.open(image_path)
            img.thumbnail((100, 100))
            photo = ImageTk.PhotoImage(img)

            frame = tk.Frame(preview_frame, bd=1, highlightthickness=1)
            if selected_images.get(normalized_path) and selected_images[normalized_path].get():
                frame.config(highlightbackground="green", highlightcolor="green")
            else:
                frame.config(highlightbackground="white", highlightcolor="white")
            frame.grid(row=row, column=col, padx=5, pady=5)

            label = tk.Label(frame, image=photo)
            label.image = photo
            label.pack()
            label.bind("<Button-1>", lambda event, path=image_path: toggle_selection(path))

            image_frame_map[normalized_path] = (frame, label)

            col += 1
            if col % 5 == 0:
                col = 0
                row += 1
        except Exception as e:
            print(f"预览 {image_path} 时出错: {e}")
            messagebox.showerror("预览错误", f"预览 {image_path} 时出错: {e}")

def toggle_selection(image_path):
    # 规范化路径
    normalized_path = get_canonical_path(image_path)
    
    # 如果不存在，则默认设为已选中状态
    if normalized_path not in selected_images:
        selected_images[normalized_path] = tk.IntVar(value=1)
    else:
        # 切换当前状态
        selected_images[normalized_path].set(1 - selected_images[normalized_path].get())
    
    # 更新UI显示
    if normalized_path in image_frame_map:
        frame = image_frame_map[normalized_path][0]
        if selected_images[normalized_path].get():
            frame.config(highlightbackground="green", highlightcolor="green")
        else:
            frame.config(highlightbackground="white", highlightcolor="white")
    
    update_selected_count()

def drop(event):
    global source_folders
    # 获取原始拖放数据
    paths_data = event.data
    print(f"原始拖放数据: {paths_data}")
    
    # 改进的路径解析逻辑，能同时处理带花括号和不带花括号的路径
    paths = []
    if paths_data.startswith('{') and paths_data.endswith('}'):
        # 处理带花括号的Windows格式路径
        current_path = ""
        in_quote = False
        for char in paths_data:
            if char == '{' and not in_quote:
                in_quote = True
                current_path = ""
            elif char == '}' and in_quote:
                in_quote = False
                if current_path:
                    paths.append(current_path)
                    current_path = ""
            elif in_quote:
                current_path += char
        # 处理可能没有被花括号包围的路径
        if current_path and not in_quote:
            paths.extend(current_path.split())
    else:
        # 处理不带花括号的路径（直接分割）
        # 先尝试用系统路径分隔符分割
        if os.pathsep in paths_data:
            paths = paths_data.split(os.pathsep)
        # 再尝试用空格分割（处理单个路径中可能包含的空格）
        elif ' ' in paths_data and len(paths_data.split()) > 1:
            paths = paths_data.split()
        # 如果都不是，可能是单个路径
        else:
            paths = [paths_data]
    
    # 清理路径列表，去除空字符串和重复项
    paths = [p.strip() for p in paths if p.strip()]
    paths = list(dict.fromkeys(paths))  # 保持顺序的同时去重
    
    print(f"解析后的路径列表: {paths}")
    print(f"开始处理拖入的文件，共 {len(paths)} 个")
    # 存储实际拖入的图片路径
    dropped_image_paths = []
    new_images_count = 0
    skipped_count = 0
    # 创建已存在图片的规范化路径集合和哈希集合
    existing_canonical_paths = set()
    existing_hashes = set()
    for p in selected_images.keys():
        canonical_path = get_canonical_path(p)
        existing_canonical_paths.add(canonical_path)
        file_hash = get_file_hash(p)
        if file_hash:
            existing_hashes.add(file_hash)
    print(f"已有图片数量: {len(selected_images)}")
    print(f"已有规范路径集合大小: {len(existing_canonical_paths)}")
    print(f"已有哈希集合大小: {len(existing_hashes)}")
    for path in paths:
        # 清理路径
        path = path.strip('{}" ')
        print(f"\n处理路径: {path}")
        if os.path.isdir(path):  # 如果是文件夹
            print(f"  检测到文件夹: {path}")
            folder_image_files = get_image_files(path)
            # 替换 drop() 中以下部分
            for img in folder_image_files:
                canonical_img = get_canonical_path(img)
                if canonical_img in existing_canonical_paths:
                    skipped_count += 1
                    continue

                # 计算文件哈希
                img_hash = get_file_hash(img)
                if img_hash is None:
                    print(f"  计算文件哈希失败，跳过图片: {img}")
                    skipped_count += 1
                    continue
                elif img_hash in existing_hashes:
                    skipped_count += 1
                    print(f"  图片已存在(哈希匹配): {img}")
                    continue

                # 添加新图片
                selected_images[canonical_img] = tk.IntVar(value=1)
                new_images_count += 1
                existing_canonical_paths.add(canonical_img)
                existing_hashes.add(img_hash)
                folder = os.path.dirname(img)
                if get_canonical_path(folder) not in [get_canonical_path(d) for d in source_folders]:
                    source_folders.append(folder)  # 存储原始路径
        elif os.path.isfile(path):  # 如果是文件
            # 检查文件是否是有效图片
            has_valid_ext = path.lower().endswith(IMAGE_EXTENSIONS)
            if not has_valid_ext:
                print(f"  无效的图片扩展名: {path}")
                print(f"  扩展名: {os.path.splitext(path)[1]}")
                print(f"  支持的扩展名: {IMAGE_EXTENSIONS}")
                continue
            # 规范化图片路径
            canonical_img = get_canonical_path(path)
            print(f"  规范路径: {canonical_img}")
            # 先通过规范路径快速比较
            if canonical_img in existing_canonical_paths:
                skipped_count += 1
                print(f"  图片已存在(路径匹配): {path}")
                continue
            # 再通过文件哈希值精确比较
            img_hash = get_file_hash(path)
            print(f"  哈希值: {img_hash}")
            if img_hash is None:
                print(f"  计算文件哈希失败，跳过图片: {path}")
                skipped_count += 1
                continue
            elif img_hash in existing_hashes:
                skipped_count += 1
                print(f"  图片已存在(哈希匹配): {path}")
                continue
            # 确认是新图片
            print(f"  添加新图片: {path}")
            dropped_image_paths.append(path)
            selected_images[canonical_img] = tk.IntVar(value=1)
            new_images_count += 1
            existing_canonical_paths.add(canonical_img)
            existing_hashes.add(img_hash)
            folder = os.path.dirname(path)
            if get_canonical_path(folder) not in [get_canonical_path(d) for d in source_folders]:
                source_folders.append(folder)  # 存储原始路径
        else:
            print(f"  无效路径: {path}")
    if new_images_count > 0:
        print(f"\n通过拖拽添加了 {new_images_count} 张新图片")
    if skipped_count > 0:
        print(f"跳过了 {skipped_count} 张已存在的图片")
    else:
        print("没有发现新图片")
    folder_entry.delete(0, tk.END)
    folder_entry.insert(0, ", ".join(source_folders))
    preview_images()
    update_selected_count()

def update_selected_count():
    # 过滤掉无效的键
    valid_selected_images = {k: v for k, v in selected_images.items() if k}
    selected_count = sum(v.get() for v in valid_selected_images.values())
    total_count = len(valid_selected_images)
    process_button.config(text=f"处理图片({selected_count}/{total_count}张)")

def add_processed_text(image):
    draw = ImageDraw.Draw(image)
    # 尝试加载支持中文的字体
    try:
        # Windows系统字体路径
        font = ImageFont.truetype("simhei.ttf", 16)
    except IOError:
        try:
            # Linux系统字体路径
            font = ImageFont.truetype("/usr/share/fonts/truetype/wqy/wqy-microhei.ttf", 16)
        except IOError:
            try:
                # macOS系统字体路径
                font = ImageFont.truetype("/System/Library/Fonts/PingFang.ttc", 16)
            except IOError:
                # 如果找不到任何中文字体，则使用默认字体
                font = ImageFont.load_default()
                print("警告: 无法加载中文字体，将使用默认字体")

    # 获取图片尺寸
    width, height = image.size
    # 获取文字的边界框
    bbox = draw.textbbox((0, 0), "已处理", font=font)
    text_width = bbox[2] - bbox[0]
    text_height = bbox[3] - bbox[1]
    # 计算居中位置
    position = ((width - text_width) // 2, (height - text_height) // 2)
    # 绘制绿色文字
    draw.text(position, "已处理", fill=(0, 255, 0), font=font)
    return image

def process_images():
    if not source_folders:
        messagebox.showerror("错误", "请选择图片文件夹。")
        return
    
    # 检查输入框是否为空，如果为空则设置为 'auto'
    horizontal_width = horizontal_width_entry.get() if horizontal_width_entry.get() else 'auto'
    horizontal_height = horizontal_height_entry.get() if horizontal_height_entry.get() else 'auto'
    vertical_width = vertical_width_entry.get() if vertical_width_entry.get() else 'auto'
    vertical_height = vertical_height_entry.get() if vertical_height_entry.get() else 'auto'
    
    save_mode = save_mode_var.get()
    save_dir = None
    if save_mode == "另存":
        save_dir = filedialog.askdirectory()
        if not save_dir:
            return
    
    # 获取用户选择的目标格式
    target_format = target_format_var.get()
    
    # 收集所有图片文件并规范化路径格式
    image_files = []
    for folder in source_folders:
        folder_images = get_image_files(folder)
        image_files.extend(folder_images)

    # 只处理在selected_images字典中存在且被选中的图片文件
    selected_image_files = []
    for img in image_files:
        canonical_img = get_canonical_path(img)
        if canonical_img in selected_images and selected_images[canonical_img].get() == 1:
            selected_image_files.append(img)

    # 调试信息：打印找到的图片数量和选中的图片数量
    print(f"找到 {len(image_files)} 张图片")
    print(f"选中 {len(selected_image_files)} 张图片进行处理")
    
    if not selected_image_files:
        messagebox.showinfo("提示", "没有选中任何图片进行处理")
        return
    
    total_images = len(selected_image_files)
    processed_count = 0
    failed_count = 0
    failed_images = []

    # 显示进度条
    progress_bar['maximum'] = total_images
    progress_bar['value'] = 0
    root.update()

    # 处理所有选中的图片
    for i, image_path in enumerate(selected_image_files):
        try:
            # 更新进度条文本
            progress_text.config(text=f"正在处理: {os.path.basename(image_path)} ({i+1}/{total_images})")
            root.update()
            
            with Image.open(image_path) as img:
                width, height = img.size
                if width < height:
                    new_width = vertical_width
                    new_height = vertical_height
                else:
                    new_width = horizontal_width
                    new_height = horizontal_height
                
                # 使用规范化路径调用resize_image
                success, result = resize_image(
                    image_path, 
                    new_width, 
                    new_height, 
                    save_mode, 
                    save_dir, 
                    source_folders[0].replace('\\', '/'),
                    target_format
                )
                
                # 在 resize_image 成功后更新UI状态
                if success:
                    processed_count += 1
                    print(f"已处理 {processed_count}/{total_images}: {image_path}")

                    # 使用 get_canonical_path 正确获取规范路径
                    normalized_path = get_canonical_path(image_path)

                    # 取消处理好的图片的选中状态
                    if normalized_path in selected_images:
                        selected_images[normalized_path].set(0)

                    # 更新预览图
                    if normalized_path in image_frame_map:
                        frame, label = image_frame_map[normalized_path]
                        frame.config(highlightbackground="white", highlightcolor="white")

                        # 在预览图上添加“已处理”文字
                        img = Image.open(image_path)
                        img.thumbnail((100, 100))
                        img = add_processed_text(img)
                        photo = ImageTk.PhotoImage(img)
                        label.config(image=photo)
                        label.image = photo
                else:
                    failed_count += 1
                    failed_images.append((image_path, result))
                    print(f"处理失败 {failed_count}: {image_path}, 错误: {result}")
                
                # 更新进度条
                progress_bar['value'] = processed_count
                root.update()
                
        except Exception as e:
            failed_count += 1
            error_msg = f"处理 {image_path} 时出错: {str(e)}"
            failed_images.append((image_path, error_msg))
            print(error_msg)
            # 继续处理其他图片

    # 重置进度条文本
    progress_text.config(text="处理完成")
    
    # 显示处理结果
    result_msg = f"处理完成！\n成功: {processed_count} 张\n失败: {failed_count} 张"
    if failed_count > 0:
        result_msg += "\n\n处理失败的图片:"
        for path, error in failed_images[:5]:  # 只显示前5个错误，避免对话框过大
            result_msg += f"\n- {os.path.basename(path)}: {error}"
        if failed_count > 5:
            result_msg += f"\n... 以及其他 {failed_count-5} 张图片"
        messagebox.showwarning("处理结果", result_msg)
    else:
        messagebox.showinfo("处理结果", result_msg)
    
    update_selected_count()

def clear_list():
    global source_folders, selected_images, image_frame_map
    # 清空文件夹列表
    source_folders = []
    folder_entry.delete(0, tk.END)
    
    # 清空图片选择信息
    selected_images = {}
    image_frame_map = {}
    
    # 清空预览区域
    for widget in preview_frame.winfo_children():
        widget.destroy()
    
    # 更新处理按钮文本
    update_selected_count()

root = TkinterDnD.Tk()  # 使用 TkinterDnD 的 Tk 类
root.title("批量图片改尺寸")
root.geometry("600x700")
root.configure(bg="#fff")

# 获取图标文件的路径
def get_icon_path():
    if getattr(sys, 'frozen', False):  # 判断是否被打包
        base_dir = sys._MEIPASS  # 打包后的临时目录
    else:
        base_dir = os.path.dirname(__file__)  # 开发环境中的目录
    return os.path.join(base_dir, 'app_icon.ico')

# 设置窗口图标
icon_path = get_icon_path()
if os.path.exists(icon_path):
    root.iconbitmap(icon_path)

# 文件夹选择
folder_frame = tk.Frame(root, bg="#fff")
folder_frame.pack(pady=10, fill=tk.X)
folder_label = tk.Label(folder_frame, text="选择图片文件夹:", bg="#fff")
folder_label.pack(side=tk.LEFT, padx=5)
folder_entry = tk.Entry(folder_frame, width=30, font=("Arial", 10), bd=1, relief=tk.SOLID)  # 设置字体大小以调整高度
folder_entry.pack(side=tk.LEFT, padx=5, expand=True, fill=tk.X)
select_folder_button = tk.Button(folder_frame, text="选择文件夹", bg="#0078d7", width=10, height=1, command=select_folder,
                                 font=("Arial", 10), border="0", fg="white")
select_folder_button.pack(side=tk.LEFT, padx=5)

# 清空列表按钮
clear_button = tk.Button(folder_frame, text="清空列表", bg="#0078d7", width=10, height=1, command=clear_list,
                         font=("Arial", 10), border="0", fg="white")
clear_button.pack(side=tk.LEFT, padx=5)

# 宽高设置 - 使用两个独立的Frame
width_frame = tk.Frame(root, bg="#fff")
width_frame.pack(pady=10, fill=tk.X)

# 横版图片设置
horizontal_frame = tk.Frame(width_frame, bg="#fff")
horizontal_frame.pack(pady=5, fill=tk.X)
horizontal_label = tk.Label(horizontal_frame, text="横版图片设置:", bg="#fff", font=("Arial", 10, "bold"))
horizontal_label.pack(side=tk.LEFT, padx=5)
horizontal_width_label = tk.Label(horizontal_frame, text="宽度:", bg="#fff")
horizontal_width_label.pack(side=tk.LEFT, padx=5)
horizontal_width_entry = tk.Entry(horizontal_frame, width=10, bd=1, relief=tk.SOLID)
horizontal_width_entry.insert(0, "auto")
horizontal_width_entry.pack(side=tk.LEFT, padx=5)
horizontal_height_label = tk.Label(horizontal_frame, text="高度:", bg="#fff")
horizontal_height_label.pack(side=tk.LEFT, padx=5)
horizontal_height_entry = tk.Entry(horizontal_frame, width=10, bd=1, relief=tk.SOLID)
horizontal_height_entry.insert(0, "auto")
horizontal_height_entry.pack(side=tk.LEFT, padx=5)

# 竖版图片设置
vertical_frame = tk.Frame(width_frame, bg="#fff")
vertical_frame.pack(pady=5, fill=tk.X)
vertical_label = tk.Label(vertical_frame, text="竖版图片设置:", bg="#fff", font=("Arial", 10, "bold"))
vertical_label.pack(side=tk.LEFT, padx=5)
vertical_width_label = tk.Label(vertical_frame, text="宽度:", bg="#fff")
vertical_width_label.pack(side=tk.LEFT, padx=5)
vertical_width_entry = tk.Entry(vertical_frame, width=10, bd=1, relief=tk.SOLID)
vertical_width_entry.insert(0, "auto")
vertical_width_entry.pack(side=tk.LEFT, padx=5)
vertical_height_label = tk.Label(vertical_frame, text="高度:", bg="#fff")
vertical_height_label.pack(side=tk.LEFT, padx=5)
vertical_height_entry = tk.Entry(vertical_frame, width=10, bd=1, relief=tk.SOLID)
vertical_height_entry.insert(0, "auto")
vertical_height_entry.pack(side=tk.LEFT, padx=5)

# 保存方式选择
save_mode_frame = tk.Frame(root, bg="#fff")
save_mode_frame.pack(pady=10, fill=tk.X)
save_mode_label = tk.Label(save_mode_frame, text="保存方式:", bg="#fff")
save_mode_label.pack(side=tk.LEFT, padx=5)
save_mode_var = tk.StringVar(root)
save_mode_var.set("覆盖原图")
radio1 = tk.Radiobutton(save_mode_frame, text="覆盖原图", variable=save_mode_var, value="覆盖原图", bg="#fff")
radio1.pack(side=tk.LEFT, padx=5)
radio2 = tk.Radiobutton(save_mode_frame, text="另存", variable=save_mode_var, value="另存", bg="#fff")
radio2.pack(side=tk.LEFT, padx=5)

# 目标格式选择
target_format_frame = tk.Frame(root, bg="#fff")
target_format_frame.pack(pady=10, fill=tk.X)
target_format_label = tk.Label(target_format_frame, text="目标格式:", bg="#fff")
target_format_label.pack(side=tk.LEFT, padx=5)
target_format_var = tk.StringVar(root)
target_format_var.set(TARGET_FORMATS[0])
target_format_menu = tk.OptionMenu(target_format_frame, target_format_var, *TARGET_FORMATS)
target_format_menu.pack(side=tk.LEFT, padx=5)

# 图片预览
preview_frame = tk.Frame(root, bg="#fff")
preview_frame.pack(pady=10, fill=tk.BOTH, expand=True)
scrollbar = tk.Scrollbar(preview_frame, orient=tk.VERTICAL)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
canvas = tk.Canvas(preview_frame, yscrollcommand=scrollbar.set)
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.config(command=canvas.yview)
canvas_frame = tk.Frame(canvas)
canvas.create_window((0, 0), window=canvas_frame, anchor=tk.NW)
canvas_frame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
preview_frame = canvas_frame

# 进度条和进度文本
progress_frame = tk.Frame(root, bg="#fff")
progress_frame.pack(pady=5, fill=tk.X)
progress_bar = ttk.Progressbar(progress_frame, orient=tk.HORIZONTAL, length=500, mode='determinate')
progress_bar.pack(side=tk.LEFT, fill=tk.X, expand=True)
progress_text = tk.Label(progress_frame, text="准备就绪", bg="#fff", width=20)
progress_text.pack(side=tk.LEFT, padx=5)

# 处理按钮
process_button = tk.Button(root, text="开始处理图片(0张)", command=process_images, bg="#0078d7", fg="white",
                           font=("Arial", 10), border="0", height="2")
process_button.pack(pady=10, fill=tk.X)

selected_images = {}
source_folders = []
image_frame_map = {}

root.drop_target_register(DND_FILES)
root.dnd_bind('<<Drop>>', drop)

root.mainloop()