Feat: Add soft-clip tone mapping with legacy Reinhard
Replace the per-channel Reinhard display transform with a parameterized soft clip T_p(x) = tanh(x^p)^(1/p), default softclip p=2, exposed through --tone-map and --tone-map-p. Keep --tone-map reinhard bit-compatible with the previous x/(1+x) curve for existing images and reject combining it with an explicit --tone-map-p. Route the primary image and the mesh overlay through the same ToneMapSettings; the linear HDR FITS writer stays pre-tone-map. Add a focused optics-linked tone-map test target, CLI success/error coverage, and document the display operator versus the Moffat effective PSF.
This commit is contained in:
1 parent
7399eb6904
commit
e31e1ed27e
10 files changed
+359
-30
No files matched your search
@@ -267,6 +267,46 @@ at the existing cache radius. Images above `F` retain the direct fallback.
|
||||
`--max-magnification M` (default unlimited) caps the per-triangle rendering
|
||||
magnification before flux is formed; it is an explicit preview approximation.
|
||||
|
||||
### Tone mapping and display
|
||||
|
||||
`--exposure` is a linear multiplier applied while the HDR framebuffer and its
|
||||
PSF splats are accumulated. The Moffat profile is the empirical effective
|
||||
optical PSF, absorbing seeing, jitter, and residual aberrations; it is not
|
||||
changed by any display choice.
|
||||
|
||||
The tone map is a later camera/display response applied to the finished linear
|
||||
HDR image, so it does not alter the linear HDR PSF. The default operator is a
|
||||
parameterized, per-channel soft clip
|
||||
|
||||
\[
|
||||
T_p(x) = \left[\tanh(x^p)\right]^{1/p}, \qquad p \ge 1,
|
||||
\]
|
||||
|
||||
selected with `--tone-map softclip --tone-map-p 2`, i.e.
|
||||
|
||||
\[
|
||||
T_2(x) = \sqrt{\tanh(x^2)}.
|
||||
\]
|
||||
|
||||
It is close to the identity in the dark, then rolls smoothly into a saturated
|
||||
shoulder above \(x \sim 1\). Because it is applied independently to each linear
|
||||
RGB channel, a bright star transitions from its colored Moffat wings into a
|
||||
white saturated core. Larger `p` approaches \(\min(x,1)\). This per-channel
|
||||
response is what gives the current simplified preview pipeline the crisp white
|
||||
cores seen in real astrophotography, rather than the gray, soft cores a
|
||||
Reinhard curve leaves on bright stars.
|
||||
|
||||
`--tone-map reinhard` selects the historical \(x/(1+x)\) display transform and
|
||||
is retained only to reproduce output rendered before the soft-clip operator was
|
||||
introduced. FITS output always remains the pre-tone-map linear RGB framebuffer,
|
||||
independent of operator and `p`; use it to measure physical flux, peak values,
|
||||
and FWHM. Tone-mapped PNG/PPM data are display-referred and must not be used for
|
||||
those measurements.
|
||||
|
||||
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.
|
||||
|
||||
### Fast preview mode
|
||||
|
||||
`--fast-mode` replaces the per-event PSF splat with a two-stage approximation:
|
||||
@@ -372,7 +412,8 @@ ordinary output, replacing its extension with `_HDR.fits`; for example,
|
||||
`output/imgs/ring_HDR.fits`. It writes the pre-tone-mapping RGB
|
||||
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. The ordinary
|
||||
is applied, and the `--tone-map` operator and `--tone-map-p` value never affect
|
||||
this file. 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