Array: read out the depth buffer; show it in the readout §05

igc_array.py gains readout_depth() -> the 24-bit Z stored in pixel memory as a
depth image (near=bright), i.e. the plane the decoded SENDE z-sweep interpolates.
Readout §05 now shows the depth buffer next to the tile footprint, ties the
z-decode to a visible array output, and reframes the "remaining work" as numeric
reconstruction across regions (the coefficients are already cross-validated).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-16 16:07:01 -05:00
co-authored by Claude Opus 4.8
parent 943d6e1090
commit b78b14b7f9
2 changed files with 119 additions and 24 deletions
+38
View File
@@ -161,6 +161,44 @@ class IGCArray:
_wword(pix, G_BIT0, C_BITS, gv)
_wword(pix, B_BIT0, C_BITS, bv)
def readout_depth(self, bg=(7, 11, 17)):
"""Read the 24-bit z stored in pixel memory back into a depth image (near=bright).
This is the plane the SENDE z-sweep interpolates, straight out of pixel memory."""
img = bytearray(self.W * self.H * 3)
for y in range(self.H):
o = y * self.W * 3
for x in range(self.W):
img[o] = bg[0]; img[o + 1] = bg[1]; img[o + 2] = bg[2]; o += 3
# gather the touched z range for contrast
zmin, zmax = Z_FAR, 0
for t in self.tiles.values():
if not t.touched:
continue
for pix in t.mem:
z = _rword(pix, Z_BIT0, Z_BITS)
if z != Z_FAR:
zmin = min(zmin, z); zmax = max(zmax, z)
span = (zmax - zmin) or 1
for (tx, ty), t in self.tiles.items():
if not t.touched:
continue
for ly in range(TILE_Y):
gy = t.y0 + ly
if gy >= self.H:
break
base = ly << TILE_X_BITS
for lx in range(TILE_X):
gx = t.x0 + lx
if gx >= self.W:
break
z = _rword(t.mem[base + lx], Z_BIT0, Z_BITS)
if z == Z_FAR:
continue
v = 1.0 - (z - zmin) / span # near = bright
o = (gy * self.W + gx) * 3
img[o] = int(30 + v * 120); img[o + 1] = int(90 + v * 150); img[o + 2] = int(120 + v * 130)
return img
def readout(self, bg=(7, 11, 17)):
"""Read pixel memory back out into an RGB framebuffer (row-major, RGB bytes)."""
img = bytearray(self.W * self.H * 3)