import cv2
import numpy as np
import tkinter as tk
from tkinter import filedialog, Scrollbar, Toplevel
from PIL import Image, ImageTk
import os
import traceback 

class UserSelection:
    def __init__(self):
        self.point = None

def process_image(image_path, point):
    """
    根据给定的点，裁剪和填充图像。（此函数无需更改）
    """
    x_center, y_center = point
    img = cv2.imread(image_path)
    if img is None:
        print(f"错误：无法在 process_image 中读取图片：{image_path}")
        return
    height, width, _ = img.shape
    left_width = 1842
    right_width = 557
    total_width = 2400
    left_start_index = x_center - left_width
    left_part_img = img[:, max(0, left_start_index):x_center]
    if left_start_index < 0:
        padding_needed = abs(left_start_index)
        left_border_pixel = img[:, 0:1]
        padding = cv2.repeat(left_border_pixel, 1, padding_needed)
        left_part_img = np.hstack([padding, left_part_img])
    right_end_index = x_center + 1 + right_width
    right_part_img = img[:, x_center + 1:min(width, right_end_index)]
    if right_end_index > width:
        padding_needed = right_end_index - width
        right_border_pixel = img[:, width-1:width]
        padding = cv2.repeat(right_border_pixel, 1, padding_needed)
        right_part_img = np.hstack([right_part_img, padding])
    center_pixel = img[:, x_center:x_center+1]
    final_image = np.hstack([left_part_img, center_pixel, right_part_img])
    final_image = final_image[:, :total_width]
    path_without_ext, ext = os.path.splitext(image_path)
    new_image_path = f"{path_without_ext}_pos{ext}"
    cv2.imwrite(new_image_path, final_image)
    print(f"处理完成！新图片已保存为：{new_image_path}")
    cv2.imshow('Processed Image (Press any key to close)', final_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def show_image_and_get_point(main_root, image_path, selection_obj):
    """
    使用Toplevel窗口显示图像，等待用户点击，并通过selection_obj返回结果。
    """
    try:
        image_window = Toplevel(main_root)
        image_window.title(f"Select a point on the image: {os.path.basename(image_path)}")
        image_window.protocol("WM_DELETE_WINDOW", image_window.destroy)
        
        frame = tk.Frame(image_window)
        frame.pack(fill=tk.BOTH, expand=True)

        x_scrollbar = Scrollbar(frame, orient=tk.HORIZONTAL)
        x_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)
        y_scrollbar = Scrollbar(frame, orient=tk.VERTICAL)
        y_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        canvas = tk.Canvas(frame, xscrollcommand=x_scrollbar.set, yscrollcommand=y_scrollbar.set)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        x_scrollbar.config(command=canvas.xview)
        y_scrollbar.config(command=canvas.yview)

        img_cv = cv2.imread(image_path)
        if img_cv is None:
            print(f"\n!!!!!! [错误] OpenCV (cv2.imread) 无法加载图片: {image_path} !!!!!!\n")
            image_window.destroy()
            return

        img_pil = Image.fromarray(cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB))
        photo = ImageTk.PhotoImage(image=img_pil)
        
        canvas.create_image(0, 0, anchor=tk.NW, image=photo)
        canvas.image = photo
        canvas.config(scrollregion=canvas.bbox(tk.ALL))

        def on_mouse_click(event):
            x = canvas.canvasx(event.x)
            y = canvas.canvasy(event.y)
            selection_obj.point = (int(x), int(y))
            image_window.destroy()

        canvas.bind("<Button-1>", on_mouse_click)
        
        # ******** 窗口管理代码 ********
        # 设置初始窗口大小
        image_window.geometry("1000x300")

        # 将窗口置于最前端
        image_window.lift()
        image_window.attributes('-topmost', True)
        image_window.attributes('-topmost', False)
        
        # 强制窗口获得焦点
        image_window.focus_force()
        # *****************************

        main_root.wait_window(image_window)

    except Exception as e:
        print("\n!!!!!! [致命错误] 在 show_image_and_get_point 函数中发生未处理的异常 !!!!!!")
        traceback.print_exc()
        print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n")


if __name__ == "__main__":
    root = tk.Tk()
    root.withdraw() 
    
    file_path = filedialog.askopenfilename(
        parent=root,
        title="选择一张图片",
        filetypes=[("Image Files", "*.jpg *.jpeg *.png *.bmp *.tif *.tiff")]
    )
    
    if file_path:
        selection = UserSelection()
        show_image_and_get_point(root, file_path, selection)
        
        if selection.point:
            process_image(file_path, selection.point)
        else:
            print("未选择任何点或窗口被关闭。程序退出。")
    else:
        print("用户未选择任何文件。")

    root.destroy()
