image
Work against a reference image in world coordinates: cut it into a georeferenced tile grid, draw world-space marks on it, and diff two of them.
What it’s for
This namespace lets your assistant work against a reference image in world coordinates: cut one into a georeferenced tile grid, draw world-space marks onto it, and place two of them side by side with a difference composite. Every coordinate going in and coming out is world centimetres, so nothing here asks anyone to do pixel arithmetic by hand.
Reach for it when the assistant is placing things against a plan, a blockout, or a screenshot of how the level should look. The loop it exists to close is: estimate a world position, draw it back onto the reference, look at it, correct. Eyeballing a coordinate on a whole-map reference is where the error comes from — in one measured run an estimate was off by roughly 1,200 world units because the image was being read downsampled, and cutting it into native-resolution tiles improved that by about 10x.
Every operation is deterministic — crop, draw, blend — and writes a file you can open.
There is no thresholding, no feature detection, and no verdict anywhere: a comparison reports
differing-pixel counts and per-channel statistics and lets you judge, and an overlay mark reports
drawn only when the pixels under it actually changed. Anything that cannot be
represented exactly is refused rather than rounded.
Examples
Cut a reference map into georeferenced tiles
One georeference describes the ground the whole image covers. The manifest records each tile's world extent plus a standalone georeference for that tile alone, so tile (r,c) of the reference and tile (r,c) of a capture cover the same ground by construction, at any resolution.
You: Cut the level reference map into a 4x2 grid over the playable area.
call("image.tile", {image:"Docs/reference/level_plan.png",
georeference:{axes:"top_down_x_right_y_down",
worldMin:{x:-10000, y:-5000, z:0}, worldMax:{x:10000, y:5000, z:0},
cols:4, rows:2}})
→ {ok:true, tiles:8, manifest:".../level_plan_manifest.json",
grid:{tilePixelWidth:1024, worldUnitsPerPixelAcross:4.88, squarePixels:true}}
Done. Eight tiles at 4.88 cm per pixel; each one carries its own georeference.
Mark a world position on the reference and check it
Positions are world points, not pixels. The response reports the pixel each mark landed on, in both
tile and whole-image space, and says inFrame: false rather than clamping a point that
falls outside the tile.
You: Mark where you are about to put the radio tower, with a 500 cm grid.
call("image.annotate", {image:".../level_plan_r0c2.png",
georeferenceFrom:".../level_plan_manifest.json", georeferenceFromTile:{col:2, row:0},
grid:{spacingCm:500}, crosshairs:[{x:3200, y:-1450, label:"tower"}]})
→ {ok:true, marksDrawn:1, pixelsChanged:14208,
crosshairs:[{label:"tower", pixel:{x:614, y:727}, inFrame:true, drawn:true}]}
Marked at pixel (614, 727). Open the annotated PNG and tell me if that is the spot.
Diff a capture against the reference
Both georeferences must be supplied together, and a mismatch is refused by name: different ground
is GEOREFERENCE_MISMATCH, different resolution is IMAGE_SIZE_MISMATCH,
because those have different fixes.
You: How close is the blockout to the plan?
call("image.compare", {imageA:".../level_plan_r0c2.png", imageB:".../capture_r0c2.png",
georeferenceA:{...}, georeferenceB:{...}, amplify:4})
→ {ok:true, sideBySide:".../plan_vs_capture_side_by_side.png",
difference:".../plan_vs_capture_difference.png",
stats:{differingFraction:0.11, meanAbsDifferenceOverall:7.4, bestFitGain:{r:1.002}}}
11% of pixels differ and the best-fit gain is ~1.0, so this is not an exposure difference. Look at the
difference image: the deltas are along the north wall.