P1 native color matrix + crop (processColorAsync): parity verified on Xiaomi (classic-neg on black -> rgb(13,5,0), translate*255)
This commit is contained in:
@@ -1,22 +1,51 @@
|
||||
import RecipescamExport from '../../modules/recipescam-export';
|
||||
import { applyExposureGain, getSkiaColorMatrix } from '../utils/colorUtils';
|
||||
import { BaseFilter, ColorAdjustments } from '../types';
|
||||
|
||||
const RUNS = 3;
|
||||
|
||||
const NEUTRAL_ADJ: ColorAdjustments = {
|
||||
exposure: 0,
|
||||
contrast: 0,
|
||||
saturation: 0,
|
||||
temperature: 5500,
|
||||
tint: 0,
|
||||
highlight: 0,
|
||||
shadow: 0,
|
||||
denoise: 0,
|
||||
clarity: 0,
|
||||
grain: 0,
|
||||
colorChrome: 'none',
|
||||
colorChromeBlue: 'none',
|
||||
dynamicRange: 100,
|
||||
sharpening: 0,
|
||||
exposureCompensation: 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* P0 spike harness (temporary — removed at P7). Runs native decode+encode on
|
||||
* the bundled wallframe artwork (3117x4000, representative of a 12MP export)
|
||||
* and logs per-stage ms proving the JS thread is not blocked while native work
|
||||
* runs. Gated by EXPO_PUBLIC_BENCH=1.
|
||||
*
|
||||
* Release-build visibility is via native Log.i (RecipesCamExport tag) because
|
||||
* Hermes release builds strip console.* entirely. JS-side dispatch gaps appear
|
||||
* as the logcat deltas between consecutive decode "start" lines.
|
||||
* P0/P1 probe harness (temporary — removed at P7).
|
||||
* P0: native decode+encode on the bundled wallframe artwork (3117x4000).
|
||||
* P1: native color matrix + crop path. Parity trick: classic-neg matrix applied
|
||||
* to a pure-black image must yield translate*255 per channel in the native
|
||||
* filter (Skia 0..1 space -> Android 0..255 space), i.e. ~(13, 5, 0); the
|
||||
* center pixel is logged natively (RecipesCamExport tag) since release Hermes
|
||||
* strips console.*.
|
||||
*/
|
||||
export async function nativeBenchProbe(): Promise<void> {
|
||||
const m = RecipescamExport as any;
|
||||
try {
|
||||
const pong = await m.ping();
|
||||
const src: string = await m.materializeBenchAsset('wallframe');
|
||||
// P1 parity: classic-neg matrix on black -> expect center ~(13,5,0).
|
||||
const matrix = applyExposureGain(getSkiaColorMatrix('classic-neg' as BaseFilter, NEUTRAL_ADJ), 0);
|
||||
const black = await m.materializeBlackAsset();
|
||||
const blackOut = black.replace(/\.png$/, `-neg-${Date.now()}.jpg`);
|
||||
await m.processColorAsync(black, blackOut, matrix, null, 95);
|
||||
console.error('[BENCH] classic-neg-on-black matrix[0..4]=' + matrix.slice(0, 5).join(','));
|
||||
|
||||
// P0 runs (decode+encode) + P1 identity-matrix run on the real artwork.
|
||||
const identity = new Array(20).fill(0);
|
||||
identity[0] = identity[6] = identity[12] = identity[18] = 1;
|
||||
for (let i = 0; i < RUNS; i++) {
|
||||
const t0 = Date.now();
|
||||
const dst = src.replace(/\.png$/, `-out-${Date.now()}-${i}.jpg`);
|
||||
@@ -26,6 +55,11 @@ export async function nativeBenchProbe(): Promise<void> {
|
||||
' decodeMs=' + timings.decodeMs + ' encodeWriteMs=' + timings.encodeWriteMs +
|
||||
' totalMs=' + timings.totalMs + ' pong=' + pong
|
||||
);
|
||||
// P1 crop: center 2000x2000 window of the 3117x4000 artwork.
|
||||
const crop = { x: Math.round((3117 - 2000) / 2), y: Math.round((4000 - 2000) / 2), width: 2000, height: 2000 };
|
||||
const colorDst = src.replace(/\.png$/, `-color-${Date.now()}-${i}.jpg`);
|
||||
const ct = await m.processColorAsync(src, colorDst, identity, crop, 95);
|
||||
console.error('[BENCH] colorRun=' + i + ' decodeMs=' + ct.decodeMs + ' colorMs=' + ct.colorMs + ' encodeWriteMs=' + ct.encodeWriteMs + ' totalMs=' + ct.totalMs);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[BENCH] failed', e);
|
||||
|
||||
Reference in New Issue
Block a user