修改深色模式下结果图片显示异常

This commit is contained in:
xinzhu.yin
2026-06-05 16:58:46 +08:00
parent 49d82da8b9
commit e9a591bf6e
11 changed files with 385 additions and 140 deletions

View File

@@ -9,7 +9,10 @@ from typing import TYPE_CHECKING
from matplotlib.patches import Rectangle
from matplotlib.lines import Line2D
from matplotlib.patches import Circle
import matplotlib.colors as mcolors
import numpy as np
from app.views.modern_styles import get_theme_palette
from app.plots.gamut_background import get_cie1976_background
from app.tests.color_accuracy import get_accuracy_color_standards
@@ -112,6 +115,9 @@ def _draw_left_panel(ax, color_patches, delta_e_values, font_scale=1.0, dark_mod
spine.set_linewidth(0.9)
# ============================================================
# 子图CIE 1976 u'v' 色度图(目标 vs 实测)
# ============================================================
@@ -121,12 +127,14 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0,
ax.clear()
try:
bg, bbox = get_cie1976_background()
if bg.shape[-1] == 4:
bg = bg[:, :, :3]
xmin, xmax, ymin, ymax = bbox
ax.imshow(
bg,
extent=(xmin, xmax, ymin, ymax),
origin="lower",
interpolation="bicubic",
interpolation="bilinear",
zorder=0,
aspect="auto",
)
@@ -181,8 +189,10 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0,
s_u, s_v = _xy_to_uv(sx, sy)
# face = get_patch_color_from_xy(name, (sx, sy)).strip().upper()
face = _COLOR_MAP.get(name, "#888888")
print(name, face)
face = _COLOR_MAP.get(name, "#FFFFFF")
# face = get_patch_color_from_xy(name, (mx, my))
# face = "#FF0000"
# 目标点Target 空心方框
ax.scatter(
@@ -300,17 +310,24 @@ def _draw_result_judgement(ax, accuracy_data, font_scale=1.0, dark_mode=False):
def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
"""绘制色准测试结果 - Calman 风格(色块 + CIE 1976 u'v' + 统计)。"""
fig = self.accuracy_fig
fig.clear()
palette = get_theme_palette()
try:
from app.views.theme_manager import is_dark
dark_mode = is_dark()
except Exception:
dark_mode = False
fig.patch.set_facecolor("#1B1F24" if dark_mode else "#FFFFFF")
fig = self.accuracy_fig
fig.clear()
try:
fig.set_layout_engine(None)
except Exception:
try:
fig.set_tight_layout(False)
except Exception:
pass
fig.patch.set_facecolor(palette["bg"])
# 根据当前画布像素尺寸动态缩放字体,避免窗口缩小时文字挤压重叠。
font_scale = 1.0
@@ -341,13 +358,12 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
else:
title = f"{test_type_name} - 色准测试(全 29色 | Gamma {target_gamma}"
title_color = "#F3F5F7" if dark_mode else "#111"
fig.suptitle(
title,
fontsize=max(8, 11 * font_scale),
y=0.975,
fontweight="bold",
color=title_color,
color=palette["fg"],
)
gs = fig.add_gridspec(
@@ -362,6 +378,8 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
ax_left = fig.add_subplot(gs[0, 0])
ax_uv = fig.add_subplot(gs[0, 1])
ax_judge = fig.add_subplot(gs[1, :])
for ax in (ax_left, ax_uv, ax_judge):
ax.set_facecolor(palette["card_bg"])
# 兼容外部对 self.accuracy_ax 的引用
self.accuracy_ax = ax_judge

View File

@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_cct 原样搬迁。
"""
import numpy as np
from app.views.modern_styles import get_theme_palette
from typing import TYPE_CHECKING
@@ -11,11 +12,36 @@ if TYPE_CHECKING:
from pqAutomationApp import PQAutomationApp
def _is_dark_palette(palette: dict[str, str]) -> bool:
"""根据主题背景色亮度判断是否深色主题。"""
bg = palette.get("bg", "#FFFFFF").lstrip("#")
try:
r = int(bg[0:2], 16)
g = int(bg[2:4], 16)
b = int(bg[4:6], 16)
except Exception:
return False
return (r * 299 + g * 587 + b * 114) / 1000 < 128
def plot_cct(self: "PQAutomationApp", test_type):
"""绘制 x 和 y 坐标分离图 - 每个点标注纵坐标值"""
palette = get_theme_palette()
dark_mode = _is_dark_palette(palette)
x_line_color = "#2F8BFF" if dark_mode else "#0A4BFF"
y_line_color = "#FF4D4D" if dark_mode else "#D90429"
ideal_line_color = "#00C853" if dark_mode else "#198754"
x_tol_color = "#FF7070" if dark_mode else "#C0392B"
y_tol_color = "#FFB74D" if dark_mode else "#D68910"
grid_color = "#566070" if dark_mode else "#B8BDC3"
axis_text = "#EDF2FA" if dark_mode else palette["fg"]
axis_sub_text = "#C8D2E0" if dark_mode else "#222222"
legend_bg = "#131821" if dark_mode else "#FFFFFF"
legend_edge = "#A4B2C6" if dark_mode else palette["border"]
self.cct_fig.clear()
self.cct_fig.patch.set_facecolor(palette["bg"])
gray_data = self.results.get_intermediate_data("shared", "gray")
if not gray_data:
@@ -31,7 +57,7 @@ def plot_cct(self: "PQAutomationApp", test_type):
ha="center",
va="center",
fontsize=14,
color="red",
color=palette["danger"],
)
ax.axis("off")
self.cct_canvas.draw()
@@ -111,12 +137,20 @@ def plot_cct(self: "PQAutomationApp", test_type):
# 为所有测试类型创建子图
ax1 = self.cct_fig.add_subplot(211)
ax2 = self.cct_fig.add_subplot(212)
for ax in (ax1, ax2):
ax.set_facecolor(palette["card_bg"])
for spine in ax.spines.values():
spine.set_color(palette["border"])
ax.tick_params(labelsize=8, colors=axis_sub_text)
ax.xaxis.label.set_color(axis_text)
ax.yaxis.label.set_color(axis_text)
# ========== 上图x coordinates ==========
ax1.plot(
grayscale,
x_measured,
"b-o",
color=x_line_color,
marker="o",
label="屏本体",
linewidth=2,
markersize=4,
@@ -133,13 +167,13 @@ def plot_cct(self: "PQAutomationApp", test_type):
ha="center",
va="bottom",
fontsize=7,
color="blue",
color=x_line_color,
bbox=dict(
boxstyle="round,pad=0.2",
facecolor="white",
edgecolor="blue",
alpha=0.8,
linewidth=0.5,
facecolor=palette["card_bg"],
edgecolor=x_line_color,
alpha=0.92 if dark_mode else 0.85,
linewidth=0.8,
),
)
@@ -147,7 +181,7 @@ def plot_cct(self: "PQAutomationApp", test_type):
full_grayscale = np.linspace(0, 100, 100)
ax1.axhline(
y=x_ideal,
color="green",
color=ideal_line_color,
linestyle="--",
linewidth=1.5,
label=f"x-ideal ({x_ideal:.4f})",
@@ -155,30 +189,34 @@ def plot_cct(self: "PQAutomationApp", test_type):
)
ax1.axhline(
y=x_low,
color="red",
color=x_tol_color,
linestyle=":",
linewidth=1,
alpha=0.7,
alpha=0.95 if dark_mode else 0.7,
label=f"x-low ({x_low:.4f})",
zorder=2,
)
ax1.axhline(
y=x_high,
color="red",
color=x_tol_color,
linestyle=":",
linewidth=1,
alpha=0.7,
alpha=0.95 if dark_mode else 0.7,
label=f"x-high ({x_high:.4f})",
zorder=2,
)
ax1.fill_between(
full_grayscale, x_low, x_high, alpha=0.15, color="blue", zorder=1
full_grayscale,
x_low,
x_high,
alpha=0.22 if dark_mode else 0.15,
color=x_line_color,
zorder=1,
)
ax1.set_xlabel("灰阶 (%)", fontsize=9)
ax1.set_ylabel("CIE x", fontsize=9)
ax1.grid(True, linestyle="--", alpha=0.3)
ax1.tick_params(labelsize=8)
ax1.set_xlabel("灰阶 (%)", fontsize=9, color=axis_text)
ax1.set_ylabel("CIE x", fontsize=9, color=axis_text)
ax1.grid(True, linestyle="--", alpha=0.45 if dark_mode else 0.3, color=grid_color)
ax1.set_xlim(0, 105)
# 纵坐标范围由用户参数控制
@@ -211,7 +249,8 @@ def plot_cct(self: "PQAutomationApp", test_type):
ax2.plot(
grayscale,
y_measured,
"r-o",
color=y_line_color,
marker="o",
label="屏本体",
linewidth=2,
markersize=4,
@@ -228,19 +267,19 @@ def plot_cct(self: "PQAutomationApp", test_type):
ha="center",
va="bottom",
fontsize=7,
color="red",
color=y_line_color,
bbox=dict(
boxstyle="round,pad=0.2",
facecolor="white",
edgecolor="red",
alpha=0.8,
linewidth=0.5,
facecolor=palette["card_bg"],
edgecolor=y_line_color,
alpha=0.92 if dark_mode else 0.85,
linewidth=0.8,
),
)
ax2.axhline(
y=y_ideal,
color="green",
color=ideal_line_color,
linestyle="--",
linewidth=1.5,
label=f"y-ideal ({y_ideal:.4f})",
@@ -248,30 +287,34 @@ def plot_cct(self: "PQAutomationApp", test_type):
)
ax2.axhline(
y=y_low,
color="orange",
color=y_tol_color,
linestyle=":",
linewidth=1,
alpha=0.7,
alpha=0.95 if dark_mode else 0.7,
label=f"y-low ({y_low:.4f})",
zorder=2,
)
ax2.axhline(
y=y_high,
color="orange",
color=y_tol_color,
linestyle=":",
linewidth=1,
alpha=0.7,
alpha=0.95 if dark_mode else 0.7,
label=f"y-high ({y_high:.4f})",
zorder=2,
)
ax2.fill_between(
full_grayscale, y_low, y_high, alpha=0.15, color="orange", zorder=1
full_grayscale,
y_low,
y_high,
alpha=0.22 if dark_mode else 0.15,
color=y_tol_color,
zorder=1,
)
ax2.set_xlabel("灰阶 (%)", fontsize=9)
ax2.set_ylabel("CIE y", fontsize=9)
ax2.grid(True, linestyle="--", alpha=0.3)
ax2.tick_params(labelsize=8)
ax2.set_xlabel("灰阶 (%)", fontsize=9, color=axis_text)
ax2.set_ylabel("CIE y", fontsize=9, color=axis_text)
ax2.grid(True, linestyle="--", alpha=0.45 if dark_mode else 0.3, color=grid_color)
ax2.set_xlim(0, 105)
# 纵坐标范围由用户参数控制
@@ -307,6 +350,7 @@ def plot_cct(self: "PQAutomationApp", test_type):
fontsize=12,
y=0.98,
fontweight="bold",
color=palette["fg"],
)
self.cct_fig.subplots_adjust(
@@ -317,12 +361,25 @@ def plot_cct(self: "PQAutomationApp", test_type):
hspace=0.30,
)
ax1.legend(
fontsize=7, loc="center left", bbox_to_anchor=(1.05, 0.5), framealpha=1.0
legend1 = ax1.legend(
fontsize=7,
loc="center left",
bbox_to_anchor=(1.05, 0.5),
framealpha=0.92 if dark_mode else 1.0,
facecolor=legend_bg,
edgecolor=legend_edge,
)
ax2.legend(
fontsize=7, loc="center left", bbox_to_anchor=(1.05, 0.5), framealpha=1.0
legend2 = ax2.legend(
fontsize=7,
loc="center left",
bbox_to_anchor=(1.05, 0.5),
framealpha=0.92 if dark_mode else 1.0,
facecolor=legend_bg,
edgecolor=legend_edge,
)
for legend in (legend1, legend2):
for text in legend.get_texts():
text.set_color(axis_text)
self.cct_canvas.draw()
self.chart_notebook.select(self.cct_chart_frame)

View File

@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_contrast 原样搬迁
"""
from matplotlib.patches import Rectangle
from app.views.modern_styles import get_theme_palette
from typing import TYPE_CHECKING
@@ -14,9 +15,12 @@ if TYPE_CHECKING:
def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
"""绘制对比度测试结果 - 固定布局版本"""
palette = get_theme_palette()
# 清空并重置
self.contrast_ax.clear()
self.contrast_fig.patch.set_facecolor(palette["bg"])
self.contrast_ax.set_facecolor(palette["card_bg"])
self.contrast_ax.set_xlim(0, 1)
self.contrast_ax.set_ylim(0, 1)
self.contrast_ax.axis("off")
@@ -51,6 +55,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
fontsize=12,
y=0.98,
fontweight="bold",
color=palette["fg"],
)
# ========== 中央大对比度卡片 ==========
@@ -107,16 +112,16 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
"title": "白场亮度",
"value": f"{max_lum:.2f}",
"unit": "cd/m²",
"color": "#E3F2FD",
"edge_color": "#2196F3",
"color": palette["surface_alt_bg"],
"edge_color": palette["primary"],
},
{
"x": start_x + card_width + gap,
"title": "黑场亮度",
"value": f"{min_lum:.4f}",
"unit": "cd/m²",
"color": "#F3E5F5",
"edge_color": "#9C27B0",
"color": palette["card_bg"],
"edge_color": palette["secondary"],
},
]
@@ -142,6 +147,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
va="top",
fontsize=10,
fontweight="bold",
color=palette["fg"],
transform=self.contrast_ax.transAxes,
)
@@ -154,6 +160,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
va="center",
fontsize=16,
fontweight="bold",
color=palette["fg"],
transform=self.contrast_ax.transAxes,
)
@@ -165,7 +172,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
ha="center",
va="bottom",
fontsize=9,
color="gray",
color=palette["muted_fg"],
transform=self.contrast_ax.transAxes,
)

