LR-EXP-HDR: HDR export (gain map JPEG, float TIFF) and develop.hdr

- `ExportOptions.hdr` (`hdr` param): photos edited in HDR export as ISO
  21496-1 gain map JPEGs (the SDR rendition as the base, the gain map measured
  against it as written) or 32-bit float TIFF with highlights above 1.
  Other formats and SDR edits export as before.
- Output sharpening and watermarks apply to both renditions.
- `develop.hdr {enabled?, maxEv?}` turns HDR editing on/off and sets the
  headroom limit.

Checked on macOS: ImageIO reports both the ISO and the Apple gain map, and
CoreImage's HDR decode of a 3 EV edit reaches 2.95 EV.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
akvaithi
2026-10-09 22:40:37 -05:00
co-authored by Claude Opus 5.5
parent e11db8fea0
commit 34d9c8f2d2
5 changed files with 163 additions and 17 deletions
+27
View File
@@ -572,6 +572,33 @@ pub fn specs() -> Vec<CommandSpec> {
Ok(())
})
}),
// ---- HDR editing
cmd!(
"develop.hdr",
"HDR",
[],
None,
"{enabled?: bool (default: toggle), maxEv?: number 0..5 (headroom limit, stops above SDR white)} — HDR editing: highlights above SDR white for HDR exports and displays; every SDR render uses the SDR rendition (the hdr.sdr* controls)",
has_active,
|s, p| {
let id = active(s, "develop.hdr")?;
let cur = s.develop_of(id).unwrap_or_default().hdr;
let enabled = bool_or(p, "enabled", !cur.enabled);
let max_ev = match p.get("maxEv") {
None => None,
Some(v) => Some(v.as_f64().filter(|x| x.is_finite()).ok_or_else(|| bad("develop.hdr", "`maxEv` must be a number"))?),
};
let label = if enabled { "HDR On" } else { "HDR Off" };
edit(s, "develop.hdr", label, |d| {
d.hdr.enabled = enabled;
if let Some(m) = max_ev {
d.hdr.max_ev = m.clamp(0.0, lightcraft_develop::Hdr::MAX_EV_LIMIT);
}
Ok(())
})?;
Ok(json!({"enabled": enabled, "maxEv": s.develop_of(id).map(|d| d.hdr.max_ev)}))
}
),
// ---- geometry: Upright
cmd!(
"geometry.upright",