Files
gplan-2/tools/golden_compare.py
T

79 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
r"""golden_compare.py — C 档黄金图对比(呈现层测试分级·渲染闸周期件)。
用法: python tools/golden_compare.py <黄金图目录> <新截图目录> [屏清单...]
默认屏清单 = shot_menu.png shot_camp.png shot_level.png shot_battle.png。
判据(容差口径,v1 冻结):
① 四屏存在且尺寸一致(与黄金图逐屏比对);
② 逐像素灰度差 >16 的像素占比 ≤2%(抗锯齿/微噪声容差带——结构级变化必超带);
③ changed 占比 >2% 即 FAIL(视觉回归信号——逐屏列差异热区提示)。
基准冻结于 v3.5 视觉落码+营地终稿+分辨率案甲后;资产升档换代时显式重制基准。
退出码: 0 = 全过 / 1 = 有失败。
"""
import sys
from pathlib import Path
from PIL import Image, ImageChops
TOLERANCE = 16 # 灰度差容差(单通道)
FAIL_RATIO = 0.02 # changed 占比失败线
# 基线平台子目录:<黄金图根目录>/<windows|mac|linux>——渲染基线按平台各存(gate_platform_id 同口径),
# 平台内部照常逐像素严格比对;跨平台不互比(字形/抗锯齿机制差异,2026-11-03 用户裁)。
_PLAT = {"win32": "windows", "darwin": "mac"}.get(sys.platform, "linux")
def plat_missing(base: Path) -> bool:
return not (base / _PLAT).is_dir()
def compare(base: Path, curr: Path, name: str, failures: list) -> None:
pb, pc = base / name, curr / name
if not pb.exists():
failures.append("%s: 黄金图缺失(基准未建)" % name)
return
if not pc.exists():
failures.append("%s: 新截图缺失" % name)
return
a = Image.open(pb).convert("L")
b = Image.open(pc).convert("L")
if a.size != b.size:
failures.append("%s: 尺寸 %s != 基准 %s" % (name, b.size, a.size))
return
diff = ImageChops.difference(a, b)
hist = diff.histogram()
total = a.size[0] * a.size[1]
changed = sum(hist[TOLERANCE + 1:]) / total
print("[golden] %s — changed=%.2f%%(容差 ≤%.0f 差/≤%.0f%%)%s" % (
name, changed * 100, TOLERANCE, FAIL_RATIO * 100, "OK" if changed <= FAIL_RATIO else "FAIL"))
if changed > FAIL_RATIO:
failures.append("%s: changed %.2f%% > %.0f%%(视觉回归——核对热区后重制或修复)" % (name, changed * 100, FAIL_RATIO * 100))
def main() -> int:
if len(sys.argv) < 3:
print("用法: python tools/golden_compare.py <黄金图目录> <新截图目录> [屏清单...]")
return 1
base, curr = Path(sys.argv[1]), Path(sys.argv[2])
base = base / _PLAT
if not base.is_dir():
print("[golden] FAIL — 本平台(%s)基线目录未建:%s" % (_PLAT, base))
print(" 处置:在该平台跑 tools/golden_baseline_refresh.sh 重制基线并提交(基线换代权限 Q6)")
return 1
shots = sys.argv[3:] or ["shot_menu.png", "shot_camp.png", "shot_level.png", "shot_battle.png"]
failures = []
for name in shots:
compare(base, curr, name, failures)
if failures:
print("[golden] FAIL——")
for f in failures:
print(" - %s" % f)
return 1
print("[golden] PASS(%d 屏黄金图对比全过)" % len(shots))
return 0
if __name__ == "__main__":
sys.exit(main())