55 lines
3.7 KiB
Python
55 lines
3.7 KiB
Python
"""Compare fixed REA captures with the one calibrated YCode header fixture mode."""
|
|
from pathlib import Path
|
|
from hashlib import sha256
|
|
import json
|
|
from PIL import Image, ImageChops
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
OUTPUT = ROOT / '.tmp/chat-header-native-swiftshader-20261016'
|
|
report = json.loads((OUTPUT / 'report.json').read_text(encoding='utf-8'))
|
|
rendering = report['rendering']
|
|
assert rendering['mode'] == 'visible-swiftshader' and rendering['visible']
|
|
assert rendering['gpu']['auxAttributes']['displayType'] == 'ANGLE_SWIFTSHADER'
|
|
assert rendering['gpu']['auxAttributes']['glImplementationParts'] == '(gl=egl-angle,angle=swiftshader)'
|
|
assert rendering['gpuFeatures']['gpu_compositing'] == 'disabled_software'
|
|
regions = [
|
|
('title', 'rea-chat-header-final-20261016/workbuddy.png', 'collapsed.png', (308, 50, 388, 74), []),
|
|
('search-button', 'rea-chat-header-final-20261016/workbuddy.png', 'collapsed.png', (1215, 46, 1248, 78), []),
|
|
('share-button', 'rea-chat-header-final-20261016/workbuddy.png', 'collapsed.png', (1251, 46, 1284, 78), []),
|
|
('panel-button', 'rea-chat-header-final-20261016/workbuddy.png', 'collapsed.png', (1287, 46, 1320, 78), []),
|
|
('header', 'rea-chat-header-final-20261016/workbuddy.png', 'collapsed.png', (285, 30, 1336, 94), []),
|
|
# Empty query: no dynamic counter. Exclude only the 3px caret column at the input start.
|
|
('search', 'rea-chat-header-title-20261016/workbuddy.png', 'search.png', (947, 46, 1248, 78), [(977, 50, 980, 74)]),
|
|
('edit-selected-title', 'rea-chat-header-title-20261016/frame-001.png', 'edit.png', (308, 50, 512, 74), []),
|
|
]
|
|
results = []
|
|
for name, reference, candidate, box, masks in regions:
|
|
source_path, own_path = ROOT / '.tmp' / reference, OUTPUT / candidate
|
|
a, b = Image.open(source_path).convert('RGB'), Image.open(own_path).convert('RGB')
|
|
assert a.size == b.size == (1336, 901)
|
|
diff = ImageChops.difference(a.crop(box), b.crop(box))
|
|
compared, changed, total, maximum = 0, 0, 0, 0
|
|
differences = []
|
|
for y in range(box[1], box[3]):
|
|
for x in range(box[0], box[2]):
|
|
if any(l <= x < r and t <= y < bt for l, t, r, bt in masks):
|
|
continue
|
|
delta = diff.getpixel((x - box[0], y - box[1]))
|
|
compared += 1
|
|
if any(delta):
|
|
changed += 1
|
|
differences.append({'x': x, 'y': y, 'source': a.getpixel((x, y)), 'candidate': b.getpixel((x, y))})
|
|
total += sum(delta)
|
|
maximum = max(maximum, *delta)
|
|
diff.save(OUTPUT / (name + '-diff.png'))
|
|
results.append({'name': name, 'source': reference, 'candidate': candidate, 'box': box, 'masks': masks,
|
|
'sourceSha256': sha256(source_path.read_bytes()).hexdigest(), 'candidateSha256': sha256(own_path.read_bytes()).hexdigest(),
|
|
'comparedPixels': compared, 'differentPixels': changed, 'maxChannelDifference': maximum,
|
|
'meanAbsoluteChannelDifference': total / (compared * 3), 'differentPixelSamples': differences[:60]})
|
|
summary = {'mode': rendering['mode'], 'displayType': rendering['gpu']['auxAttributes']['displayType'],
|
|
'gpuCompositing': rendering['gpuFeatures']['gpu_compositing'], 'channelTolerance': 0,
|
|
'regions': results, 'limitations': ['Fixed Windows/DPR1/1336x901 component fixture only. Production integration, tooltips, prompt-list states, compact/Mac/dark are outside these pixel results.',
|
|
'Remaining different pixels are preserved and reported; no tolerance or reference-pixel patch was applied.']}
|
|
(OUTPUT / 'pixels.json').write_text(json.dumps(summary, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
print(json.dumps([{'name': r['name'], 'pixels': r['comparedPixels'], 'different': r['differentPixels'], 'max': r['maxChannelDifference']} for r in results]))
|