44 lines
2.2 KiB
Python
44 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Derive H5 crops from exported PSD assets; never crop the original exports."""
|
|
from pathlib import Path
|
|
from PIL import Image
|
|
import json
|
|
import cv2
|
|
import numpy as np
|
|
|
|
root = Path(__file__).resolve().parents[1] / 'h5/assets/img/ui-20261009'
|
|
for name in ['bg-splash', 'bg-login', 'bg-profile', 'bg-history', 'bg-report']:
|
|
source = Image.open(root / (name + '.jpg'))
|
|
# Native status/navigation area belongs to the host, not the H5 document.
|
|
top = 253 if name == 'bg-report' else 248
|
|
source.crop((0, top, source.width, source.height)).save(root / (name + '-h5.jpg'), quality=92, optimize=True)
|
|
# Mobile delivery variant; preserve the full-resolution PSD exports/JPEGs.
|
|
Image.open(root / (name + '-h5.jpg')).save(root / (name + '-h5.webp'), quality=85, method=6)
|
|
|
|
geometry = []
|
|
for direction in ['front', 'left', 'right']:
|
|
alpha = np.array(Image.open(root / ('camera-mask-' + direction + '.png')).getchannel('A'))
|
|
contours, _ = cv2.findContours((alpha < 100).astype('uint8'), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
contour = max((c for c in contours if 500 < cv2.boundingRect(c)[1] < 1600), key=cv2.contourArea)
|
|
points = cv2.approxPolyDP(contour, 1.4, True).reshape(-1, 2)
|
|
outline = 'M' + 'L'.join(f'{x/2.88:.2f},{y/2.88:.2f}' for x, y in points) + 'Z'
|
|
guide_alpha = np.array(Image.open(root / ('camera-guide-' + direction + '.png')).getchannel('A'))
|
|
count, labels, stats, _ = cv2.connectedComponentsWithStats((guide_alpha > 100).astype('uint8'))
|
|
guides = []
|
|
for i in range(1, count):
|
|
x, y, w, h, area = stats[i]
|
|
if area < 50:
|
|
continue
|
|
points = []
|
|
if w > h:
|
|
for col in range(x, x+w, 3):
|
|
rows = np.where(labels[:, col] == i)[0]
|
|
if len(rows): points.append((col, rows.mean()))
|
|
else:
|
|
for row in range(y, y+h, 3):
|
|
cols = np.where(labels[row, :] == i)[0]
|
|
if len(cols): points.append((cols.mean(), row))
|
|
guides.append('M' + 'L'.join(f'{px/2.88:.2f},{py/2.88:.2f}' for px, py in points))
|
|
geometry.append({'outline': outline, 'guides': guides})
|
|
(root.parents[2] / 'js/camera-geometry.js').write_text('window.CameraGeometry = ' + json.dumps(geometry) + ';\n')
|