py屏幕颜色信息提取

abs8023 / 2025-01-15 / 原文

from tkinter import simpledialog, messagebox
from colorspacious import cspace_convert
from PIL import Image
from PIL import ImageGrab

import atexit
import tkinter as tk
import pyautogui
import colorspacious
import colorsys
import numpy as np

# 创建主窗口
root = tk.Tk()
root.title("GetPixelColor")
root.iconbitmap("xxxxx.ico")  # 替换为图标文件的实际路径
root.geometry("400x200")
# root.attributes("-topmost", True) #窗口固定前端显示
# 创建菜单条
menu_bar = tk.Menu(root)
root.config(menu=menu_bar)

# 创建“视图”菜单
view_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="视图", menu=view_menu)
# view_menu.add_separator()  # 添加分隔符
# view_menu.add_command(label="刷新窗口", command=lambda: root.update())

# 创建菜单项来设置窗口是否在最上层
topmost_var = tk.BooleanVar()  # 创建一个布尔变量来存储窗口是否在最上层的状态
topmost_var.set(False)  # 默认窗口不在最上层

def set_topmost(state):
    topmost_var.set(state)
    root.attributes("-topmost", state)  # 设置窗口是否在最上层

# 添加“始终在最上层”菜单项,并设置命令
view_menu.add_checkbutton(label="前端显示", variable=topmost_var, command=lambda: set_topmost(topmost_var.get()))

# 创建“关于”菜单
about_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="关于", menu=about_menu)

# 添加“关于”菜单项(示例)
about_menu.add_command(label="关于本软件", command=lambda: messagebox.showinfo("关于", "提取鼠标位置的颜色信息,每100ms刷新一次信息。"))
about_menu.add_command(label="版本信息", command=lambda: messagebox.showinfo("版本", "v2024.10.28.01"))


# 创建并放置标签,用于显示鼠标位置
label_position = tk.Label(root, text="鼠标位置: X=?, Y=?")
label_position.grid(row=1, column=0, padx=5, pady=5, sticky="w")  # 使用grid方法,设置sticky="w"左对齐

# 创建用于显示颜色信息的标签
color_label_rgb = tk.Label(root, text="位置 ({x}, {y}) 的RGB值是: ???")
color_label_rgb.grid(row=2, column=0, padx=5, pady=5, sticky="w")  # 使用grid方法,设置sticky="w"左对齐
color_label_lab = tk.Label(root, text="位置 ({x}, {y}) 的LAB值是: ???")
color_label_lab.grid(row=3, column=0, padx=5, pady=5, sticky="w")  # 使用grid方法,设置sticky="w"左对齐
color_label_hsv = tk.Label(root, text="位置 ({x}, {y}) 的HSV值是: ???")
color_label_hsv.grid(row=4, column=0, padx=5, pady=5, sticky="w")  # 使用grid方法,设置sticky="w"左对齐
color_label_hsl = tk.Label(root, text="位置 ({x}, {y}) 的HSL值是: ???")
color_label_hsl.grid(row=5, column=0, padx=5, pady=5, sticky="w")  # 使用grid方法,设置sticky="w"左对齐

def get_screen_color(event=None):
    # 获取鼠标当前位置
    x, y = root.winfo_pointerxy()  # 获取相对于屏幕的x坐标
    #y = root.winfo_pointery()  # 获取相对于屏幕的y坐标
    # 更新标签文本
    label_position.config(text=f"鼠标位置: X={x}, Y={y}")
    0.
    if x is None or y is None:
        messagebox.showerror("鼠标位置错误", "移动鼠标位置至屏幕取色位置")
        return
   
#    # 获取屏幕截图并提取颜色
    screenshot = pyautogui.screenshot()
    rgb_color = screenshot.getpixel((x, y))

    # 在界面上显示RGB颜色信息_10进制
    color_label_rgb.config(text=f"位置 ({x}, {y}) 的颜色RGB是: {rgb_color}")    
 
    # rgb转换到0到1范围
    rgb_color_normalized = tuple(c / 255.0 for c in rgb_color)
    lab_color = colorspacious.cspace_convert(rgb_color_normalized, "sRGB1", "CIELab")
    lab_color_rounded2 = tuple(float(round(value , 2)) for value in lab_color)
    hsv_color = colorsys.rgb_to_hsv(*rgb_color_normalized)
    HSV_h_color, HSV_s_color, HSV_v_color = hsv_color
    HSV_h = round(float(HSV_h_color * 360.0), 2)
    HSV_s = round(float(HSV_s_color * 100.0), 2)
    HSV_v = round(float(HSV_v_color * 100.0), 2)

    hsl_color = colorsys.rgb_to_hls(*rgb_color_normalized)
    HSL_h_color, HSL_l_color, HSL_s_color = hsl_color
    HSL_h = round(HSL_h_color * 360, 2)
    HSL_s = round(HSL_s_color * 100, 2)
    HSL_l = round(HSL_l_color * 100, 2)


    # 在界面上显示RGB颜色信息_10进制
    color_label_lab.config(text=f"位置 ({x}, {y}) 的LAB值是: {lab_color_rounded2}")  
    color_label_hsv.config(text=f"位置 ({x}, {y}) 的HSV值是: {HSV_h, HSV_s, HSV_v}")  
    color_label_hsl.config(text=f"位置 ({x}, {y}) 的HSL值是: {HSL_h, HSL_s, HSL_l}")  
                 
    root.after(100, get_screen_color)

# 设置定时器,每隔100毫秒更新一次鼠标位置和颜色信息
root.after(100, get_screen_color)

# 在启动时调用一次函数以获取初始颜色
get_screen_color()

# 定义在程序退出时要执行的清理函数
def cleanup():
    # 这里可以添加任何需要在程序退出前执行的清理操作
    # 对于Tkinter,通常不需要手动销毁窗口,因为mainloop退出时会自动销毁
    # 但如果你有其他需要清理的资源,可以在这里添加代码
    print("程序即将退出,执行清理操作...")

# 注册清理函数
atexit.register(cleanup)

# 启动主循环
try:
    root.mainloop()
except KeyboardInterrupt:  # 处理Ctrl+C中断
    print("检测到Ctrl+C,程序即将退出...")
    root.destroy()  # 确保Tk窗口被销毁(尽管在atexit中通常不需要,但这里为了完整性添加)