import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk
import os

class PaletteApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图片主色调提取")
        self.root.geometry("700x620")

        top = ttk.Frame(root, padding=8)
        top.pack(fill=tk.X)
        ttk.Button(top, text="选择图片", command=self.load_image).pack(side=tk.LEFT)
        self.path_label = ttk.Label(top, text="未选择图片")
        self.path_label.pack(side=tk.LEFT, padx=10)

        self.preview = tk.Label(root, bg="#dddddd", height=20)
        self.preview.pack(fill=tk.BOTH, expand=True, padx=8, pady=5)

        self.palette_frame = ttk.Frame(root, padding=8)
        self.palette_frame.pack(fill=tk.X)

        self.image_path = None
        self.photo = None

    def load_image(self):
        path = filedialog.askopenfilename(
            title="选择图片",
            filetypes=[("图片文件", "*.jpg *.jpeg *.png *.bmp *.gif *.webp")])
        if not path:
            return
        self.image_path = path
        self.path_label.config(text=os.path.basename(path))

        img = Image.open(path).convert("RGB")
        img.thumbnail((660, 380))
        self.photo = ImageTk.PhotoImage(img)
        self.preview.config(image=self.photo, height=img.height)

        self.extract_colors()

    def extract_colors(self):
        for w in self.palette_frame.winfo_children():
            w.destroy()

        try:
            img = Image.open(self.image_path).convert("RGB")
            # 缩小以加速，再量化成 8 种颜色
            img.thumbnail((200, 200))
            quant = img.quantize(colors=8, method=Image.MEDIANCUT)
            palette = quant.getpalette()  # [r,g,b, r,g,b, ...]
            counts = sorted(quant.getcolors(), reverse=True)  # [(count, index), ...]

            colors = []
            for count, idx in counts:
                r, g, b = palette[idx*3: idx*3+3]
                colors.append((r, g, b))
        except Exception as e:
            messagebox.showerror("错误", f"提取颜色失败：{e}")
            return

        for i, rgb in enumerate(colors):
            hex_code = "#{:02X}{:02X}{:02X}".format(*rgb)
            cell = ttk.Frame(self.palette_frame)
            cell.grid(row=0, column=i, padx=4)

            swatch = tk.Label(cell, bg=hex_code, width=8, height=3,
                              relief="solid", borderwidth=1, cursor="hand2")
            swatch.pack()
            label = ttk.Label(cell, text=hex_code, cursor="hand2")
            label.pack(pady=2)

            for widget in (swatch, label):
                widget.bind("<Button-1>", lambda e, h=hex_code: self.copy_hex(h))

        ttk.Label(self.palette_frame, text="（点击色块或色号可复制）",
                  foreground="gray").grid(row=1, column=0, columnspan=8, pady=6)

    def copy_hex(self, hex_code):
        self.root.clipboard_clear()
        self.root.clipboard_append(hex_code)
        self.root.update()
        messagebox.showinfo("已复制", f"色号 {hex_code} 已复制到剪贴板")


if __name__ == "__main__":
    root = tk.Tk()
    app = PaletteApp(root)
    root.mainloop()