# Scalar depth-map export evidence

An original, dependency-free Python utility and reproducible numerical experiment
for a relative-depth-to-controlled-2.5D-parallax handoff. This package does **not**
run Depth Anything V2, contain its code or weights, execute a game engine, estimate
metric distance, or measure rendered image quality. All included input grids are
synthetic numbers generated by `reproduce.py`.

## Requirements and quick start

Python 3.10 or newer, standard library only. The recorded run used Python 3.12.14.
Run commands from this package's directory. `-B` avoids bytecode caches.

```sh
python3 --version
python3 -B test_depth_normalize.py
python3 -B reproduce.py --out-dir reproduced
python3 -B depth_normalize.py observed/fixtures/ramp-1024.json --out-dir my-ramp --near-is high
python3 -B depth_normalize.py observed/fixtures/outlier-101.json --out-dir my-clipped --near-is high --mode percentile --low-percentile 0 --high-percentile 99
python3 -B depth_normalize.py observed/fixtures/polarity-5.json --out-dir my-reversed --near-is low
```

Each output directory must be **new**, and its parent must already exist. There
is no overwrite or recursive-directory-creation option. A successful export
writes `depth-8.png`, `depth-16.png`, and `manifest.json`. Existing files,
directories, and destination symlinks are refused. Input and normalization
validation finish before output creation. An I/O failure during writing can leave
a partial, newly created output directory; inspect it and choose a new destination
for a retry. This utility is not a sandbox against concurrent hostile filesystem
changes. It has no network operations.

The checked-in `observed/` directory already exists, so choose `reproduced` or
another fresh name to repeat the demonstration. For a real external depth array,
first export its numbers as the JSON format below; this package supplies no
checkpoint loader, tensor converter, or model adapter.

## Accepted input and limits

UTF-8 JSON containing a nonempty rectangular array of nonempty rows, for example:

```json
[[0.0, 0.25, 0.5], [0.75, 0.9, 1.0]]
```

- At most 16,777,216 input bytes, 4,096 columns, 4,096 rows, and 1,048,576 cells
- Values must be JSON numbers representable as finite Python binary64 floats
- Booleans, strings, nulls, missing/ragged rows, NaN, Infinity, and overflow such
  as `1e309` are rejected
- Input integers are converted to binary64 too; precision beyond that format is
  not preserved. For example, `2**53` and `2**53+1` can collapse to one value
- Constant grids, including constants produced by binary64 conversion, are
  rejected. A percentile interval with identical selected values is also rejected
- Input must be a regular file. A file-size bound is not a peak-memory guarantee;
  JSON parsing, sorting, PNG assembly, and encoding allocate additional memory

## Exact numerical convention

For min-max mode, `L=min(input)` and `H=max(input)`. For percentile mode, sort all
N values ascending; for percentile q use `h=(N-1)*(q/100)`, `i=floor(h)`, and
`f=h-i`, then interpolate between sorted indices i and min(i+1,N-1). This is
linear order-statistic interpolation with zero-based indices. Both percentile
arguments are required and must satisfy `0 <= low < high <= 100`.

Values at or below L map to t=0; values at or above H map to t=1. Otherwise,
`t=(value-L)/(H-L)`. The implementation uses an algebraically equivalent scaled
calculation if the unscaled span overflows binary64. Percentile interpolation
also avoids opposite-sign subtraction overflow. All arithmetic is binary64,
not arbitrary-precision or exact rational arithmetic.

The required `--near-is high` option leaves t as-is. `--near-is low` uses `1-t`.
**Both outputs use zero for far and the maximum code for near.** The caller must
choose polarity from the source data's documented convention or a known
near/far check. The utility cannot infer it from appearance or the grid.

For bit depth b, quantization is `floor(t*(2**b-1)+0.5)` after clamping to [0,1].
This is round-half-up, not Python's built-in ties-to-even `round`. Polarity is
applied before quantization; reversing already quantized codes can differ by one
code at exact halfway cases (0.5 maps to 128 in either orientation at 8 bits).

Manifest clipping counts mean strictly below L or strictly above H. Samples
exactly on a threshold are not counted as clipped, even though endpoint values
share the same output code as saturated tails.

## PNG and manifest contract

Both PNGs are grayscale color type 0, noninterlaced, row filter 0. The 16-bit
samples use PNG-required network byte order (big-endian). They contain only IHDR,
IDAT, and IEND chunks, with no gamma, color profile, timestamp, or other ancillary
metadata. Stored DEFLATE blocks make encoding deterministic without depending on
a compressor's heuristics. Identical validated data and options produce identical
PNG bytes in the tested runtime. The JSON manifest records bounds, polarity,
strict clipping counts, dimensions, code ranges, unique code counts, and SHA-256
hashes of the exact source file bytes and each PNG. Whitespace changes in a source
JSON file change its input hash even when its grid values are unchanged.

These are **numeric texture exports**. A visual preview does not establish
preserved 16-bit precision or the correct engine import settings. The decoder in
the tests verifies PNG samples directly, including CRCs, bit depth, scanline
filters, and 16-bit byte order. No engine import or rendering has been tested.

## What the evidence supports

See `RESULTS.md` and `observed/observations.json` for measured counts. The ramp
demonstrates quantization capacity; the outlier demonstrates the selected
normalization tradeoff; the five-point fixture demonstrates polarity. None shows
that a model became more accurate, that 16 bits add scene detail, or that clipped
tails are semantically disposable. The outlier's value 10000 is a constructed
number, not a detected erroneous pixel. Percentile clipping deliberately makes
it indistinguishable from the high threshold.

Per-grid normalization can change scale and endpoint locations between frames.
Temporal stabilization, metric calibration, masks, occlusion/disocclusion,
inpainting, camera amplitude, texture filtering, and game-engine integration are
outside this experiment. No performance, memory, platform, or visual-quality
benchmark is claimed.

## Rebuilding the downloadable archive

`build_archive.py` uses an explicit allowlist of source, documentation, recorded
results, fixtures, and numeric exports. The archive includes `build_archive.py`,
but never includes the output ZIP itself. It refuses an existing archive.
ZIP entry dates/permissions are fixed, and extra fields/comments are empty.
The archive contains no caches, VCS data, hidden metadata, unrelated output
directories, or concept illustration. The adjacent concept illustration, if
present on the article site, is separate from this numerical evidence.

```sh
python3 -B build_archive.py
```

The script also writes `SHA256SUMS` for the exact allowlisted files (excluding
that checksum file itself and the output ZIP). On a fresh extraction, the ZIP
does not exist, so this command can run directly. Tests and recorded result logs
are not regenerated by the builder. The ZIP is reproducible from the same file
bytes; different Python versions or test timings can change recorded text files.

## License and provenance

All package code, documentation, fixtures, and numeric exports are original to
this example and released under the included MIT license. See `PROVENANCE.md`.
No third-party model code, model weights, inference outputs, or images are
included in the archive. The independent project name Depth Anything V2 appears
only as the article's integration context; this package is not affiliated with
or endorsed by its authors.
