//#region src/core/frame-report.d.ts /** * What the frame looks like, as something worth saying. * * The pixels are not the deliverable. A 1280x720 frame is 2.8 million numbers: * unreadable by a person, unaffordable for a model (roughly a thousand tokens * as an image, roughly a million as text). The deliverable is the JUDGEMENT — * black screen, one flat colour, washed out — and the numbers behind it, small * enough to print and compare. * * Same principle as `framing`'s "lit by: NOTHING": a report is a sentence * before it is a number, because a number needs a reader who already knows what * to compare it against. * * Pure arithmetic over an RGBA buffer — no three, no DOM, no GPU. Whoever has * the pixels calls this; in practice that is the browser holding the canvas. */ /** Per-cell mean colour, `[r, g, b]` 0..255. */ type GridCell = [number, number, number]; interface FrameStats { width: number; height: number; /** Every pixel below the black threshold — the render produced nothing. */ black: boolean; /** One colour everywhere: a clear-colour fill, or a camera inside geometry. */ uniform: boolean; /** 0..1 mean relative luminance. */ meanLuma: number; /** Coarse mean colour per cell, rows top to bottom. */ grid: GridCell[][]; /** What the frame is OF, or null when it is all background. */ subject: Subject | null; /** * The page was HIDDEN when these pixels were read, so they are whatever it * last drew. * * Added by the page, not computed from pixels — a stale buffer looks exactly * like a live one. Undefined for a capture that never came from a browser. */ hidden?: boolean; } /** * The thing in the shot: everything that is not the background. * * `black` and `uniform` answer "did anything render at all". They do not answer * the question that actually goes wrong — "is the thing IN the shot, and can * you see it" — and every visual defect reported against the editor's model * previews walked straight past them. A white square with a faint sky gradient * is neither black nor uniform; a character drawn as a speck in the corner has * a perfectly ordinary mean luminance. */ interface Subject { /** Bounding box in pixels, origin top-left. */ box: { x: number; y: number; w: number; h: number; }; /** Share of the frame's pixels that are subject, 0..1. */ coverage: number; /** Touching an edge — the shot is a crop, and something is outside it. */ clipped: boolean; } interface FrameStatsOptions { /** Cells across and down. Default 16x9 — 144 cells, printable. */ grid?: [number, number]; } declare function frameStats(pixels: Uint8Array | Uint8ClampedArray, width: number, height: number, opts?: FrameStatsOptions): FrameStats; /** The report a person or an agent reads. Verdict first, numbers after. */ declare function frameText(stats: FrameStats): string; /** * Comparison resolution. Fine enough that a one-pixel line moves a cell by * several levels at 720p, small enough (6912 bytes) to hold and to send. */ declare const SIGNATURE_GRID: readonly [number, number]; interface FrameSignature { /** The frame this was made from — a different size is not comparable. */ width: number; height: number; cols: number; rows: number; /** base64 of `cols * rows * 3` bytes: cell means, rows top to bottom. */ data: string; } interface FrameDiff { /** False when the two cannot be subtracted at all; see `reason`. */ comparable: boolean; reason?: string; /** 0..1 fraction of cells that moved past the threshold. */ changed: number; /** Largest single-channel move, 0..255. */ maxDelta: number; /** Mean single-channel move across the frame, 0..255. */ meanDelta: number; /** Where the change is, in pixels of the compared frame. */ box: { x: number; y: number; w: number; h: number; } | null; /** A thin full-length band is worth naming: that is what a seam looks like. */ shape: "vertical band" | "horizontal band" | null; } declare function frameSignature(pixels: Uint8Array | Uint8ClampedArray, width: number, height: number, grid?: readonly [number, number]): FrameSignature; declare function diffSignatures(before: FrameSignature, after: FrameSignature, opts?: { threshold?: number; }): FrameDiff; /** The comparison a person or an agent reads. */ declare function diffText(diff: FrameDiff): string; //#endregion export { GridCell as a, diffText as c, frameText as d, FrameStatsOptions as i, frameSignature as l, FrameSignature as n, SIGNATURE_GRID as o, FrameStats as r, diffSignatures as s, FrameDiff as t, frameStats as u };