Feat: Add optional three-channel sensor bloom model
Add an opt-in, post-processing limited-response model applied to the finished linear HDR before tone mapping. Each RGB channel is processed independently and isotropically: overflow above E spreads to the eight neighbours with a fixed 9-point stencil, while the rest is absorbed or lost at the image boundary. The synchronous ping-pong update uses a monotonic bounding box and a row-parallel, deterministic reduction; the conservative round bound reserves fp guard rounds inside a 4096 hard limit and fails before touching HDR when exceeded. Expose --sensor-bloom-limit E and --sensor-bloom-transfer e (both required together, default disabled), validate them before expensive initialization, and route every output path through the same hook in write_frame_outputs: raw FITS first, bloom, tone-mapped PNG/PPM, then the mesh overlay. The raw --hdr-output FITS therefore stays pre-bloom. Add a standalone unit test (stencil, boundary loss, cascade reference, symmetry, thread determinism, convergence limits, validation, allocation failure), CLI integration and regression coverage, an isolated sensor-bloom-bench target, and document the model in the design, usage, README, and build docs.
This commit is contained in:
1 parent
85fce1bdeb
commit
9cd933d1f8
12 files changed
+1280
-7
No files matched your search
@@ -307,6 +307,33 @@ Commands written before this change that omit `--tone-map` actually used
|
||||
Reinhard; add `--tone-map reinhard` explicitly to reproduce their PNG/PPM
|
||||
output. Historical FITS/HDR benchmarks are unaffected.
|
||||
|
||||
### Sensor bloom (optional)
|
||||
|
||||
`--sensor-bloom-limit E --sensor-bloom-transfer e` (both required together,
|
||||
default disabled) enable an optional post-PSF sensor saturation model applied to
|
||||
the finished linear HDR framebuffer before the display operator. Each RGB
|
||||
channel is processed independently and isotropically. A channel value above the
|
||||
finite response limit \(E\) contributes overflow \(D=\max(H-E,0)\). A fraction
|
||||
\(e\in[0,1)\) of that overflow is spread to the eight neighbours with a fixed
|
||||
9-point stencil (four axial weights \(4/20\), four diagonal weights \(1/20\)),
|
||||
while the remaining \((1-e)D\) is absorbed. Overflow directed outside the image
|
||||
is lost at the boundary and the stencil is not renormalized there. `e=0` clamps
|
||||
every over-limit channel to \(E\) without spreading to neighbours.
|
||||
|
||||
\(E\) is expressed in the post-exposure linear HDR renderer scale, so it scales
|
||||
with `--exposure`. The model is a phenomenological limited-response
|
||||
approximation, not a specific CCD/CMOS/Bayer structure. It is non-conservative:
|
||||
signal is lost both to the drain \((1-e)D\) and to the image boundary, and \(e\)
|
||||
controls both the per-round retained fraction and the effective propagation
|
||||
distance. The mesh overlay is drawn after the model, so the diagnostic lines
|
||||
neither bloom nor feed back into overflow propagation. Visual multi-scale bloom
|
||||
is not implemented.
|
||||
|
||||
When enabled, each frame prints one `Sensor bloom:` line with the initial
|
||||
saturated and final clamped channel counts, the actual and conservative round
|
||||
counts, the peak and maximum initial overflow, absorbed and boundary loss,
|
||||
residual clamp loss, and elapsed time.
|
||||
|
||||
### Fast preview mode
|
||||
|
||||
`--fast-mode` replaces the per-event PSF splat with a two-stage approximation:
|
||||
@@ -413,7 +440,8 @@ ordinary output, replacing its extension with `_HDR.fits`; for example,
|
||||
framebuffer as a three-plane, 32-bit float FITS image. Values remain linear HDR
|
||||
at the renderer's arbitrary scale; no tone mapping or per-frame normalization
|
||||
is applied, and the `--tone-map` operator and `--tone-map-p` value never affect
|
||||
this file. The ordinary
|
||||
this file. The `--sensor-bloom-*` model runs only after this file is written, so
|
||||
enabling bloom never changes the stored FITS. The ordinary
|
||||
binaries do not contain this option or writer.
|
||||
|
||||
The FITS header describes a synthetic 8640-by-5760, 36-by-24 mm full-frame
|
||||
|
||||
Reference in new issue
Block a user