From 65c1f1a46871db456d3265562e75a15c5e18f3f9 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Fri, 2 Oct 2026 22:37:41 -0400 Subject: [PATCH] Let the develop example render the profile off, the look doubled, or a preset Diagnostic only. "matrix" switches the camera profile off and "look200" doubles its look, so a DNG's tables can be judged against the matrix render; "preset:" applies a shipped preset as the menu does. The example now renders through render_detailed, the path every frontend takes, because a preset with clarity in it composes a detail stage that plain render refuses. --- core/dr-gpu/examples/develop.rs | 42 ++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/core/dr-gpu/examples/develop.rs b/core/dr-gpu/examples/develop.rs index cb38e9d..1721ac5 100644 --- a/core/dr-gpu/examples/develop.rs +++ b/core/dr-gpu/examples/develop.rs @@ -24,7 +24,7 @@ fn main() { let mut args = std::env::args().skip(1); let Some(input) = args.next() else { eprintln!("usage: develop [out.ppm] [preset]"); - eprintln!(" preset: neutral (default) | punchy | recover"); + eprintln!(" preset: neutral (default) | matrix | look200 | punchy | recover | …"); std::process::exit(2); }; let output = args.next().unwrap_or_else(|| "develop.ppm".into()); @@ -78,6 +78,24 @@ fn main() { graph.set_param(brilliance::ID, brilliance::BRILLIANCE, 40.0); graph.set_param(white_balance::ID, white_balance::TEMPERATURE, 15.0); } + // The camera profile switched off: the matrix alone, as every + // photograph rendered before D20. Beside "neutral" on a DNG that + // embeds a profile, the difference is the profile's tables. + "matrix" => { + graph.set_param( + dr_pipeline::ops::camera_profile::ID, + dr_pipeline::ops::camera_profile::APPLY, + 0.0, + ); + } + // The profile's look table at twice its strength. + "look200" => { + graph.set_param( + dr_pipeline::ops::camera_profile::ID, + dr_pipeline::ops::camera_profile::LOOK, + 200.0, + ); + } // Contrast alone, so its effect can be judged without anything else // moving. "contrast" => { @@ -109,6 +127,14 @@ fn main() { graph.set_param(curve::ID, curve::P0_Y, 0.12); graph.set_param(curve::ID, curve::P1_Y, 0.32); } + // A shipped preset by name — `preset:Vivid landscape` — applied as + // the presets menu applies it, so a look can be judged on a real file. + named if named.starts_with("preset:") => { + let name = &named["preset:".len()..]; + let preset = dr_pipeline::bundled::lookup(&Default::default(), name) + .unwrap_or_else(|| panic!("no shipped preset called {name:?}")); + let _ = preset.apply(&mut graph, dr_pipeline::Scope::adjustments()); + } _ => {} } @@ -123,8 +149,15 @@ fn main() { let mut adjust = AdjustPass::new(&ctx); let (w, h) = image.size(); + // Through the detail stage when the edit has one — clarity, sharpening + // — which is the path every frontend takes; `render` alone refuses such + // a shader. let t2 = std::time::Instant::now(); - adjust.render(&image, &shader, w, h).expect("adjust"); + let detail = graph.compose_detail(image.size(), (w, h)); + let key = graph.invalidation().through(dr_pipeline::Affects::Colour); + adjust + .render_detailed(&image, &shader, w, h, None, &detail, key) + .expect("adjust"); ctx.device .poll(wgpu::PollType::wait_indefinitely()) .expect("poll"); @@ -134,8 +167,11 @@ fn main() { // path, and it must not recompile. graph.set_param(exposure::ID, exposure::EXPOSURE, 0.31); let again = graph.compose(); + let key = graph.invalidation().through(dr_pipeline::Affects::Colour); let t3 = std::time::Instant::now(); - adjust.render(&image, &again, w, h).expect("adjust"); + adjust + .render_detailed(&image, &again, w, h, None, &detail, key) + .expect("adjust"); ctx.device .poll(wgpu::PollType::wait_indefinitely()) .expect("poll");