调整打包文件
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 633 KiB |
BIN
assets/gamma.ico
BIN
assets/gamma.ico
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,93 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal ENABLEDELAYEDEXPANSION
|
|
||||||
|
|
||||||
:: ------------------------------------------------------------
|
|
||||||
:: Select ico file via GUI
|
|
||||||
:: ------------------------------------------------------------
|
|
||||||
for /f "delims=" %%A in ('powershell -command ^
|
|
||||||
"Add-Type -AssemblyName System.Windows.Forms | Out-Null; $f=New-Object Windows.Forms.OpenFileDialog; $f.Filter='Icon (*.ico)|*.ico'; if($f.ShowDialog() -eq 'OK'){Write-Output $f.FileName}"') do (
|
|
||||||
set ICO=%%A
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%ICO%"=="" (
|
|
||||||
echo No file selected.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
echo Checking icon: %ICO%
|
|
||||||
echo -----------------------------------------
|
|
||||||
|
|
||||||
:: ------------------------------------------------------------
|
|
||||||
:: Extract bytes via PowerShell (safe for PNG-ICON)
|
|
||||||
:: ------------------------------------------------------------
|
|
||||||
for /f "tokens=* delims=" %%B in ('powershell -command ^
|
|
||||||
"[System.IO.File]::ReadAllBytes('%ICO%') -join ' '"') do (
|
|
||||||
set RAW=%%B
|
|
||||||
)
|
|
||||||
|
|
||||||
:: Convert byte list into array
|
|
||||||
set i=0
|
|
||||||
for %%b in (%RAW%) do (
|
|
||||||
set BYTE[!i!]=%%b
|
|
||||||
set /a i+=1
|
|
||||||
)
|
|
||||||
set /a LEN=i
|
|
||||||
|
|
||||||
:: ICONDIR.Count = bytes 4-5
|
|
||||||
set /a COUNT=BYTE[4] + BYTE[5]*256
|
|
||||||
echo Total frames: %COUNT%
|
|
||||||
echo.
|
|
||||||
|
|
||||||
if %COUNT% LEQ 0 (
|
|
||||||
echo ERROR: Invalid icon or no frames.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
set HAS256=0
|
|
||||||
set FIRST256=0
|
|
||||||
|
|
||||||
echo Frame list:
|
|
||||||
echo -----------------------------------------
|
|
||||||
|
|
||||||
:: Each ICONDIRENTRY = 16 bytes starting at offset 6
|
|
||||||
for /l %%I in (0,1,%COUNT%-1) do (
|
|
||||||
set /a OFFSET=6 + 16 * %%I
|
|
||||||
|
|
||||||
set W=!BYTE[%OFFSET%]!
|
|
||||||
set H=!BYTE[%OFFSET%+1]!
|
|
||||||
|
|
||||||
if "!W!"=="0" set W=256
|
|
||||||
if "!H!"=="0" set H=256
|
|
||||||
|
|
||||||
echo Frame %%I = !W! x !H!
|
|
||||||
|
|
||||||
if "!W!"=="256" if "!H!"=="256" (
|
|
||||||
set HAS256=1
|
|
||||||
if %%I==0 set FIRST256=1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo -----------------------------------------
|
|
||||||
|
|
||||||
if %HAS256%==0 (
|
|
||||||
echo ERROR: No 256x256 frame found.
|
|
||||||
echo This is why NSIS and Windows show a small icon.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
if %FIRST256%==0 (
|
|
||||||
echo WARNING: 256x256 exists but is NOT frame 0.
|
|
||||||
echo This causes small icons in NSIS installers.
|
|
||||||
echo You should reorder frames so 256x256 is the first frame.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
echo SUCCESS: 256x256 frame exists AND is the first frame.
|
|
||||||
echo Icon is well-structured.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 107 KiB |
103
installer.nsi
103
installer.nsi
@@ -1,31 +1,17 @@
|
|||||||
Unicode True
|
Unicode True
|
||||||
SetCompressor /SOLID lzma
|
SetCompressor /SOLID lzma
|
||||||
|
SetCompressorDictSize 64
|
||||||
RequestExecutionLevel user
|
RequestExecutionLevel user
|
||||||
|
|
||||||
!include "MUI2.nsh"
|
!include "MUI2.nsh"
|
||||||
!include "LogicLib.nsh"
|
|
||||||
|
|
||||||
!define PROJECT_ROOT "."
|
!define PROJECT_ROOT "."
|
||||||
!define DIST_ROOT "${PROJECT_ROOT}\\dist\\pqAutomationApp"
|
!define DIST_ROOT "${PROJECT_ROOT}\dist\pqAutomationApp"
|
||||||
!define APP_EXE "pqAutomationApp.exe"
|
!define APP_EXE "pqAutomationApp.exe"
|
||||||
!define APP_ID "PQAutomationApp"
|
!define APP_ID "PQAutomationApp"
|
||||||
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
; Detect Python from PATH
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
!define PYTHON_CMD "python"
|
!define PYTHON_CMD "python"
|
||||||
|
|
||||||
!system '"${PYTHON_CMD}" -V > python_check.txt 2>&1'
|
|
||||||
!searchparse /file python_check.txt "Python " PY_VER ""
|
|
||||||
!if "${PY_VER}" == ""
|
|
||||||
!error "Python not found. Ensure python.exe is available in PATH."
|
|
||||||
!endif
|
|
||||||
!delfile python_check.txt
|
|
||||||
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
; Extract APP_NAME and APP_VERSION from Python code
|
|
||||||
; (App version file may contain Unicode, so we use Python to output ASCII)
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
!system '"${PYTHON_CMD}" -c "import app_version; print(app_version.APP_NAME)" > app_name.txt'
|
!system '"${PYTHON_CMD}" -c "import app_version; print(app_version.APP_NAME)" > app_name.txt'
|
||||||
!system '"${PYTHON_CMD}" -c "import app_version; print(app_version.APP_VERSION)" > app_version.txt'
|
!system '"${PYTHON_CMD}" -c "import app_version; print(app_version.APP_VERSION)" > app_version.txt'
|
||||||
|
|
||||||
@@ -35,20 +21,22 @@ RequestExecutionLevel user
|
|||||||
!delfile "app_name.txt"
|
!delfile "app_name.txt"
|
||||||
!delfile "app_version.txt"
|
!delfile "app_version.txt"
|
||||||
|
|
||||||
; ------------------------------------------------------------
|
!if /FileExists "${DIST_ROOT}\${APP_EXE}"
|
||||||
; Registry Keys
|
!else
|
||||||
; ------------------------------------------------------------
|
!error "Executable not found: ${DIST_ROOT}\${APP_EXE}. Please build using PyInstaller first."
|
||||||
!define UNINSTALL_REG_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${APP_ID}"
|
!endif
|
||||||
!define APP_REG_KEY "Software\\${APP_ID}"
|
|
||||||
|
!define UNINSTALL_REG_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_ID}"
|
||||||
|
!define APP_REG_KEY "Software\${APP_ID}"
|
||||||
|
|
||||||
Name "${APP_NAME} ${APP_VERSION}"
|
Name "${APP_NAME} ${APP_VERSION}"
|
||||||
OutFile "dist\\PQAutomationApp_Setup_${APP_VERSION}.exe"
|
OutFile "dist\PQAutomationApp_Setup_${APP_VERSION}.exe"
|
||||||
InstallDir "$LOCALAPPDATA\\Programs\\${APP_ID}"
|
InstallDir "$LOCALAPPDATA\Programs\${APP_ID}"
|
||||||
InstallDirRegKey HKCU "${APP_REG_KEY}" "InstallDir"
|
InstallDirRegKey HKCU "${APP_REG_KEY}" "InstallDir"
|
||||||
|
|
||||||
!define MUI_ABORTWARNING
|
!define MUI_ABORTWARNING
|
||||||
!define MUI_ICON "assets\\pq.ico"
|
!define MUI_ICON "assets\pq.ico"
|
||||||
!define MUI_UNICON "assets\\pq.ico"
|
!define MUI_UNICON "assets\pq.ico"
|
||||||
|
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
@@ -59,71 +47,46 @@ InstallDirRegKey HKCU "${APP_REG_KEY}" "InstallDir"
|
|||||||
!insertmacro MUI_UNPAGE_INSTFILES
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
!insertmacro MUI_UNPAGE_FINISH
|
!insertmacro MUI_UNPAGE_FINISH
|
||||||
|
|
||||||
!insertmacro MUI_LANGUAGE "English"
|
!insertmacro MUI_LANGUAGE "SimpChinese"
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
; Init
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
Function .onInit
|
|
||||||
IfFileExists "${DIST_ROOT}\\${APP_EXE}" +2 0
|
|
||||||
MessageBox MB_ICONSTOP|MB_OK "Executable not found: ${DIST_ROOT}\\${APP_EXE}$\r$\nPlease build using PyInstaller first."
|
|
||||||
IfFileExists "${DIST_ROOT}\\${APP_EXE}" +2 0
|
|
||||||
Abort
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
; Installation Section
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
Section "Main Installation" SEC_MAIN
|
Section "Main Installation" SEC_MAIN
|
||||||
SetOutPath "$INSTDIR"
|
SetOutPath "$INSTDIR"
|
||||||
CreateDirectory "$INSTDIR"
|
|
||||||
CreateDirectory "$INSTDIR\\internal"
|
|
||||||
CreateDirectory "$INSTDIR\\settings"
|
|
||||||
|
|
||||||
File "${DIST_ROOT}\\${APP_EXE}"
|
File "${DIST_ROOT}\${APP_EXE}"
|
||||||
|
|
||||||
SetOutPath "$INSTDIR\\internal"
|
SetOutPath "$INSTDIR\internal"
|
||||||
File /r "${DIST_ROOT}\\internal\\*.*"
|
File /r /x "*.pdb" /x "*.lib" /x "*.exp" /x "*.h" /x "__pycache__" /x "*.pyc" "${DIST_ROOT}\internal\*.*"
|
||||||
|
|
||||||
IfFileExists "${PROJECT_ROOT}\\settings\\pq_config.json" 0 +3
|
IfFileExists "$INSTDIR\settings\pq_config.json" +3 0
|
||||||
SetOutPath "$INSTDIR\\settings"
|
SetOutPath "$INSTDIR\settings"
|
||||||
File /oname=pq_config.json "${PROJECT_ROOT}\\settings\\pq_config.json"
|
File /oname=pq_config.json "${PROJECT_ROOT}\settings\pq_config.json"
|
||||||
|
|
||||||
WriteUninstaller "$INSTDIR\\Uninstall.exe"
|
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
WriteRegStr HKCU "${APP_REG_KEY}" "InstallDir" "$INSTDIR"
|
WriteRegStr HKCU "${APP_REG_KEY}" "InstallDir" "$INSTDIR"
|
||||||
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "DisplayName" "${APP_NAME}"
|
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "DisplayName" "${APP_NAME}"
|
||||||
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "DisplayVersion" "${APP_VERSION}"
|
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "DisplayVersion" "${APP_VERSION}"
|
||||||
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "InstallLocation" "$INSTDIR"
|
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "InstallLocation" "$INSTDIR"
|
||||||
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "DisplayIcon" "$INSTDIR\\${APP_EXE}"
|
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "DisplayIcon" "$INSTDIR\${APP_EXE}"
|
||||||
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "Publisher" "Moka"
|
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "Publisher" "Moka"
|
||||||
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "UninstallString" "$\"$INSTDIR\\Uninstall.exe$\""
|
WriteRegStr HKCU "${UNINSTALL_REG_KEY}" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
|
||||||
WriteRegDWORD HKCU "${UNINSTALL_REG_KEY}" "NoModify" 1
|
WriteRegDWORD HKCU "${UNINSTALL_REG_KEY}" "NoModify" 1
|
||||||
WriteRegDWORD HKCU "${UNINSTALL_REG_KEY}" "NoRepair" 1
|
WriteRegDWORD HKCU "${UNINSTALL_REG_KEY}" "NoRepair" 1
|
||||||
|
|
||||||
CreateDirectory "$SMPROGRAMS\\${APP_NAME}"
|
CreateDirectory "$SMPROGRAMS\${APP_NAME}"
|
||||||
CreateShortcut "$SMPROGRAMS\\${APP_NAME}\\${APP_NAME}.lnk" "$INSTDIR\\${APP_EXE}"
|
CreateShortcut "$SMPROGRAMS\${APP_NAME}\${APP_NAME}.lnk" "$INSTDIR\${APP_EXE}"
|
||||||
CreateShortcut "$SMPROGRAMS\\${APP_NAME}\\Uninstall ${APP_NAME}.lnk" "$INSTDIR\\Uninstall.exe"
|
CreateShortcut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\${APP_EXE}"
|
||||||
CreateShortcut "$DESKTOP\\${APP_NAME}.lnk" "$INSTDIR\\${APP_EXE}"
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
; Uninstall Section
|
|
||||||
; ------------------------------------------------------------
|
|
||||||
Section "Uninstall"
|
Section "Uninstall"
|
||||||
Delete "$DESKTOP\\${APP_NAME}.lnk"
|
Delete "$DESKTOP\${APP_NAME}.lnk"
|
||||||
Delete "$SMPROGRAMS\\${APP_NAME}\\${APP_NAME}.lnk"
|
Delete "$SMPROGRAMS\${APP_NAME}\${APP_NAME}.lnk"
|
||||||
Delete "$SMPROGRAMS\\${APP_NAME}\\Uninstall ${APP_NAME}.lnk"
|
RMDir "$SMPROGRAMS\${APP_NAME}"
|
||||||
RMDir "$SMPROGRAMS\\${APP_NAME}"
|
|
||||||
|
|
||||||
Delete "$INSTDIR\\${APP_EXE}"
|
Delete "$INSTDIR\${APP_EXE}"
|
||||||
Delete "$INSTDIR\\Uninstall.exe"
|
Delete "$INSTDIR\Uninstall.exe"
|
||||||
Delete "$INSTDIR\\settings\\pq_config.json"
|
RMDir /r "$INSTDIR\internal"
|
||||||
RMDir /r "$INSTDIR\\internal"
|
RMDir /r "$INSTDIR\settings"
|
||||||
RMDir /r "$INSTDIR\\settings"
|
|
||||||
RMDir "$INSTDIR"
|
RMDir "$INSTDIR"
|
||||||
|
|
||||||
DeleteRegKey HKCU "${UNINSTALL_REG_KEY}"
|
DeleteRegKey HKCU "${UNINSTALL_REG_KEY}"
|
||||||
|
|||||||
@@ -6,14 +6,10 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
import colour
|
|
||||||
import json
|
import json
|
||||||
import traceback
|
import traceback
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import matplotlib.image as mpimg
|
|
||||||
import algorithm.pq_algorithm as pq_algorithm
|
import algorithm.pq_algorithm as pq_algorithm
|
||||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
|
||||||
from app_version import APP_NAME, APP_VERSION, get_app_title
|
from app_version import APP_NAME, APP_VERSION, get_app_title
|
||||||
from utils.caSerail import CASerail
|
from utils.caSerail import CASerail
|
||||||
from utils.tvSerail import tvSerial
|
from utils.tvSerail import tvSerial
|
||||||
@@ -27,13 +23,11 @@ from views.collapsing_frame import CollapsingFrame
|
|||||||
|
|
||||||
# from views.pq_history_gui import PQHistoryGUI
|
# from views.pq_history_gui import PQHistoryGUI
|
||||||
from views.pq_log_gui import PQLogGUI
|
from views.pq_log_gui import PQLogGUI
|
||||||
from colormath.color_objects import xyYColor, LabColor
|
|
||||||
from colormath.color_conversions import convert_color
|
|
||||||
from colormath.color_diff import delta_e_cie2000
|
|
||||||
from views.pq_debug_panel import PQDebugPanel
|
|
||||||
|
|
||||||
plt.rcParams["font.family"] = ["sans-serif"]
|
plt = None
|
||||||
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
|
mpimg = None
|
||||||
|
FigureCanvasTkAgg = None
|
||||||
|
colour = None
|
||||||
|
|
||||||
|
|
||||||
def get_resource_path(relative_path):
|
def get_resource_path(relative_path):
|
||||||
@@ -190,6 +184,59 @@ class PQAutomationApp:
|
|||||||
)
|
)
|
||||||
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
|
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
|
||||||
|
|
||||||
|
def _ensure_matplotlib_loaded(self):
|
||||||
|
"""按需加载 matplotlib,避免阻塞主界面启动。"""
|
||||||
|
global plt, mpimg, FigureCanvasTkAgg
|
||||||
|
if plt is None or mpimg is None or FigureCanvasTkAgg is None:
|
||||||
|
import matplotlib.pyplot as _plt
|
||||||
|
import matplotlib.image as _mpimg
|
||||||
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg as _FigureCanvasTkAgg
|
||||||
|
|
||||||
|
_plt.rcParams["font.family"] = ["sans-serif"]
|
||||||
|
_plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
|
||||||
|
|
||||||
|
plt = _plt
|
||||||
|
mpimg = _mpimg
|
||||||
|
FigureCanvasTkAgg = _FigureCanvasTkAgg
|
||||||
|
|
||||||
|
def _ensure_colour_loaded(self):
|
||||||
|
"""按需加载 colour-science,减少冷启动导入压力。"""
|
||||||
|
global colour
|
||||||
|
if colour is None:
|
||||||
|
import colour as _colour
|
||||||
|
|
||||||
|
colour = _colour
|
||||||
|
|
||||||
|
def _initialize_chart(self, chart_name):
|
||||||
|
"""按需初始化图表。"""
|
||||||
|
if chart_name == "gamut":
|
||||||
|
self.init_gamut_chart()
|
||||||
|
elif chart_name == "gamma":
|
||||||
|
self.init_gamma_chart()
|
||||||
|
elif chart_name == "eotf":
|
||||||
|
self.init_eotf_chart()
|
||||||
|
elif chart_name == "cct":
|
||||||
|
self.init_cct_chart()
|
||||||
|
elif chart_name == "contrast":
|
||||||
|
self.init_contrast_chart()
|
||||||
|
elif chart_name == "accuracy":
|
||||||
|
self.init_accuracy_chart()
|
||||||
|
|
||||||
|
def _ensure_chart_initialized(self, chart_name):
|
||||||
|
"""确保目标图表已完成初始化。"""
|
||||||
|
if not self.chart_init_state.get(chart_name, False):
|
||||||
|
self._initialize_chart(chart_name)
|
||||||
|
self.chart_init_state[chart_name] = True
|
||||||
|
|
||||||
|
def _warmup_remaining_charts(self):
|
||||||
|
"""在界面显示后分帧预热其它图表,降低首屏阻塞。"""
|
||||||
|
for chart_name in ("gamma", "eotf", "cct", "contrast", "accuracy"):
|
||||||
|
if self.chart_init_state.get(chart_name, False):
|
||||||
|
continue
|
||||||
|
self._ensure_chart_initialized(chart_name)
|
||||||
|
self.root.after(1, self._warmup_remaining_charts)
|
||||||
|
return
|
||||||
|
|
||||||
def get_config_path(self):
|
def get_config_path(self):
|
||||||
"""获取配置文件的完整路径(兼容打包后的程序)"""
|
"""获取配置文件的完整路径(兼容打包后的程序)"""
|
||||||
import os
|
import os
|
||||||
@@ -227,6 +274,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def init_gamut_chart(self):
|
def init_gamut_chart(self):
|
||||||
"""初始化色域图表 - 手动设置subplot位置,完全避免重叠"""
|
"""初始化色域图表 - 手动设置subplot位置,完全避免重叠"""
|
||||||
|
self._ensure_matplotlib_loaded()
|
||||||
container = ttk.Frame(self.gamut_chart_frame)
|
container = ttk.Frame(self.gamut_chart_frame)
|
||||||
container.pack(expand=True, fill=tk.BOTH)
|
container.pack(expand=True, fill=tk.BOTH)
|
||||||
|
|
||||||
@@ -263,6 +311,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def init_gamma_chart(self):
|
def init_gamma_chart(self):
|
||||||
"""初始化Gamma曲线图表 - 左侧曲线 + 右侧表格(✅ 4列 + 通用说明)"""
|
"""初始化Gamma曲线图表 - 左侧曲线 + 右侧表格(✅ 4列 + 通用说明)"""
|
||||||
|
self._ensure_matplotlib_loaded()
|
||||||
container = ttk.Frame(self.gamma_chart_frame)
|
container = ttk.Frame(self.gamma_chart_frame)
|
||||||
container.pack(expand=True, fill=tk.BOTH)
|
container.pack(expand=True, fill=tk.BOTH)
|
||||||
|
|
||||||
@@ -372,6 +421,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def init_eotf_chart(self):
|
def init_eotf_chart(self):
|
||||||
"""初始化 EOTF 曲线图表(HDR 专用)- 左侧曲线 + 右侧表格(✅ 4列)"""
|
"""初始化 EOTF 曲线图表(HDR 专用)- 左侧曲线 + 右侧表格(✅ 4列)"""
|
||||||
|
self._ensure_matplotlib_loaded()
|
||||||
container = ttk.Frame(self.eotf_chart_frame)
|
container = ttk.Frame(self.eotf_chart_frame)
|
||||||
container.pack(expand=True, fill=tk.BOTH)
|
container.pack(expand=True, fill=tk.BOTH)
|
||||||
|
|
||||||
@@ -477,6 +527,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def init_cct_chart(self):
|
def init_cct_chart(self):
|
||||||
"""初始化色度坐标图表 - 正向横坐标,标题居中最上方"""
|
"""初始化色度坐标图表 - 正向横坐标,标题居中最上方"""
|
||||||
|
self._ensure_matplotlib_loaded()
|
||||||
container = ttk.Frame(self.cct_chart_frame)
|
container = ttk.Frame(self.cct_chart_frame)
|
||||||
container.pack(expand=True)
|
container.pack(expand=True)
|
||||||
|
|
||||||
@@ -522,6 +573,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def init_contrast_chart(self):
|
def init_contrast_chart(self):
|
||||||
"""初始化对比度图表 - 固定大小,居中显示"""
|
"""初始化对比度图表 - 固定大小,居中显示"""
|
||||||
|
self._ensure_matplotlib_loaded()
|
||||||
container = ttk.Frame(self.contrast_chart_frame)
|
container = ttk.Frame(self.contrast_chart_frame)
|
||||||
container.pack(expand=True)
|
container.pack(expand=True)
|
||||||
|
|
||||||
@@ -557,6 +609,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def init_accuracy_chart(self):
|
def init_accuracy_chart(self):
|
||||||
"""初始化色准图表 - 固定大小,居中显示"""
|
"""初始化色准图表 - 固定大小,居中显示"""
|
||||||
|
self._ensure_matplotlib_loaded()
|
||||||
container = ttk.Frame(self.accuracy_chart_frame)
|
container = ttk.Frame(self.accuracy_chart_frame)
|
||||||
container.pack(expand=True)
|
container.pack(expand=True)
|
||||||
|
|
||||||
@@ -2791,6 +2844,7 @@ class PQAutomationApp:
|
|||||||
def _run_custom_row_single_step(self, item_id, row_no):
|
def _run_custom_row_single_step(self, item_id, row_no):
|
||||||
"""后台执行客户模板单步测试"""
|
"""后台执行客户模板单步测试"""
|
||||||
try:
|
try:
|
||||||
|
self._ensure_colour_loaded()
|
||||||
self.root.after(0, lambda: self.status_var.set(f"单步测试第 {row_no} 行..."))
|
self.root.after(0, lambda: self.status_var.set(f"单步测试第 {row_no} 行..."))
|
||||||
self.log_gui.log(f"开始单步测试第 {row_no} 行")
|
self.log_gui.log(f"开始单步测试第 {row_no} 行")
|
||||||
|
|
||||||
@@ -3387,35 +3441,43 @@ class PQAutomationApp:
|
|||||||
self.chart_notebook.add(self.contrast_chart_frame, text="对比度")
|
self.chart_notebook.add(self.contrast_chart_frame, text="对比度")
|
||||||
self.chart_notebook.add(self.accuracy_chart_frame, text="色准")
|
self.chart_notebook.add(self.accuracy_chart_frame, text="色准")
|
||||||
|
|
||||||
# 初始化六个独立的图表
|
# 图表初始化状态:首屏仅初始化当前可见图表,其余延后。
|
||||||
self.init_gamut_chart()
|
self.chart_init_state = {
|
||||||
self.init_gamma_chart()
|
"gamut": False,
|
||||||
self.init_eotf_chart()
|
"gamma": False,
|
||||||
self.init_cct_chart()
|
"eotf": False,
|
||||||
self.init_contrast_chart()
|
"cct": False,
|
||||||
self.init_accuracy_chart()
|
"contrast": False,
|
||||||
|
"accuracy": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
# 首屏只初始化色域图,其他图表在切换 Tab 或空闲时初始化。
|
||||||
|
self._ensure_chart_initialized("gamut")
|
||||||
|
self.root.after(120, self._warmup_remaining_charts)
|
||||||
|
|
||||||
# 绑定Tab切换事件
|
# 绑定Tab切换事件
|
||||||
self.chart_notebook.bind("<<NotebookTabChanged>>", self.on_chart_tab_changed)
|
self.chart_notebook.bind("<<NotebookTabChanged>>", self.on_chart_tab_changed)
|
||||||
|
|
||||||
# ==================== ✅ 在图表下方创建单步调试面板 ====================
|
# 旧版内嵌调试面板改为按需窗口,不在启动阶段创建复杂控件。
|
||||||
self.debug_container = ttk.LabelFrame(
|
|
||||||
self.result_frame, # ← 放在 result_frame 内,图表正下方
|
|
||||||
text="🔧 单步调试",
|
|
||||||
padding=10,
|
|
||||||
)
|
|
||||||
# 默认不显示
|
|
||||||
|
|
||||||
# 创建单步调试面板实例
|
|
||||||
self.debug_panel = PQDebugPanel(self.debug_container, self)
|
|
||||||
|
|
||||||
self.log_gui.log("✓ 单步调试面板已创建(放在测试结果图表下方)")
|
|
||||||
|
|
||||||
def on_chart_tab_changed(self, event):
|
def on_chart_tab_changed(self, event):
|
||||||
"""Tab切换时的事件处理"""
|
"""Tab切换时的事件处理"""
|
||||||
try:
|
try:
|
||||||
|
selected_tab = self.chart_notebook.select()
|
||||||
|
tab_to_chart = {
|
||||||
|
str(self.gamut_chart_frame): "gamut",
|
||||||
|
str(self.gamma_chart_frame): "gamma",
|
||||||
|
str(self.eotf_chart_frame): "eotf",
|
||||||
|
str(self.cct_chart_frame): "cct",
|
||||||
|
str(self.contrast_chart_frame): "contrast",
|
||||||
|
str(self.accuracy_chart_frame): "accuracy",
|
||||||
|
}
|
||||||
|
chart_name = tab_to_chart.get(selected_tab)
|
||||||
|
if chart_name:
|
||||||
|
self._ensure_chart_initialized(chart_name)
|
||||||
|
|
||||||
self._last_tab_index = self.chart_notebook.index(
|
self._last_tab_index = self.chart_notebook.index(
|
||||||
self.chart_notebook.select()
|
selected_tab
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log_gui.log(f"Tab切换事件处理失败: {str(e)}")
|
self.log_gui.log(f"Tab切换事件处理失败: {str(e)}")
|
||||||
@@ -6234,6 +6296,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
# 每完成一个 pattern,实时写入客户模板结果表。
|
# 每完成一个 pattern,实时写入客户模板结果表。
|
||||||
try:
|
try:
|
||||||
|
self._ensure_colour_loaded()
|
||||||
xy = colour.XYZ_to_xy(np.array([X, Y, Z]))
|
xy = colour.XYZ_to_xy(np.array([X, Y, Z]))
|
||||||
u_prime, v_prime, _ = colour.XYZ_to_CIE1976UCS(
|
u_prime, v_prime, _ = colour.XYZ_to_CIE1976UCS(
|
||||||
np.array([X, Y, Z])
|
np.array([X, Y, Z])
|
||||||
@@ -7145,6 +7208,7 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def plot_gamut(self, results, coverage, test_type):
|
def plot_gamut(self, results, coverage, test_type):
|
||||||
"""绘制色域图 - 根据用户选择的参考标准动态计算覆盖率"""
|
"""绘制色域图 - 根据用户选择的参考标准动态计算覆盖率"""
|
||||||
|
self._ensure_chart_initialized("gamut")
|
||||||
|
|
||||||
self.gamut_ax_xy.clear()
|
self.gamut_ax_xy.clear()
|
||||||
self.gamut_ax_uv.clear()
|
self.gamut_ax_uv.clear()
|
||||||
@@ -7670,6 +7734,8 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def plot_gamma(self, L_bar, results_with_gamma_list, target_gamma, test_type):
|
def plot_gamma(self, L_bar, results_with_gamma_list, target_gamma, test_type):
|
||||||
"""绘制Gamma曲线 + 数据表格(包含实测亮度)"""
|
"""绘制Gamma曲线 + 数据表格(包含实测亮度)"""
|
||||||
|
self._ensure_chart_initialized("gamma")
|
||||||
|
|
||||||
# ========== 1. 清空并重置左侧曲线 ==========
|
# ========== 1. 清空并重置左侧曲线 ==========
|
||||||
self.gamma_ax.clear()
|
self.gamma_ax.clear()
|
||||||
self.gamma_ax.set_xlim(0, 105)
|
self.gamma_ax.set_xlim(0, 105)
|
||||||
@@ -7804,6 +7870,8 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def plot_eotf(self, L_bar, results_with_eotf_list, test_type):
|
def plot_eotf(self, L_bar, results_with_eotf_list, test_type):
|
||||||
"""绘制 EOTF 曲线 + 数据表格(HDR 专用,包含实测亮度)"""
|
"""绘制 EOTF 曲线 + 数据表格(HDR 专用,包含实测亮度)"""
|
||||||
|
self._ensure_chart_initialized("eotf")
|
||||||
|
|
||||||
# ========== 1. 清空并重置左侧曲线 ==========
|
# ========== 1. 清空并重置左侧曲线 ==========
|
||||||
self.eotf_ax.clear()
|
self.eotf_ax.clear()
|
||||||
self.eotf_ax.set_xlim(0, 105)
|
self.eotf_ax.set_xlim(0, 105)
|
||||||
@@ -7985,6 +8053,8 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def plot_cct(self, test_type):
|
def plot_cct(self, test_type):
|
||||||
"""绘制 x 和 y 坐标分离图 - 每个点标注纵坐标值"""
|
"""绘制 x 和 y 坐标分离图 - 每个点标注纵坐标值"""
|
||||||
|
self._ensure_chart_initialized("cct")
|
||||||
|
|
||||||
self.cct_fig.clear()
|
self.cct_fig.clear()
|
||||||
|
|
||||||
gray_data = self.results.get_intermediate_data("shared", "gray")
|
gray_data = self.results.get_intermediate_data("shared", "gray")
|
||||||
@@ -8301,6 +8371,8 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def plot_contrast(self, contrast_data, test_type):
|
def plot_contrast(self, contrast_data, test_type):
|
||||||
"""绘制对比度测试结果 - 固定布局版本"""
|
"""绘制对比度测试结果 - 固定布局版本"""
|
||||||
|
self._ensure_chart_initialized("contrast")
|
||||||
|
|
||||||
# 清空并重置
|
# 清空并重置
|
||||||
self.contrast_ax.clear()
|
self.contrast_ax.clear()
|
||||||
self.contrast_ax.set_xlim(0, 1)
|
self.contrast_ax.set_xlim(0, 1)
|
||||||
@@ -8462,6 +8534,8 @@ class PQAutomationApp:
|
|||||||
|
|
||||||
def plot_accuracy(self, accuracy_data, test_type):
|
def plot_accuracy(self, accuracy_data, test_type):
|
||||||
"""绘制色准测试结果 - 29色显示 - 简洁版布局(显示 Gamma)"""
|
"""绘制色准测试结果 - 29色显示 - 简洁版布局(显示 Gamma)"""
|
||||||
|
self._ensure_chart_initialized("accuracy")
|
||||||
|
|
||||||
self.accuracy_ax.clear()
|
self.accuracy_ax.clear()
|
||||||
self.accuracy_ax.set_xlim(0, 1)
|
self.accuracy_ax.set_xlim(0, 1)
|
||||||
self.accuracy_ax.set_ylim(0, 1)
|
self.accuracy_ax.set_ylim(0, 1)
|
||||||
|
|||||||
@@ -74,8 +74,19 @@ a = Analysis(
|
|||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
excludes=['PyQt5'],
|
excludes=[
|
||||||
|
'PyQt5',
|
||||||
|
'PyQt6',
|
||||||
|
'PySide2',
|
||||||
|
'PySide6',
|
||||||
|
'cv2',
|
||||||
|
'imageio',
|
||||||
|
'imageio_ffmpeg',
|
||||||
|
'IPython',
|
||||||
|
'jedi',
|
||||||
|
],
|
||||||
noarchive=False,
|
noarchive=False,
|
||||||
|
# numpy 在运行时依赖部分 docstring,optimize=2 会移除 docstring 导致启动报错。
|
||||||
optimize=0,
|
optimize=0,
|
||||||
)
|
)
|
||||||
pyz = PYZ(a.pure)
|
pyz = PYZ(a.pure)
|
||||||
@@ -89,7 +100,8 @@ exe = EXE(
|
|||||||
debug=False,
|
debug=False,
|
||||||
bootloader_ignore_signals=False,
|
bootloader_ignore_signals=False,
|
||||||
strip=False,
|
strip=False,
|
||||||
upx=True,
|
# 关闭 UPX:通常可减少启动时解压与杀软扫描开销,提升冷启动体感。
|
||||||
|
upx=False,
|
||||||
console=False,
|
console=False,
|
||||||
disable_windowed_traceback=False,
|
disable_windowed_traceback=False,
|
||||||
argv_emulation=False,
|
argv_emulation=False,
|
||||||
@@ -105,7 +117,7 @@ coll = COLLECT(
|
|||||||
a.binaries,
|
a.binaries,
|
||||||
a.datas,
|
a.datas,
|
||||||
strip=False,
|
strip=False,
|
||||||
upx=True,
|
upx=False,
|
||||||
upx_exclude=[],
|
upx_exclude=[],
|
||||||
name='pqAutomationApp',
|
name='pqAutomationApp',
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user