"""Gradio application for single-image height estimation.
The demo is a thin wrapper around two things that already exist in this repo and
are shared with the offline CLI, so the Space cannot drift from the numbers the
CLI reports:
* `infer/` + `dwdata/` — the model and the exact preprocessing contract stored
in the checkpoint.
* `viz/` and `viewer/` — the visualisation layer: the figure primitives
(`viz.figures`), the mesh writers (`viz.mesh`), and the standalone dual-pane
DSM inspector (`viewer/index.html` + `viewer/app.js`), which is inlined into
an iframe here and works identically opened straight off disk.
The viewer is *not* re-implemented for the Space. `viewer/index.html` is read at
import time and its `',
f'\n'
'',
)
def inline(match: "re.Match[str]") -> str:
src = match.group(1)
js = (_VIEWER_ROOT / src).read_text(encoding="utf-8")
# a literal \n" + js.replace(""
document, n = re.subn(r'', inline, document)
if n < 4: # three.js, OrbitControls, PointerLockControls, app.js
raise RuntimeError(f"viewer/index.html: inlined only {n} of 4 scripts")
if _PAYLOAD_SLOT not in document:
raise RuntimeError("viewer/index.html: no slot for the prediction payload")
return document
_VIEWER_SHELL = _build_viewer_shell()
def _png_data_url(image: Image.Image) -> str:
buffer = io.BytesIO()
image.save(buffer, format="PNG", optimize=True)
encoded = base64.b64encode(buffer.getvalue()).decode("ascii")
return f"data:image/png;base64,{encoded}"
def _viewer(payload: dict) -> str:
# `<` never appears outside a JSON string, so escaping it is enough to make
# the blob inert inside the