fix(photos): shared EXIF-oriented decode for axis/overlay space (#72)
PhotoStage used new Image() while mask worker and calculate used bare createImageBitmap; Orientation-8 matched-set JPEGs can disagree across those paths so the approved pink axis is not the overlay (ux,uy). One decodeOrientedBitmap helper always requests imageOrientation from-image (with bare fallback), wired into PhotoStage, mask.worker, and session calculate/siblings.
This commit is contained in:
@@ -545,6 +545,43 @@ function tiltedAxis25Fixture() {
|
||||
return { W, H, bitset, bbox, ux0, uy0, rx0, ry0, halfL, cx, cy };
|
||||
}
|
||||
|
||||
|
||||
test('buildOverlayPlan: angleDeg=90 vertical long side → width left→right within 2° of horizontal (#72)', () => {
|
||||
// Upright slab: approved length axis is vertical (angleDeg 90). Width marks must
|
||||
// run left→right ≈ horizontal (atan2 ≈ 0 or ±π), not slanted with the photo.
|
||||
const W = 200, H = 400;
|
||||
const bitset = new Uint8Array(W * H);
|
||||
for (let y = 40; y <= 360; y++) {
|
||||
for (let x = 60; x <= 140; x++) bitset[y * W + x] = 1;
|
||||
}
|
||||
const prev = minAreaRect(bitset, W, H)!;
|
||||
const bbox = orientedRect(prev, 90);
|
||||
assert.equal(bbox.angleDeg, 90);
|
||||
const scale = 10; // 320px span ≈ 32"
|
||||
const plan = buildOverlayPlan({
|
||||
bitset,
|
||||
widthPx: W,
|
||||
heightPx: H,
|
||||
bbox,
|
||||
scale,
|
||||
lengthIn: 32,
|
||||
lengthLabel: '32"',
|
||||
mapToInventory: (x, y) => [x, y],
|
||||
});
|
||||
assert.ok(plan.widths.length > 0, 'expected width stations');
|
||||
for (const w of plan.widths) {
|
||||
const ang = Math.atan2(w.right[1] - w.left[1], w.right[0] - w.left[0]);
|
||||
// Fold to [-90, 90] so left→right and right→left both count as horizontal.
|
||||
let deg = (ang * 180) / Math.PI;
|
||||
if (deg > 90) deg -= 180;
|
||||
if (deg < -90) deg += 180;
|
||||
assert.ok(
|
||||
Math.abs(deg) <= 2,
|
||||
`width station ${w.stationIn} left→right must be within 2° of horizontal (atan2 deg=${deg.toFixed(2)}; left=${w.left} right=${w.right})`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('buildOverlayPlan: length a→b || approved (ux,uy); width left→right || (rx,ry) (#70)', () => {
|
||||
const { W, H, bitset, bbox, cx, cy } = tiltedAxis25Fixture();
|
||||
const scale = 10;
|
||||
|
||||
Reference in New Issue
Block a user