View File

@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_eotf 原样搬迁。
"""
import numpy as np
from app.views.modern_styles import get_theme_palette
from typing import TYPE_CHECKING
@@ -14,15 +15,21 @@ if TYPE_CHECKING:
def plot_eotf(self: "PQAutomationApp", L_bar, results_with_eotf_list, test_type):
"""绘制 EOTF 曲线 + 数据表格HDR 专用,包含实测亮度)"""
palette = get_theme_palette()
# ========== 1. 清空并重置左侧曲线 ==========
self.eotf_ax.clear()
self.eotf_fig.patch.set_facecolor(palette["bg"])
self.eotf_ax.set_facecolor(palette["card_bg"])
self.eotf_ax.set_xlim(0, 105)
self.eotf_ax.set_ylim(0, 1.1)
self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10)
self.eotf_ax.set_ylabel("L_bar", fontsize=10)
self.eotf_ax.grid(True, linestyle="--", alpha=0.3)
self.eotf_ax.tick_params(labelsize=9)
self.eotf_ax.tick_params(colors=palette["fg"])
for spine in self.eotf_ax.spines.values():
spine.set_color(palette["border"])
# 生成横坐标(灰阶百分比)
x_values = np.linspace(0, 100, len(L_bar))
@@ -120,17 +127,17 @@ def plot_eotf(self: "PQAutomationApp", L_bar, results_with_eotf_list, test_type)
# 表头样式
for i in range(4):
cell = table[(0, i)]
cell.set_facecolor("#4472C4")
cell.set_text_props(weight="bold", color="white")
cell.set_facecolor(palette["primary"])
cell.set_text_props(weight="bold", color=palette["select_fg"])
# 数据行交替颜色
for i in range(1, len(table_data)):
for j in range(4):
cell = table[(i, j)]
if i % 2 == 0:
cell.set_facecolor("#E7E6E6")
cell.set_facecolor(palette["surface_alt_bg"])
else:
cell.set_facecolor("#FFFFFF")
cell.set_facecolor(palette["card_bg"])
# ========== 3. 总标题 ==========
test_type_name = self.get_test_type_name(test_type)
@@ -139,6 +146,7 @@ def plot_eotf(self: "PQAutomationApp", L_bar, results_with_eotf_list, test_type)
fontsize=12,
y=0.98,
fontweight="bold",
color=palette["fg"],
)
# 选中 EOTF Tab

View File

@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_gamma 原样搬迁。
"""
import numpy as np
from app.views.modern_styles import get_theme_palette
from typing import TYPE_CHECKING
@@ -11,18 +12,44 @@ if TYPE_CHECKING:
from pqAutomationApp import PQAutomationApp
def _is_dark_palette(palette: dict[str, str]) -> bool:
"""根据主题背景色亮度判断是否深色主题。"""
bg = palette.get("bg", "#FFFFFF").lstrip("#")
try:
r = int(bg[0:2], 16)
g = int(bg[2:4], 16)
b = int(bg[4:6], 16)
except Exception:
return False
return (r * 299 + g * 587 + b * 114) / 1000 < 128
def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_gamma, test_type):
"""绘制Gamma曲线 + 数据表格(包含实测亮度)"""
palette = get_theme_palette()
dark_mode = _is_dark_palette(palette)
line_actual = "#3FA7FF" if dark_mode else "#0A4BFF"
line_ideal = "#FF6B6B" if dark_mode else "#D62828"
grid_color = "#566070" if dark_mode else "#B8BDC3"
legend_bg = "#131821" if dark_mode else "#FFFFFF"
legend_edge = "#A4B2C6" if dark_mode else palette["border"]
table_edge = "#738196" if dark_mode else palette["border"]
table_body_fg = "#EEF3FA" if dark_mode else palette["fg"]
# ========== 1. 清空并重置左侧曲线 ==========
self.gamma_ax.clear()
self.gamma_fig.patch.set_facecolor(palette["bg"])
self.gamma_ax.set_facecolor(palette["card_bg"])
self.gamma_ax.set_xlim(0, 105)
self.gamma_ax.set_ylim(0, 1.1)
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10)
self.gamma_ax.set_ylabel("L_bar", fontsize=10)
self.gamma_ax.grid(True, linestyle="--", alpha=0.3)
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10, color=palette["fg"])
self.gamma_ax.set_ylabel("L_bar", fontsize=10, color=palette["fg"])
self.gamma_ax.grid(True, linestyle="--", alpha=0.45 if dark_mode else 0.3, color=grid_color)
self.gamma_ax.tick_params(labelsize=9)
self.gamma_ax.tick_params(colors=palette["fg"])
for spine in self.gamma_ax.spines.values():
spine.set_color(palette["border"])
# 生成横坐标(灰阶百分比)
x_values = np.linspace(0, 100, len(L_bar))
@@ -46,7 +73,8 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
self.gamma_ax.plot(
x_values,
L_bar,
"b-o",
color=line_actual,
marker="o",
label=f"实测 (平均γ={avg_gamma:.2f})",
linewidth=2,
markersize=4,
@@ -58,15 +86,24 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
self.gamma_ax.plot(
x_values,
ideal_L_bar,
"r--",
color=line_ideal,
linestyle="--",
label=f"理想 (γ={target_gamma})",
linewidth=2,
alpha=0.7,
alpha=0.9 if dark_mode else 0.7,
zorder=3,
)
# 图例
self.gamma_ax.legend(fontsize=9, loc="upper left", framealpha=0.95)
legend = self.gamma_ax.legend(
fontsize=9,
loc="upper left",
framealpha=0.9 if dark_mode else 0.95,
facecolor=legend_bg,
edgecolor=legend_edge,
)
for text in legend.get_texts():
text.set_color(palette["fg"])
# ========== 2. 清空并绘制右侧表格 ==========
self.gamma_table_ax.clear()
@@ -120,17 +157,22 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
# 表头样式
for i in range(4):
cell = table[(0, i)]
cell.set_facecolor("#4472C4")
cell.set_text_props(weight="bold", color="white")
cell.set_facecolor(palette["primary"])
cell.set_text_props(weight="bold", color=palette["select_fg"])
cell.set_edgecolor(table_edge)
cell.set_linewidth(0.8)
# 数据行交替颜色
for i in range(1, len(table_data)):
for j in range(4):
cell = table[(i, j)]
if i % 2 == 0:
cell.set_facecolor("#E7E6E6")
cell.set_facecolor(palette["surface_alt_bg"])
else:
cell.set_facecolor("#FFFFFF")
cell.set_facecolor(palette["card_bg"])
cell.set_text_props(color=table_body_fg)
cell.set_edgecolor(table_edge)
cell.set_linewidth(0.6)
# ========== 3. 总标题 ==========
test_type_name = self.get_test_type_name(test_type)
@@ -139,6 +181,7 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
fontsize=12,
y=0.98,
fontweight="bold",
color=palette["fg"],
)
# ========== 4. 绘制到画布 ==========

View File

@@ -178,7 +178,7 @@ def _style_axes(ax, *, title, xlabel, ylabel, xlim, ylim, dark_mode):
ax.set_ylabel(ylabel, fontsize=10, color=text)
ax.set_xlim(*xlim)
ax.set_ylim(*ylim)
ax.set_aspect("equal", adjustable="datalim")
ax.set_aspect("equal", adjustable="box")
ax.grid(True, linestyle=":", linewidth=0.7, color=grid, alpha=0.32)
ax.tick_params(axis="both", labelsize=9, colors=text)
for spine in ax.spines.values():
@@ -193,8 +193,10 @@ def _blit_background(ax, background, bbox):
ax.imshow(
background,
extent=(xmin, xmax, ymin, ymax),
origin="upper", # canvas.buffer_rgba 行 0 为顶部
interpolation="bicubic",
# gamut_background._render_chromaticity 已做过 np.flipud
# 这里必须使用 lower 才能与真实色度坐标方向一致。
origin="lower",
interpolation="bilinear",
zorder=0,
aspect="auto", # 由 _style_axes 的 set_aspect("equal") 控制
)