P4 native frames (classic/polaroid/wallframe) + GPS watermark verified on Xiaomi (sample gates pass)

This commit is contained in:
2026-09-09 16:34:24 +07:00
parent 11635a0d33
commit 25e4f21917
4 changed files with 380 additions and 10 deletions
+24 -1
View File
@@ -41,7 +41,7 @@ export async function nativeBenchProbe(): Promise<void> {
const { matrix, ...adj } = o;
const dst = src.replace(/\.png$/, `-${tag}-${Date.now()}.jpg`);
const t = await m.processPhotoAsync(src, dst, matrix ?? IDENTITY, null, adj);
console.error(`[BENCH] ${tag} totalMs=${t.totalMs} decodeMs=${t.decodeMs} toneMs=${t.toneMs ?? 0} cinemaMs=${t.cinemaMs ?? 0} colorMs=${t.colorMs} clarityMs=${t.clarityMs ?? 0} grainMs=${t.grainMs ?? 0} encodeWriteMs=${t.encodeWriteMs}`);
console.error(`[BENCH] ${tag} totalMs=${t.totalMs} decodeMs=${t.decodeMs} toneMs=${t.toneMs ?? 0} cinemaMs=${t.cinemaMs ?? 0} colorMs=${t.colorMs} clarityMs=${t.clarityMs ?? 0} grainMs=${t.grainMs ?? 0} frameMs=${t.frameMs ?? 0} encodeWriteMs=${t.encodeWriteMs}`);
};
const src: string = await m.materializeBenchAsset('wallframe');
@@ -94,6 +94,29 @@ export async function nativeBenchProbe(): Promise<void> {
const gray100 = await m.materializeSolidAsset(100, 100, 100);
await run('grain10-100', gray100, { grain: 10 });
// P4 frame parity on solid gray100 64x64 — border/bar/card colors and the
// composed output geometry are fully predictable, so probeSamples assert
// exact pixels. Expected (offline verifier re-checks):
// classic-white: (1,1)=white border, (32,32)=100 photo, size 64x64.
// cinematic: (1,1)=black bar, (32,32)=100, size 64x64.
// polaroid: outH=round(64*(SIDE+DECK)+64*WIN_W)=78; (1,1)=card #FAF9F6,
// (32,32)=100 photo, (32,70)=card deck.
await run('frame-classic', gray100, { frameId: 'classic-white', png: true, probeSamples: [{ x: 1, y: 1 }, { x: 32, y: 32 }] });
await run('frame-cinematic', gray100, { frameId: 'cinematic', png: true, probeSamples: [{ x: 1, y: 1 }, { x: 32, y: 32 }] });
await run('frame-polaroid', gray100, { frameId: 'polaroid', png: true, probeSamples: [{ x: 1, y: 1 }, { x: 32, y: 32 }, { x: 32, y: 70 }] });
// wallframe: export becomes the fixed 3117x4000 rotated artwork; center is
// the cover-cropped photo (100), mat samples compare against wallframe.png
// pixels offline (display->source: (dx,dy)->(dy, 3117-dx)). Art + fonts are
// resolved natively from bundled resources — embedded metro assets expose
// no readable file URI to JS (readAsStringAsync rejects 'wallframe').
await run('frame-wallframe', gray100, { frameId: 'wallframe', png: true, probeSamples: [{ x: 100, y: 1500 }, { x: 2900, y: 200 }, { x: 1559, y: 1998 }] });
// P4 GPS watermark (no frame): 400x400 gray base, stamp bottom-left.
// probeStampDiff logs stampPixelDiff/amber/white after drawing — counts > 0
// prove the emoji + amber text actually rendered (vs a silent no-op).
const gray400 = await m.materializeSolidSized(400, 400, 100, 100, 100);
await run('geo-stamp', gray400, { geo: { locality: 'HANOI TEST', timestamp: Date.now() }, png: true, probeStampDiff: true });
// Full-artwork run: provia + tone + cinema + all enhance passes, 12MP.
const provia = applyExposureGain(getSkiaColorMatrix('provia' as BaseFilter, NEUTRAL_ADJ), 0);
for (let i = 0; i < RUNS; i++) {