重构移动utils文件夹
This commit is contained in:
901
app/views/panels/cct_panel.py
Normal file
901
app/views/panels/cct_panel.py
Normal file
@@ -0,0 +1,901 @@
|
||||
"""CCT 参数面板及其处理函数(Step 6 重构)。"""
|
||||
|
||||
import time
|
||||
import traceback
|
||||
from tkinter import messagebox
|
||||
import tkinter as tk
|
||||
import ttkbootstrap as ttk
|
||||
|
||||
import algorithm.pq_algorithm as pq_algorithm
|
||||
|
||||
def create_cct_params_frame(self):
|
||||
"""创建色度参数设置区域 - 屏模组、SDR、HDR 独立(✅ 增加色域参考标准选择 + 单步调试按钮)"""
|
||||
|
||||
# ==================== 屏模组色度参数 Frame ====================
|
||||
self.cct_params_frame = ttk.LabelFrame(
|
||||
self.test_items_frame, text="色度参数设置(屏模组)"
|
||||
)
|
||||
|
||||
# 默认值
|
||||
self.DEFAULT_CCT_PARAMS = {
|
||||
"x_ideal": 0.3127,
|
||||
"x_tolerance": 0.003,
|
||||
"y_ideal": 0.3290,
|
||||
"y_tolerance": 0.003,
|
||||
}
|
||||
|
||||
# 从配置读取屏模组参数
|
||||
saved_params = self.config.current_test_types.get("screen_module", {}).get(
|
||||
"cct_params", self.DEFAULT_CCT_PARAMS.copy()
|
||||
)
|
||||
|
||||
# 色域参考标准
|
||||
saved_gamut_ref = self.config.current_test_types.get("screen_module", {}).get(
|
||||
"gamut_reference", "DCI-P3"
|
||||
)
|
||||
|
||||
# 创建屏模组变量
|
||||
self.cct_x_ideal_var = tk.StringVar(
|
||||
value=str(saved_params.get("x_ideal", 0.3127))
|
||||
)
|
||||
self.cct_x_tolerance_var = tk.StringVar(
|
||||
value=str(saved_params.get("x_tolerance", 0.003))
|
||||
)
|
||||
self.cct_y_ideal_var = tk.StringVar(
|
||||
value=str(saved_params.get("y_ideal", 0.3290))
|
||||
)
|
||||
self.cct_y_tolerance_var = tk.StringVar(
|
||||
value=str(saved_params.get("y_tolerance", 0.003))
|
||||
)
|
||||
self.screen_gamut_ref_var = tk.StringVar(value=saved_gamut_ref)
|
||||
|
||||
# 创建屏模组输入框(左侧:色度参数)
|
||||
params = [
|
||||
("x-ideal:", self.cct_x_ideal_var, "x_ideal"),
|
||||
("x-tolerance:", self.cct_x_tolerance_var, "x_tolerance"),
|
||||
("y-ideal:", self.cct_y_ideal_var, "y_ideal"),
|
||||
("y-tolerance:", self.cct_y_tolerance_var, "y_tolerance"),
|
||||
]
|
||||
|
||||
for i, (label_text, var, key) in enumerate(params):
|
||||
ttk.Label(self.cct_params_frame, text=label_text).grid(
|
||||
row=i, column=0, sticky=tk.W, padx=5, pady=3
|
||||
)
|
||||
entry = ttk.Entry(self.cct_params_frame, textvariable=var, width=15)
|
||||
entry.grid(row=i, column=1, sticky=tk.W, padx=5, pady=3)
|
||||
|
||||
# 绑定失去焦点事件
|
||||
default_val = self.DEFAULT_CCT_PARAMS[key]
|
||||
entry.bind(
|
||||
"<FocusOut>",
|
||||
lambda e, v=var, d=default_val: self.on_cct_param_focus_out(v, d),
|
||||
)
|
||||
|
||||
# 色域参考标准选择(右侧第一行)
|
||||
ttk.Label(self.cct_params_frame, text="色域参考标准:").grid(
|
||||
row=0, column=2, sticky=tk.W, padx=(20, 5), pady=3
|
||||
)
|
||||
screen_gamut_combo = ttk.Combobox(
|
||||
self.cct_params_frame,
|
||||
textvariable=self.screen_gamut_ref_var,
|
||||
values=["BT.2020", "BT.709", "DCI-P3"],
|
||||
state="disabled",
|
||||
width=12,
|
||||
)
|
||||
screen_gamut_combo.grid(row=0, column=3, sticky=tk.W, padx=5, pady=3)
|
||||
screen_gamut_combo.bind(
|
||||
"<<ComboboxSelected>>", self.on_screen_gamut_ref_changed
|
||||
)
|
||||
self.screen_gamut_combo = screen_gamut_combo
|
||||
|
||||
# ==================== ✅ 单步调试按钮(右侧第二行)====================
|
||||
ttk.Label(self.cct_params_frame, text="单步调试:").grid(
|
||||
row=1, column=2, sticky=tk.W, padx=(20, 5), pady=3
|
||||
)
|
||||
|
||||
self.screen_debug_btn = ttk.Button(
|
||||
self.cct_params_frame,
|
||||
text="打开调试面板",
|
||||
command=self.toggle_screen_debug_panel,
|
||||
bootstyle="info-outline",
|
||||
state=tk.DISABLED, # 初始禁用
|
||||
width=15,
|
||||
)
|
||||
self.screen_debug_btn.grid(row=1, column=3, sticky=tk.W, padx=5, pady=3)
|
||||
|
||||
# 重新计算按钮(屏模组)
|
||||
self.recalc_cct_btn = ttk.Button(
|
||||
self.cct_params_frame,
|
||||
text="应用新参数并重绘",
|
||||
command=self.recalculate_cct,
|
||||
bootstyle="success",
|
||||
)
|
||||
self.recalc_cct_btn.grid(
|
||||
row=4, column=0, columnspan=2, pady=10, padx=5, sticky="ew"
|
||||
)
|
||||
self.recalc_cct_btn.grid_remove()
|
||||
|
||||
# 色域重新计算按钮
|
||||
self.recalc_gamut_btn = ttk.Button(
|
||||
self.cct_params_frame,
|
||||
text="应用色域参考并重绘",
|
||||
command=self.recalculate_gamut,
|
||||
bootstyle="warning",
|
||||
)
|
||||
self.recalc_gamut_btn.grid(
|
||||
row=4, column=2, columnspan=2, pady=10, padx=5, sticky="ew"
|
||||
)
|
||||
self.recalc_gamut_btn.grid_remove()
|
||||
|
||||
# 提示文字
|
||||
ttk.Label(
|
||||
self.cct_params_frame,
|
||||
text="提示: 清空输入框将恢复默认值",
|
||||
font=("SimHei", 8),
|
||||
foreground="gray",
|
||||
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
||||
|
||||
# ==================== SDR 色度参数 Frame ====================
|
||||
self.sdr_cct_params_frame = ttk.LabelFrame(
|
||||
self.test_items_frame, text="色度参数设置(SDR)"
|
||||
)
|
||||
|
||||
# SDR 默认值
|
||||
self.SDR_DEFAULT_CCT_PARAMS = {
|
||||
"x_ideal": 0.3127,
|
||||
"x_tolerance": 0.003,
|
||||
"y_ideal": 0.3290,
|
||||
"y_tolerance": 0.003,
|
||||
}
|
||||
|
||||
# 从配置读取 SDR 参数
|
||||
sdr_saved_params = self.config.current_test_types.get("sdr_movie", {}).get(
|
||||
"cct_params", self.SDR_DEFAULT_CCT_PARAMS.copy()
|
||||
)
|
||||
|
||||
# 色域参考标准
|
||||
sdr_saved_gamut_ref = self.config.current_test_types.get("sdr_movie", {}).get(
|
||||
"gamut_reference", "BT.709"
|
||||
)
|
||||
|
||||
# 创建 SDR 变量
|
||||
self.sdr_cct_x_ideal_var = tk.StringVar(
|
||||
value=str(sdr_saved_params.get("x_ideal", 0.3127))
|
||||
)
|
||||
self.sdr_cct_x_tolerance_var = tk.StringVar(
|
||||
value=str(sdr_saved_params.get("x_tolerance", 0.003))
|
||||
)
|
||||
self.sdr_cct_y_ideal_var = tk.StringVar(
|
||||
value=str(sdr_saved_params.get("y_ideal", 0.3290))
|
||||
)
|
||||
self.sdr_cct_y_tolerance_var = tk.StringVar(
|
||||
value=str(sdr_saved_params.get("y_tolerance", 0.003))
|
||||
)
|
||||
self.sdr_gamut_ref_var = tk.StringVar(value=sdr_saved_gamut_ref)
|
||||
|
||||
# 创建 SDR 输入框
|
||||
sdr_params = [
|
||||
("x-ideal:", self.sdr_cct_x_ideal_var, "x_ideal"),
|
||||
("x-tolerance:", self.sdr_cct_x_tolerance_var, "x_tolerance"),
|
||||
("y-ideal:", self.sdr_cct_y_ideal_var, "y_ideal"),
|
||||
("y-tolerance:", self.sdr_cct_y_tolerance_var, "y_tolerance"),
|
||||
]
|
||||
|
||||
for i, (label_text, var, key) in enumerate(sdr_params):
|
||||
ttk.Label(self.sdr_cct_params_frame, text=label_text).grid(
|
||||
row=i, column=0, sticky=tk.W, padx=5, pady=3
|
||||
)
|
||||
entry = ttk.Entry(self.sdr_cct_params_frame, textvariable=var, width=15)
|
||||
entry.grid(row=i, column=1, sticky=tk.W, padx=5, pady=3)
|
||||
|
||||
# 绑定失去焦点事件
|
||||
default_val = self.SDR_DEFAULT_CCT_PARAMS[key]
|
||||
entry.bind(
|
||||
"<FocusOut>",
|
||||
lambda e, v=var, d=default_val: self.on_sdr_cct_param_focus_out(v, d),
|
||||
)
|
||||
|
||||
# 色域参考标准选择(右侧第一行)
|
||||
ttk.Label(self.sdr_cct_params_frame, text="色域参考标准:").grid(
|
||||
row=0, column=2, sticky=tk.W, padx=(20, 5), pady=3
|
||||
)
|
||||
sdr_gamut_combo = ttk.Combobox(
|
||||
self.sdr_cct_params_frame,
|
||||
textvariable=self.sdr_gamut_ref_var,
|
||||
values=["BT.2020", "BT.709", "DCI-P3"],
|
||||
state="disabled",
|
||||
width=12,
|
||||
)
|
||||
sdr_gamut_combo.grid(row=0, column=3, sticky=tk.W, padx=5, pady=3)
|
||||
sdr_gamut_combo.bind("<<ComboboxSelected>>", self.on_sdr_gamut_ref_changed)
|
||||
self.sdr_gamut_combo = sdr_gamut_combo
|
||||
|
||||
# ==================== ✅ SDR 单步调试按钮(右侧第二行)====================
|
||||
ttk.Label(self.sdr_cct_params_frame, text="单步调试:").grid(
|
||||
row=1, column=2, sticky=tk.W, padx=(20, 5), pady=3
|
||||
)
|
||||
|
||||
self.sdr_debug_btn = ttk.Button(
|
||||
self.sdr_cct_params_frame,
|
||||
text="打开调试面板",
|
||||
command=self.toggle_sdr_debug_panel,
|
||||
bootstyle="info-outline",
|
||||
state=tk.DISABLED, # 初始禁用
|
||||
width=15,
|
||||
)
|
||||
self.sdr_debug_btn.grid(row=1, column=3, sticky=tk.W, padx=5, pady=3)
|
||||
|
||||
# 重新计算按钮(SDR)
|
||||
self.sdr_recalc_cct_btn = ttk.Button(
|
||||
self.sdr_cct_params_frame,
|
||||
text="应用新参数并重绘",
|
||||
command=self.recalculate_cct,
|
||||
bootstyle="success",
|
||||
)
|
||||
self.sdr_recalc_cct_btn.grid(
|
||||
row=4, column=0, columnspan=2, pady=10, padx=5, sticky="ew"
|
||||
)
|
||||
self.sdr_recalc_cct_btn.grid_remove()
|
||||
|
||||
# 色域重新计算按钮(SDR)
|
||||
self.sdr_recalc_gamut_btn = ttk.Button(
|
||||
self.sdr_cct_params_frame,
|
||||
text="应用色域参考并重绘",
|
||||
command=self.recalculate_gamut,
|
||||
bootstyle="warning",
|
||||
)
|
||||
self.sdr_recalc_gamut_btn.grid(
|
||||
row=4, column=2, columnspan=2, pady=10, padx=5, sticky="ew"
|
||||
)
|
||||
self.sdr_recalc_gamut_btn.grid_remove()
|
||||
|
||||
# 提示文字
|
||||
ttk.Label(
|
||||
self.sdr_cct_params_frame,
|
||||
text="提示: 清空输入框将恢复默认值",
|
||||
font=("SimHei", 8),
|
||||
foreground="gray",
|
||||
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
||||
|
||||
# ==================== HDR 色度参数 Frame ====================
|
||||
self.hdr_cct_params_frame = ttk.LabelFrame(
|
||||
self.test_items_frame, text="色度参数设置(HDR)"
|
||||
)
|
||||
|
||||
# HDR 默认值
|
||||
self.HDR_DEFAULT_CCT_PARAMS = {
|
||||
"x_ideal": 0.3127,
|
||||
"x_tolerance": 0.003,
|
||||
"y_ideal": 0.3290,
|
||||
"y_tolerance": 0.003,
|
||||
}
|
||||
|
||||
# 从配置读取 HDR 参数
|
||||
hdr_saved_params = self.config.current_test_types.get("hdr_movie", {}).get(
|
||||
"cct_params", self.HDR_DEFAULT_CCT_PARAMS.copy()
|
||||
)
|
||||
|
||||
# 色域参考标准
|
||||
hdr_saved_gamut_ref = self.config.current_test_types.get("hdr_movie", {}).get(
|
||||
"gamut_reference", "BT.2020"
|
||||
)
|
||||
|
||||
# 创建 HDR 变量
|
||||
self.hdr_cct_x_ideal_var = tk.StringVar(
|
||||
value=str(hdr_saved_params.get("x_ideal", 0.3127))
|
||||
)
|
||||
self.hdr_cct_x_tolerance_var = tk.StringVar(
|
||||
value=str(hdr_saved_params.get("x_tolerance", 0.003))
|
||||
)
|
||||
self.hdr_cct_y_ideal_var = tk.StringVar(
|
||||
value=str(hdr_saved_params.get("y_ideal", 0.3290))
|
||||
)
|
||||
self.hdr_cct_y_tolerance_var = tk.StringVar(
|
||||
value=str(hdr_saved_params.get("y_tolerance", 0.003))
|
||||
)
|
||||
self.hdr_gamut_ref_var = tk.StringVar(value=hdr_saved_gamut_ref)
|
||||
|
||||
# 创建 HDR 输入框
|
||||
hdr_params = [
|
||||
("x-ideal:", self.hdr_cct_x_ideal_var, "x_ideal"),
|
||||
("x-tolerance:", self.hdr_cct_x_tolerance_var, "x_tolerance"),
|
||||
("y-ideal:", self.hdr_cct_y_ideal_var, "y_ideal"),
|
||||
("y-tolerance:", self.hdr_cct_y_tolerance_var, "y_tolerance"),
|
||||
]
|
||||
|
||||
for i, (label_text, var, key) in enumerate(hdr_params):
|
||||
ttk.Label(self.hdr_cct_params_frame, text=label_text).grid(
|
||||
row=i, column=0, sticky=tk.W, padx=5, pady=3
|
||||
)
|
||||
entry = ttk.Entry(self.hdr_cct_params_frame, textvariable=var, width=15)
|
||||
entry.grid(row=i, column=1, sticky=tk.W, padx=5, pady=3)
|
||||
|
||||
# 绑定失去焦点事件
|
||||
default_val = self.HDR_DEFAULT_CCT_PARAMS[key]
|
||||
entry.bind(
|
||||
"<FocusOut>",
|
||||
lambda e, v=var, d=default_val: self.on_hdr_cct_param_focus_out(v, d),
|
||||
)
|
||||
|
||||
# 色域参考标准选择(右侧第一行)
|
||||
ttk.Label(self.hdr_cct_params_frame, text="色域参考标准:").grid(
|
||||
row=0, column=2, sticky=tk.W, padx=(20, 5), pady=3
|
||||
)
|
||||
hdr_gamut_combo = ttk.Combobox(
|
||||
self.hdr_cct_params_frame,
|
||||
textvariable=self.hdr_gamut_ref_var,
|
||||
values=["BT.2020", "BT.709", "DCI-P3"],
|
||||
state="disabled",
|
||||
width=12,
|
||||
)
|
||||
hdr_gamut_combo.grid(row=0, column=3, sticky=tk.W, padx=5, pady=3)
|
||||
hdr_gamut_combo.bind("<<ComboboxSelected>>", self.on_hdr_gamut_ref_changed)
|
||||
self.hdr_gamut_combo = hdr_gamut_combo
|
||||
|
||||
# ==================== ✅ HDR 单步调试按钮(右侧第二行)====================
|
||||
ttk.Label(self.hdr_cct_params_frame, text="单步调试:").grid(
|
||||
row=1, column=2, sticky=tk.W, padx=(20, 5), pady=3
|
||||
)
|
||||
|
||||
self.hdr_debug_btn = ttk.Button(
|
||||
self.hdr_cct_params_frame,
|
||||
text="打开调试面板",
|
||||
command=self.toggle_hdr_debug_panel,
|
||||
bootstyle="info-outline",
|
||||
state=tk.DISABLED, # 初始禁用
|
||||
width=15,
|
||||
)
|
||||
self.hdr_debug_btn.grid(row=1, column=3, sticky=tk.W, padx=5, pady=3)
|
||||
|
||||
# 重新计算按钮(HDR)
|
||||
self.hdr_recalc_cct_btn = ttk.Button(
|
||||
self.hdr_cct_params_frame,
|
||||
text="应用新参数并重绘",
|
||||
command=self.recalculate_cct,
|
||||
bootstyle="success",
|
||||
)
|
||||
self.hdr_recalc_cct_btn.grid(
|
||||
row=4, column=0, columnspan=2, pady=10, padx=5, sticky="ew"
|
||||
)
|
||||
self.hdr_recalc_cct_btn.grid_remove()
|
||||
|
||||
# 色域重新计算按钮(HDR)
|
||||
self.hdr_recalc_gamut_btn = ttk.Button(
|
||||
self.hdr_cct_params_frame,
|
||||
text="应用色域参考并重绘",
|
||||
command=self.recalculate_gamut,
|
||||
bootstyle="warning",
|
||||
)
|
||||
self.hdr_recalc_gamut_btn.grid(
|
||||
row=4, column=2, columnspan=2, pady=10, padx=5, sticky="ew"
|
||||
)
|
||||
self.hdr_recalc_gamut_btn.grid_remove()
|
||||
|
||||
# 提示文字
|
||||
ttk.Label(
|
||||
self.hdr_cct_params_frame,
|
||||
text="提示: 清空输入框将恢复默认值",
|
||||
font=("SimHei", 8),
|
||||
foreground="gray",
|
||||
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
||||
|
||||
|
||||
def on_sdr_cct_param_focus_out(self, var, default_value):
|
||||
"""SDR 色度参数失去焦点时的处理"""
|
||||
try:
|
||||
value = var.get().strip()
|
||||
|
||||
if value == "":
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"✓ SDR 参数为空,恢复默认值: {default_value}")
|
||||
else:
|
||||
try:
|
||||
float_val = float(value)
|
||||
if float_val < 0 or float_val > 1:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(
|
||||
f"⚠️ SDR 参数超出范围,恢复默认值: {default_value}"
|
||||
)
|
||||
except ValueError:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"⚠️ SDR 参数无效,恢复默认值: {default_value}")
|
||||
|
||||
self.save_sdr_cct_params()
|
||||
except Exception as e:
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"处理 SDR 参数失败: {str(e)}")
|
||||
|
||||
|
||||
def save_sdr_cct_params(self):
|
||||
"""保存 SDR 色度参数"""
|
||||
try:
|
||||
|
||||
def get_float(var, default):
|
||||
try:
|
||||
value = var.get().strip()
|
||||
if value == "":
|
||||
return default
|
||||
return float(value)
|
||||
except:
|
||||
return default
|
||||
|
||||
sdr_cct_params = {
|
||||
"x_ideal": get_float(
|
||||
self.sdr_cct_x_ideal_var, self.SDR_DEFAULT_CCT_PARAMS["x_ideal"]
|
||||
),
|
||||
"x_tolerance": get_float(
|
||||
self.sdr_cct_x_tolerance_var,
|
||||
self.SDR_DEFAULT_CCT_PARAMS["x_tolerance"],
|
||||
),
|
||||
"y_ideal": get_float(
|
||||
self.sdr_cct_y_ideal_var, self.SDR_DEFAULT_CCT_PARAMS["y_ideal"]
|
||||
),
|
||||
"y_tolerance": get_float(
|
||||
self.sdr_cct_y_tolerance_var,
|
||||
self.SDR_DEFAULT_CCT_PARAMS["y_tolerance"],
|
||||
),
|
||||
}
|
||||
|
||||
if "sdr_movie" not in self.config.current_test_types:
|
||||
self.config.current_test_types["sdr_movie"] = {}
|
||||
|
||||
self.config.current_test_types["sdr_movie"]["cct_params"] = sdr_cct_params
|
||||
self.save_pq_config()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def on_hdr_cct_param_focus_out(self, var, default_value):
|
||||
"""HDR 色度参数失去焦点时的处理"""
|
||||
try:
|
||||
value = var.get().strip()
|
||||
|
||||
if value == "":
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"✓ HDR 参数为空,恢复默认值: {default_value}")
|
||||
else:
|
||||
try:
|
||||
float_val = float(value)
|
||||
if float_val < 0 or float_val > 1:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(
|
||||
f"⚠️ HDR 参数超出范围,恢复默认值: {default_value}"
|
||||
)
|
||||
except ValueError:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"⚠️ HDR 参数无效,恢复默认值: {default_value}")
|
||||
|
||||
self.save_hdr_cct_params()
|
||||
except Exception as e:
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"处理 HDR 参数失败: {str(e)}")
|
||||
|
||||
|
||||
def save_hdr_cct_params(self):
|
||||
"""保存 HDR 色度参数"""
|
||||
try:
|
||||
|
||||
def get_float(var, default):
|
||||
try:
|
||||
value = var.get().strip()
|
||||
if value == "":
|
||||
return default
|
||||
return float(value)
|
||||
except:
|
||||
return default
|
||||
|
||||
hdr_cct_params = {
|
||||
"x_ideal": get_float(
|
||||
self.hdr_cct_x_ideal_var, self.HDR_DEFAULT_CCT_PARAMS["x_ideal"]
|
||||
),
|
||||
"x_tolerance": get_float(
|
||||
self.hdr_cct_x_tolerance_var,
|
||||
self.HDR_DEFAULT_CCT_PARAMS["x_tolerance"],
|
||||
),
|
||||
"y_ideal": get_float(
|
||||
self.hdr_cct_y_ideal_var, self.HDR_DEFAULT_CCT_PARAMS["y_ideal"]
|
||||
),
|
||||
"y_tolerance": get_float(
|
||||
self.hdr_cct_y_tolerance_var,
|
||||
self.HDR_DEFAULT_CCT_PARAMS["y_tolerance"],
|
||||
),
|
||||
}
|
||||
|
||||
if "hdr_movie" not in self.config.current_test_types:
|
||||
self.config.current_test_types["hdr_movie"] = {}
|
||||
|
||||
self.config.current_test_types["hdr_movie"]["cct_params"] = hdr_cct_params
|
||||
self.save_pq_config()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def recalculate_cct(self):
|
||||
"""重新计算并绘制色度图"""
|
||||
try:
|
||||
# 1. 保存新参数
|
||||
self.save_cct_params()
|
||||
self.log_gui.log("✓ 色度参数已更新")
|
||||
|
||||
# 2. 收起配置项
|
||||
if hasattr(self, "config_panel_frame"):
|
||||
try:
|
||||
if self.config_panel_frame.winfo_viewable():
|
||||
self.config_panel_frame.btn.invoke()
|
||||
self.root.update_idletasks()
|
||||
time.sleep(0.1)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 3. 跳转到色度图Tab
|
||||
self.chart_notebook.select(self.cct_chart_frame)
|
||||
self.root.update_idletasks()
|
||||
|
||||
# 4. 检查是否有数据
|
||||
if not hasattr(self, "results") or not self.results:
|
||||
self.log_gui.log("⚠️ 没有测试数据,无法重新绘制")
|
||||
messagebox.showwarning("警告", "请先完成测试后再重新计算")
|
||||
return
|
||||
|
||||
# 5. 获取保存的灰阶数据
|
||||
gray_data = self.results.get_intermediate_data("shared", "gray")
|
||||
if not gray_data:
|
||||
gray_data = self.results.get_intermediate_data("cct", "gray")
|
||||
|
||||
if not gray_data or len(gray_data) < 2:
|
||||
self.log_gui.log("⚠️ 没有可用的灰阶数据")
|
||||
messagebox.showwarning("警告", "没有找到色度测试数据")
|
||||
return
|
||||
|
||||
# 6. 重新计算 CCT
|
||||
self.log_gui.log("=" * 50)
|
||||
self.log_gui.log("开始重新计算色度一致性...")
|
||||
self.log_gui.log("=" * 50)
|
||||
|
||||
import algorithm.pq_algorithm as pq_algorithm
|
||||
|
||||
cct_values = pq_algorithm.calculate_cct_from_results(gray_data)
|
||||
|
||||
# 7. 更新结果
|
||||
self.results.set_test_item_result("cct", {"cct_values": cct_values})
|
||||
|
||||
# 8. 重新绘制色度图
|
||||
test_type = self.config.current_test_type
|
||||
self.plot_cct(test_type)
|
||||
|
||||
self.log_gui.log("✓ 色度图已重新绘制")
|
||||
self.log_gui.log("=" * 50)
|
||||
|
||||
messagebox.showinfo("成功", "色度图已根据新参数重新绘制!")
|
||||
|
||||
except Exception as e:
|
||||
self.log_gui.log(f"❌ 重新计算失败: {str(e)}")
|
||||
import traceback
|
||||
|
||||
self.log_gui.log(traceback.format_exc())
|
||||
messagebox.showerror("错误", f"重新计算失败: {str(e)}")
|
||||
|
||||
|
||||
def recalculate_gamut(self):
|
||||
"""重新计算并绘制色域图(使用新的参考标准)"""
|
||||
try:
|
||||
# 1. 收起配置项
|
||||
if hasattr(self, "config_panel_frame"):
|
||||
try:
|
||||
if self.config_panel_frame.winfo_viewable():
|
||||
self.config_panel_frame.btn.invoke()
|
||||
self.root.update_idletasks()
|
||||
time.sleep(0.1)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 2. 跳转到色域图Tab
|
||||
self.chart_notebook.select(self.gamut_chart_frame)
|
||||
self.root.update_idletasks()
|
||||
|
||||
# 3. 检查是否有数据
|
||||
if not hasattr(self, "results") or not self.results:
|
||||
self.log_gui.log("⚠️ 没有测试数据,无法重新绘制")
|
||||
messagebox.showwarning("警告", "请先完成测试后再重新计算")
|
||||
return
|
||||
|
||||
# 4. 获取保存的色域数据
|
||||
rgb_data = self.results.get_intermediate_data("gamut", "rgb")
|
||||
|
||||
if not rgb_data or len(rgb_data) < 3:
|
||||
self.log_gui.log("⚠️ 没有可用的色域数据")
|
||||
messagebox.showwarning("警告", "没有找到色域测试数据")
|
||||
return
|
||||
|
||||
# 5. 获取当前测试类型
|
||||
test_type = self.config.current_test_type
|
||||
|
||||
# 6. 获取用户选择的参考标准
|
||||
if test_type == "screen_module":
|
||||
reference_standard = self.screen_gamut_ref_var.get()
|
||||
elif test_type == "sdr_movie":
|
||||
reference_standard = self.sdr_gamut_ref_var.get()
|
||||
elif test_type == "hdr_movie":
|
||||
reference_standard = self.hdr_gamut_ref_var.get()
|
||||
else:
|
||||
reference_standard = "DCI-P3"
|
||||
|
||||
self.log_gui.log("=" * 50)
|
||||
self.log_gui.log(f"开始重新计算色域(参考标准: {reference_standard})...")
|
||||
self.log_gui.log("=" * 50)
|
||||
|
||||
# 7. 重新计算 XY 色域覆盖率
|
||||
xy_points = [[result[0], result[1]] for result in rgb_data]
|
||||
|
||||
# 根据参考标准计算 XY 覆盖率
|
||||
if reference_standard == "BT.2020":
|
||||
area_xy, coverage_xy = pq_algorithm.calculate_gamut_coverage_BT2020(
|
||||
xy_points
|
||||
)
|
||||
elif reference_standard == "BT.709":
|
||||
area_xy, coverage_xy = pq_algorithm.calculate_gamut_coverage_BT709(
|
||||
xy_points
|
||||
)
|
||||
elif reference_standard == "DCI-P3":
|
||||
area_xy, coverage_xy = pq_algorithm.calculate_gamut_coverage_DCIP3(
|
||||
xy_points
|
||||
)
|
||||
else:
|
||||
area_xy, coverage_xy = pq_algorithm.calculate_gamut_coverage_DCIP3(
|
||||
xy_points
|
||||
)
|
||||
reference_standard = "DCI-P3"
|
||||
|
||||
self.log_gui.log(f"✓ 参考标准: {reference_standard}")
|
||||
self.log_gui.log(f"✓ XY 色域覆盖率: {coverage_xy:.1f}%")
|
||||
|
||||
# ========== ✅✅✅ 8. 重新计算 UV 色域覆盖率 ==========
|
||||
# 将 XY 坐标转换为 UV 坐标
|
||||
uv_points = []
|
||||
for x, y in xy_points:
|
||||
try:
|
||||
# XY转UV公式
|
||||
denom = -2 * x + 12 * y + 3
|
||||
if abs(denom) < 1e-10:
|
||||
u, v = 0, 0
|
||||
else:
|
||||
u = 4 * x / denom
|
||||
v = 9 * y / denom
|
||||
uv_points.append([u, v])
|
||||
except ZeroDivisionError:
|
||||
continue
|
||||
|
||||
self.log_gui.log(f"✓ 转换后的 UV 点数量: {len(uv_points)}")
|
||||
|
||||
# 根据参考标准计算 UV 覆盖率
|
||||
if reference_standard == "BT.2020":
|
||||
area_uv, coverage_uv = pq_algorithm.calculate_gamut_coverage_BT2020_uv(
|
||||
uv_points
|
||||
)
|
||||
elif reference_standard == "BT.709":
|
||||
area_uv, coverage_uv = pq_algorithm.calculate_gamut_coverage_BT709_uv(
|
||||
uv_points
|
||||
)
|
||||
elif reference_standard == "DCI-P3":
|
||||
area_uv, coverage_uv = pq_algorithm.calculate_gamut_coverage_DCIP3_uv(
|
||||
uv_points
|
||||
)
|
||||
else:
|
||||
area_uv, coverage_uv = pq_algorithm.calculate_gamut_coverage_DCIP3_uv(
|
||||
uv_points
|
||||
)
|
||||
|
||||
self.log_gui.log(f"✓ UV 色域覆盖率: {coverage_uv:.1f}%")
|
||||
# ========================================================
|
||||
|
||||
# 9. ✅ 更新结果(同时保存 XY 和 UV 覆盖率)
|
||||
self.results.set_test_item_result(
|
||||
"gamut",
|
||||
{
|
||||
"area": area_xy, # ← 兼容旧字段
|
||||
"coverage": coverage_xy, # ← 兼容旧字段
|
||||
"area_xy": area_xy, # ← XY 面积
|
||||
"coverage_xy": coverage_xy, # ← XY 覆盖率
|
||||
"area_uv": area_uv, # ← UV 面积
|
||||
"coverage_uv": coverage_uv, # ← UV 覆盖率
|
||||
"uv_coverage": coverage_uv, # ← 兼容字段(Excel 导出用)
|
||||
"reference": reference_standard,
|
||||
},
|
||||
)
|
||||
|
||||
self.log_gui.log("✓ 测试结果已更新到 results 对象")
|
||||
|
||||
# 10. 重新绘制色域图
|
||||
self.plot_gamut(rgb_data, coverage_xy, test_type)
|
||||
|
||||
self.log_gui.log("✓ 色域图已重新绘制")
|
||||
self.log_gui.log("=" * 50)
|
||||
|
||||
messagebox.showinfo(
|
||||
"成功",
|
||||
f"色域图已根据新参考标准 {reference_standard} 重新绘制!\n\n"
|
||||
f"XY 覆盖率: {coverage_xy:.1f}%\n"
|
||||
f"UV 覆盖率: {coverage_uv:.1f}%",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.log_gui.log(f"❌ 重新计算失败: {str(e)}")
|
||||
import traceback
|
||||
|
||||
self.log_gui.log(traceback.format_exc())
|
||||
messagebox.showerror("错误", f"重新计算失败: {str(e)}")
|
||||
|
||||
|
||||
def on_cct_param_change(self, var, default_value):
|
||||
"""色度参数改变时的处理 - 空值恢复默认"""
|
||||
try:
|
||||
value = var.get().strip()
|
||||
|
||||
if value == "":
|
||||
# 空值:恢复默认值
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"输入框为空,恢复默认值: {default_value}")
|
||||
else:
|
||||
# 验证是否为有效数字
|
||||
try:
|
||||
float_val = float(value)
|
||||
if float_val < 0 or float_val > 1:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(
|
||||
f"参数超出范围 [0, 1],恢复默认值: {default_value}"
|
||||
)
|
||||
except ValueError:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"无效的参数值,恢复默认值: {default_value}")
|
||||
|
||||
# 保存配置
|
||||
self.save_cct_params()
|
||||
|
||||
except Exception as e:
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"处理参数变化失败: {str(e)}")
|
||||
|
||||
|
||||
def on_cct_param_focus_out(self, var, default_value):
|
||||
"""色度参数失去焦点时的处理 - 空值恢复默认"""
|
||||
try:
|
||||
value = var.get().strip()
|
||||
|
||||
if value == "":
|
||||
# 空值:恢复默认值
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"✓ 输入框为空,恢复默认值: {default_value}")
|
||||
else:
|
||||
# 验证是否为有效数字
|
||||
try:
|
||||
float_val = float(value)
|
||||
if float_val < 0 or float_val > 1:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(
|
||||
f"⚠️ 参数超出范围 [0, 1],恢复默认值: {default_value}"
|
||||
)
|
||||
except ValueError:
|
||||
var.set(str(default_value))
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"⚠️ 无效的参数值,恢复默认值: {default_value}")
|
||||
|
||||
# 保存配置
|
||||
self.save_cct_params()
|
||||
|
||||
except Exception as e:
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"处理参数变化失败: {str(e)}")
|
||||
|
||||
|
||||
def save_cct_params(self):
|
||||
"""保存色度参数 - 简化版"""
|
||||
try:
|
||||
current_type = self.config.current_test_type
|
||||
|
||||
def get_float(var, default):
|
||||
try:
|
||||
value = var.get().strip()
|
||||
if value == "":
|
||||
return default
|
||||
return float(value)
|
||||
except:
|
||||
return default
|
||||
|
||||
cct_params = {
|
||||
"x_ideal": get_float(
|
||||
self.cct_x_ideal_var, self.DEFAULT_CCT_PARAMS["x_ideal"]
|
||||
),
|
||||
"x_tolerance": get_float(
|
||||
self.cct_x_tolerance_var, self.DEFAULT_CCT_PARAMS["x_tolerance"]
|
||||
),
|
||||
"y_ideal": get_float(
|
||||
self.cct_y_ideal_var, self.DEFAULT_CCT_PARAMS["y_ideal"]
|
||||
),
|
||||
"y_tolerance": get_float(
|
||||
self.cct_y_tolerance_var, self.DEFAULT_CCT_PARAMS["y_tolerance"]
|
||||
),
|
||||
}
|
||||
|
||||
if current_type not in self.config.current_test_types:
|
||||
self.config.current_test_types[current_type] = {}
|
||||
|
||||
self.config.current_test_types[current_type]["cct_params"] = cct_params
|
||||
self.save_pq_config()
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def reload_cct_params(self):
|
||||
"""切换测试类型时重新加载色度参数"""
|
||||
try:
|
||||
current_type = self.config.current_test_type
|
||||
saved_params = self.config.current_test_types.get(current_type, {}).get(
|
||||
"cct_params", None
|
||||
)
|
||||
|
||||
if saved_params is None:
|
||||
saved_params = self.DEFAULT_CCT_PARAMS.copy()
|
||||
|
||||
# 更新输入框的值
|
||||
self.cct_x_ideal_var.set(str(saved_params["x_ideal"]))
|
||||
self.cct_x_tolerance_var.set(str(saved_params["x_tolerance"]))
|
||||
self.cct_y_ideal_var.set(str(saved_params["y_ideal"]))
|
||||
self.cct_y_tolerance_var.set(str(saved_params["y_tolerance"]))
|
||||
|
||||
except Exception as e:
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"重新加载色度参数失败: {str(e)}")
|
||||
|
||||
|
||||
def toggle_cct_params_frame(self):
|
||||
"""根据测试类型和测试项的选中状态显示对应参数框"""
|
||||
selected_items = self.get_selected_test_items()
|
||||
current_test_type = self.config.current_test_type
|
||||
|
||||
# ========== 默认隐藏所有参数框 ==========
|
||||
self.cct_params_frame.pack_forget()
|
||||
self.sdr_cct_params_frame.pack_forget()
|
||||
|
||||
# HDR 色度参数框(如果存在的话)
|
||||
if hasattr(self, "hdr_cct_params_frame"):
|
||||
self.hdr_cct_params_frame.pack_forget()
|
||||
|
||||
# ========== 根据测试类型和选中项显示对应参数框 ==========
|
||||
if current_test_type == "screen_module":
|
||||
# 屏模组:只有色度参数
|
||||
if "cct" in selected_items:
|
||||
self.cct_params_frame.pack(fill=tk.X, padx=5, pady=5)
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log("✓ 显示屏模组色度参数设置")
|
||||
|
||||
elif current_test_type == "sdr_movie":
|
||||
# SDR:只有色度参数(色准不需要参数设置框)
|
||||
if "cct" in selected_items:
|
||||
self.sdr_cct_params_frame.pack(fill=tk.X, padx=5, pady=5)
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log("✓ 显示 SDR 色度参数设置")
|
||||
|
||||
elif current_test_type == "hdr_movie":
|
||||
# HDR:只有色度参数(色准不需要参数设置框)
|
||||
if "cct" in selected_items:
|
||||
if hasattr(self, "hdr_cct_params_frame"):
|
||||
self.hdr_cct_params_frame.pack(fill=tk.X, padx=5, pady=5)
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log("✓ 显示 HDR 色度参数设置")
|
||||
else:
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log("⚠️ HDR 色度参数框尚未创建")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user