EXR export: no compand / tone mapping, and the output space's own curve

OpenEXR renders (Render Queue sequences and Save Frame As ProEXR) received
the frame after Project Settings > HDR, so Compand and Tone Map (the default
of every OCIO project) compressed highlights and changed values below 1.0
before the writer decoded them, always with the sRGB curve.

- RenderOpts::scene_output: the top-level comp converts to the output space
  without the HDR step (CPU and GPU walks, via Renderer::output_pipe).
- Pipe::output_linear: the writers decode with the output space's curve
  (the Working Gamma's when unmanaged) instead of a fixed sRGB curve.
- Render Queue EXR jobs and ProEXR set the flag; PSD layers, 8-bit stills,
  movies and the viewer keep the HDR step. The flag is part of the viewer
  frame and disk cache keys (opts_hash).

Golden hashes, taken before the change, pin PNG/TIFF/Targa bytes for
8/16/32 bpc x Clip/Compand/ToneMap, Clip-mode EXR samples with an sRGB
output, and the layered PSD bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
vangel76
2026-11-03 01:47:24 +01:00
co-authored by Claude Opus 5.5
parent a646bdcc2e
commit 684e05859f
16 changed files with 548 additions and 23 deletions
+8
View File
@@ -6,6 +6,14 @@ fn converting_a_frame_with_nan_alpha_keeps_the_viewer_alive() {
assert_eq!(to_color_image(&image).pixels, [egui::Color32::TRANSPARENT]);
}
/// A float output's frames (`RenderOpts::scene_output`, no HDR step) never share a RAM or disk
/// cache key with the HDR-mapped frames of the same options.
#[test]
fn scene_output_frames_have_keys_of_their_own() {
let opts = RenderOpts::default();
assert_ne!(opts_hash(&opts), opts_hash(&RenderOpts { scene_output: true, ..opts }));
}
struct ProbeDisk {
keys: Mutex<HashSet<u128>>,
probes: std::sync::atomic::AtomicUsize,