LR-PROF-CAMERACOLOR: camera local tone mapping (ProfileGainTableMap) as a per-photo opt-in

Renders a raw's DNG ProfileGainTableMap (Apple ProRAW's local tone mapping)
when the photo's Profile option "Camera local tone mapping" is on
(`profile.camera_local_tone`, off by default: Lightroom Classic renders
ProRAW without it). Built on #427's parser; supersedes the decode-time
applier of the first version of #273.

- raw/gaintable: GainTableMap::gain / evaluator (GainEval) per DNG 1.7.1:
  bilinear between tables with edges replicated, input clamp(weights .
  (R,G,B,min,max))^gamma in linear ProPhoto after the baseline exposure,
  index input x MapPointsN clamped to the last point. Saturating cell
  math; maps whose sizes don't match their gains aren't evaluated.
  SourcePlacement: where a developed source sits in the active area.
- pipeline/local_tone: the gain per output pixel in the scene-linear
  stage, before the white balance, mapped back through the frame (crop,
  user orientation, warp) and the EXIF orientation. lin_needs_cpu routes
  the stage to the CPU when it's on (CPU and GPU match); lin_key includes
  it. SourceInfo::local_tone carries the map from the decoder.
- develop: Profile::camera_local_tone (omitted from JSON when off, so
  existing settings and their hashes are unchanged); Profile row checkbox
  when the source has a map; translations.
- RENDER_CACHE_VERSION 17. Docs: parity row and What's New as an opt-in.

Off renders pixel-identical to main on two iPhone 15 Pro ProRAWs (12 and
48 MP). On adds ~60-75 ms to the scene-linear stage at 1536x2048 on a
2-core VM, the same for both files (cost follows output pixels).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VFqow2P1EtDxt6nRjjQoTA
This commit is contained in:
BuonBredaandClaude Opus 5.5 committed 2026-10-09 11:11:52 +02:00
1 parent c435d143de
commit fa1565d855
19 files changed
+439 -13

No files matched your search

+6 -1
View File
@@ -88,11 +88,16 @@ pub struct Profile {
pub id: String,
/// Creative profile amount 0..200 (%).
pub amount: f64,
/// Render the raw's own local tone mapping (DNG `ProfileGainTableMap`, Apple ProRAW), as the
/// camera does. Off: rendered as Lightroom Classic does, without it. Omitted when off, so
/// settings without it keep their JSON (and hash).
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub camera_local_tone: bool,
}
impl Default for Profile {
fn default() -> Self {
Self { id: "lc.color".into(), amount: 100.0 }
Self { id: "lc.color".into(), amount: 100.0, camera_local_tone: false }
}
}