mirror of
https://github.com/storytold/lightcraft.git
synced 2026-11-13 09:20:07 -06:00
* LR-BEHAV-RENDER-FIDELITY: V3 camera tone curve rolls off in stops past its last knot (#1632) A raw's camera tone curve is fitted only to camera JPEG tones below 0.85, so its last knot sits 1 to 3 stops below the sensor's white. Past it, CameraTone::apply closes on white exponentially in linear light: the sensor's white renders at 8-bit 246-254 at Exposure 0 and 254-255 from +1, and raising Exposure turns the top stop the sensor recorded white. Process V3 extends the curve with CameraTone::apply_rolloff: same value and slope at the knot, then gap / (1 + c (2^t - 1)) at t stops past it, the gap halving every stop in the end. On 11 CC0 corpus files with a fitted look, unclipped pixels rendering white drop from up to 22.5% to 0 at +1 EV and from up to 35% to 0 at +2 EV; Exposure 0 renders change by at most 1 code on average. V1 and V2, the fit itself, JPEGs and raws without a fitted look are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * LR-BEHAV-RENDER-FIDELITY: V3 generic raw curve rolls off in stops too; DRO-off, DNG and GPU checks (#1632) Raws without a camera curve take ToneMap::hdr, which reached white about 1/4 stop past the sensor's white and clipped there (o.min(1.0)). Process V3 now uses ToneMap::rolloff_hdr: from half a stop below the white point (tone::GENERIC_KNEE_STOPS) the extended Reinhard curve hands over to the same stop-based shoulder as the camera curve (tone::rolloff_past, shared with CameraTone::apply_rolloff), with the same value and slope at the join. The sensor's white renders at about 235 / 248 / 252 at Exposure 0 / +1 / +2 where V1 and V2 render 239 / 255 / 255. On 6 CC0 DNGs on the generic curve, unclipped pixels rendering white drop from up to 8.4% to 0 at +1 EV and from up to 17.2% to 0 at +2 EV. The DRO-off gate (look_fit::at_most) also checks the V3 shoulder; the rate bound already implies it, so no fit changes and LOOK_VERSION stays. Tests: the generic shoulder (join, slope, monotone, below white, no kink), a regression test that fails with the clipping curve, a DNG ProfileToneCurve under V3, the DRO-off property tests on the V3 shoulder, and a per-process camera-curve GPU check. Docs: process-versions, parity checklist (LR-BEHAV-RENDER-FIDELITY, LRC-DEV-PROCESS), gap 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * LR-BEHAV-RENDER-FIDELITY: what's new: process 3 keeps raw highlights when Exposure is raised (#1632) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * LR-BEHAV-RENDER-FIDELITY: a flat last camera-curve segment joins the V3 shoulder with its own slope (#1632) The V3 camera shoulder took the last segment's slope with a floor of 0.1, so a flat or shallow segment (valid for a fitted, DNG or saved curve) joined with a kink: slope 0 on the curve, about 0.1 just past it. The shoulder now keeps the segment's own slope at the knot. Below 0.1 a quadratic term in 2^t - 1 joins the denominator: it adds no slope at the knot and makes up the 0.1 pace further up, so a flat curve still closes on white. Segments at 0.1 or steeper are byte-identical, and the generic curve passes no floor. Comments now say the shoulder approaches white in real numbers and can round to it in f32. Found in an independent review of the branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * LR-BEHAV-RENDER-FIDELITY: V4's GPU test pins V4; the corpus DRO photos keep their knots under the V5 bound (#1632) The GPU light-operator test assumed the default process is V4; it now sets V4, since V5 is the default. The corpus DRO test checks that dro_off's V5 bound leaves the second-last knot where the rate bound puts it on the Sony DRO samples, so their V1 to V4 renders don't change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * LR-BEHAV-RENDER-FIDELITY: the DRO-off curve is main's again, so V1 to V4 keep it (#1632) CodeRabbit found that the V5 bound in `dro_off` could move the second-last knot of a DRO photo whose fitted last segment is flat, and V1 to V4 read that curve too. `dro_off` and `at_most` are back to main's, so the camera-look fit is unchanged and LOOK_VERSION stays. The DRO tests check the V5 shoulder where the lowered segment's slope over its squared gap is at most the fitted one's (then it stays below), and on the Sony DRO corpus samples. Also: `rolloff_hdr`'s doc names the HDR lift, and the release note names DNGs whose curve already reaches white. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>