mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-13 14:52:19 +00:00
test(cctv): lock the still draw path and fit-aware dedupe
Drive drawProjectionFrame with a fake runtime and a recording canvas: a 640x480 still draws at its fitted rectangle over the matte, the same pixels at the same size skip the redraw, and the same pixels at a new aspect redraw at the new fit. The last case fails on the pixel-only signature; the first fails if drawImage stretches to the canvas again. Expected rectangles now read the canvas size from policy.js. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
56c5d03b65
commit
35c612c5f6
1 file changed
+106
-2
@@ -3,9 +3,25 @@
|
|||||||
// 1920x1080 projection canvas, instead of being stretched to fill it.
|
// 1920x1080 projection canvas, instead of being stretched to fill it.
|
||||||
import { test } from 'node:test';
|
import { test } from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import { fitToProjection } from './frames.js';
|
import { createFrames, fitToProjection } from './frames.js';
|
||||||
|
import {
|
||||||
|
FRAME_SIGNATURE_W,
|
||||||
|
FRAME_SIGNATURE_H,
|
||||||
|
PROJECTION_CANVAS_WIDTH,
|
||||||
|
PROJECTION_CANVAS_HEIGHT,
|
||||||
|
PROJECTION_MATTE_COLOR,
|
||||||
|
} from './policy.js';
|
||||||
|
|
||||||
const FULL_CANVAS = { x: 0, y: 0, w: 1920, h: 1080 };
|
// The expected rectangles below are written for a 1920x1080 canvas.
|
||||||
|
assert.equal(PROJECTION_CANVAS_WIDTH, 1920);
|
||||||
|
assert.equal(PROJECTION_CANVAS_HEIGHT, 1080);
|
||||||
|
|
||||||
|
const FULL_CANVAS = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
w: PROJECTION_CANVAS_WIDTH,
|
||||||
|
h: PROJECTION_CANVAS_HEIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
test('a 4:3 still is pillarboxed at full height', () => {
|
test('a 4:3 still is pillarboxed at full height', () => {
|
||||||
assert.deepEqual(fitToProjection(640, 480), {
|
assert.deepEqual(fitToProjection(640, 480), {
|
||||||
@@ -35,3 +51,91 @@ test('a missing or zero dimension falls back to the full canvas', () => {
|
|||||||
assert.deepEqual(fitToProjection(640, undefined), FULL_CANVAS);
|
assert.deepEqual(fitToProjection(640, undefined), FULL_CANVAS);
|
||||||
assert.deepEqual(fitToProjection(undefined, undefined), FULL_CANVAS);
|
assert.deepEqual(fitToProjection(undefined, undefined), FULL_CANVAS);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Draw path: the fit reaches drawImage, and the unchanged-frame skip keys on the
|
||||||
|
// fitted size as well as the pixels (the 64x36 hash alone drops aspect).
|
||||||
|
function stillHarness() {
|
||||||
|
const calls = [];
|
||||||
|
const ctx = {
|
||||||
|
fillStyle: null,
|
||||||
|
fillRect: (...rect) => calls.push(['fillRect', ctx.fillStyle, ...rect]),
|
||||||
|
clearRect: () => {},
|
||||||
|
drawImage: (_image, ...rect) => calls.push(['drawImage', ...rect]),
|
||||||
|
};
|
||||||
|
// Every frame downsamples to the same pixels, so only the size differs.
|
||||||
|
const pixels = new Uint8ClampedArray(
|
||||||
|
FRAME_SIGNATURE_W * FRAME_SIGNATURE_H * 4,
|
||||||
|
).fill(7);
|
||||||
|
const runtime = {
|
||||||
|
mode: 'image',
|
||||||
|
ctx,
|
||||||
|
image: { naturalWidth: 0, naturalHeight: 0 },
|
||||||
|
imageReady: true,
|
||||||
|
// In flight, so refreshProjectionImage returns before touching image.src.
|
||||||
|
imageLoading: true,
|
||||||
|
imageStamp: 0,
|
||||||
|
drawnImageStamp: -1,
|
||||||
|
lastFrameSignature: null,
|
||||||
|
canvasStamp: 0,
|
||||||
|
signatureCtx: {
|
||||||
|
clearRect: () => {},
|
||||||
|
drawImage: () => {},
|
||||||
|
getImageData: () => ({ data: pixels }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const record = { camera: { id: 'still' }, projection: runtime };
|
||||||
|
const { drawProjectionFrame } = createFrames({
|
||||||
|
state: { _healthById: new Map(), _activeCameraId: null },
|
||||||
|
services: {},
|
||||||
|
parts: {},
|
||||||
|
source: {},
|
||||||
|
});
|
||||||
|
const load = (width, height) => {
|
||||||
|
runtime.image = { naturalWidth: width, naturalHeight: height };
|
||||||
|
runtime.imageStamp += 1;
|
||||||
|
calls.length = 0;
|
||||||
|
drawProjectionFrame(record);
|
||||||
|
return calls.slice();
|
||||||
|
};
|
||||||
|
return { runtime, load };
|
||||||
|
}
|
||||||
|
|
||||||
|
test('a still is drawn into its fitted rectangle over a full matte', () => {
|
||||||
|
const { runtime, load } = stillHarness();
|
||||||
|
assert.deepEqual(load(640, 480), [
|
||||||
|
[
|
||||||
|
'fillRect',
|
||||||
|
PROJECTION_MATTE_COLOR,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
PROJECTION_CANVAS_WIDTH,
|
||||||
|
PROJECTION_CANVAS_HEIGHT,
|
||||||
|
],
|
||||||
|
['drawImage', 240, 0, 1440, 1080],
|
||||||
|
]);
|
||||||
|
assert.equal(runtime.canvasStamp, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('same pixels at the same size skip the redraw', () => {
|
||||||
|
const { runtime, load } = stillHarness();
|
||||||
|
load(640, 480);
|
||||||
|
assert.deepEqual(load(640, 480), []);
|
||||||
|
assert.equal(runtime.canvasStamp, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('same pixels at a new aspect redraw at the new fit', () => {
|
||||||
|
const { runtime, load } = stillHarness();
|
||||||
|
load(640, 480);
|
||||||
|
assert.deepEqual(load(1920, 1080), [
|
||||||
|
[
|
||||||
|
'fillRect',
|
||||||
|
PROJECTION_MATTE_COLOR,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
PROJECTION_CANVAS_WIDTH,
|
||||||
|
PROJECTION_CANVAS_HEIGHT,
|
||||||
|
],
|
||||||
|
['drawImage', 0, 0, 1920, 1080],
|
||||||
|
]);
|
||||||
|
assert.equal(runtime.canvasStamp, 2);
|
||||||
|
});
|
||||||
Reference in new issue
Block a user