diff --git a/core/dr-gpu/src/adjust.rs b/core/dr-gpu/src/adjust.rs index 228506a..1408639 100644 --- a/core/dr-gpu/src/adjust.rs +++ b/core/dr-gpu/src/adjust.rs @@ -3420,8 +3420,10 @@ mod tests { read_centre(&ctx, t) }; + // The default rendering of a raw is Camera Raw's tone (D21): a grey + // goes through the ACR3 curve unchanged in hue. let scene = 3537.0 / 16383.0; - let viewed = dr_pipeline::view::Sigmoid::default_curve().channel(scene); + let viewed = dr_types::tone::evaluate(&dr_types::tone::ACR3_DEFAULT, scene); let expected = (dr_types::Transfer::Srgb.encode(viewed) * 255.0).round() as i32; let delta = (i32::from(from_sensor[0]) - expected).abs(); assert!( diff --git a/core/dr-gpu/src/demosaic.rs b/core/dr-gpu/src/demosaic.rs index 09f3e6b..c9c9f5c 100644 --- a/core/dr-gpu/src/demosaic.rs +++ b/core/dr-gpu/src/demosaic.rs @@ -578,7 +578,7 @@ impl DemosaicedImage { view, width, height, - color_matrix: raw.color_matrix.unwrap_or(IDENTITY_3X3), + color_matrix: rendering_matrix(raw), profile_tables: raw.profile_tables.clone(), as_shot_wb: [raw.wb_coeffs[0], raw.wb_coeffs[1], raw.wb_coeffs[2]], non_linear: false, @@ -589,6 +589,23 @@ impl DemosaicedImage { } } +/// TRACES: FR-DEV-3e +/// The camera matrix a raw renders through: the file's — identity where the +/// body is uncalibrated, so the image renders with no colour transform +/// rather than not at all — times the baseline exposure as a gain +/// (camera-profiles.md §11). +/// +/// A uniform gain commutes with every scene operation before the view +/// transform, so folding it in here is the same as an exposure step at the +/// head of the chain, at no cost. The camera-space tap and the white-balance +/// probe read camera RGB before this matrix and are unaffected. +/// `RawImage::color_matrix` stays the file's: a merge writes a linear DNG +/// from it and must not bake a gain into its pixels. +fn rendering_matrix(raw: &RawImage) -> [f32; 9] { + let gain = raw.baseline_exposure.exp2(); + raw.color_matrix.unwrap_or(IDENTITY_3X3).map(|v| v * gain) +} + /// Convert an f32 to half-precision bits, the general case: sign, /// subnormals, round-to-nearest-even, saturation at the largest finite. /// @@ -937,7 +954,7 @@ impl Demosaicer { height, // Identity where the body is uncalibrated: the image renders with // no colour transform rather than not at all. - color_matrix: raw.color_matrix.unwrap_or(IDENTITY_3X3), + color_matrix: rendering_matrix(raw), profile_tables: raw.profile_tables.clone(), as_shot_wb: [raw.wb_coeffs[0], raw.wb_coeffs[1], raw.wb_coeffs[2]], // Whatever the profile database had for this body (FR-DEV-3e), diff --git a/core/dr-gpu/tests/camera_profile.rs b/core/dr-gpu/tests/camera_profile.rs index 3404be3..cfc92fe 100644 --- a/core/dr-gpu/tests/camera_profile.rs +++ b/core/dr-gpu/tests/camera_profile.rs @@ -192,6 +192,41 @@ fn the_shader_agrees_with_the_cpu_reference() { assert_agrees(&got, |c| apply_reference(&tables, c, 2.0), "look at 200%"); } +#[test] +fn camera_raw_tone_agrees_with_its_cpu_reference() { + // TRACES: FR-DEV-3j + // D21's rendering on 256 colours: the ProPhoto round trip, the clip, the + // curve from the profile buffer's placeholder, and RGBTone's placement + // of the middle channel, against `camera_raw::apply_reference`. + let Some(ctx) = ctx() else { + eprintln!("skipping: no GPU adapter"); + return; + }; + let source = Demosaicer::new(&ctx) + .expect("demosaicer") + .run(&frame(None)) + .expect("upload"); + let ops: Vec> = vec![Box::new(dr_pipeline::ops::ViewTransform::new())]; + let shader = dr_pipeline::compose(&ops); + let mut adjust = AdjustPass::new(&ctx); + adjust.render(&source, &shader, SIZE, SIZE).expect("render"); + let (pixels, _, _) = adjust.export_pixels().expect("readback"); + let got: Vec<[u8; 3]> = pixels.chunks_exact(4).map(|p| [p[0], p[1], p[2]]).collect(); + let curve = &dr_types::tone::ACR3_DEFAULT; + assert_agrees( + &got, + |c| { + dr_pipeline::camera_raw::apply_reference( + curve, + c, + dr_pipeline::view::DEFAULT_CONTRAST, + dr_pipeline::view::DEFAULT_WHITE, + ) + }, + "Camera Raw tone", + ); +} + #[test] fn switched_off_or_absent_the_render_is_unchanged() { let Some(ctx) = ctx() else { diff --git a/core/dr-gpu/tests/view_transform.rs b/core/dr-gpu/tests/view_transform.rs index 9d4575a..e653e6a 100644 --- a/core/dr-gpu/tests/view_transform.rs +++ b/core/dr-gpu/tests/view_transform.rs @@ -46,6 +46,40 @@ fn flat_raw(level: u16) -> RawImage { } } +/// The default chain with D19's sigmoid chosen: Camera Raw's tone is the +/// default since D21, and these tests are about the sigmoid. +fn sigmoid_chain() -> EditGraph { + let mut g = EditGraph::default_chain(); + g.set_param( + dr_pipeline::ops::view_transform::ID, + dr_pipeline::ops::view_transform::CURVE, + dr_pipeline::ops::view_transform::SIGMOID, + ); + g +} + +#[test] +fn camera_raw_tone_is_the_default_and_agrees_with_the_acr3_curve() { + // TRACES: FR-DEV-3j + // D21: a raw with no profile renders a grey through Camera Raw's default + // curve, which the profile buffer's placeholder carries. + let Some(ctx) = ctx() else { + eprintln!("skipping: no GPU adapter"); + return; + }; + let graph = EditGraph::default_chain(); + for level in [500u16, 4_000, 8_520, 20_000, 40_000] { + let scene = f32::from(level) / f32::from(u16::MAX); + let display = dr_types::tone::evaluate(&dr_types::tone::ACR3_DEFAULT, scene); + let expected = (dr_types::Transfer::Srgb.encode(display) * 255.0).round() as i32; + let got = i32::from(rendered(&ctx, level, &graph)); + assert!( + (got - expected).abs() <= 2, + "raw {level} rendered as {got}, the ACR3 curve says {expected}" + ); + } +} + /// Render `graph` over a flat frame and return the centre pixel's red. /// /// The centre rather than a corner: a demosaic has to invent its edges. @@ -70,7 +104,7 @@ fn the_shader_agrees_with_the_cpu_reference() { return; }; let curve = Sigmoid::default_curve(); - let graph = EditGraph::default_chain(); + let graph = sigmoid_chain(); for level in [0u16, 500, 4_000, 8_520, 32_768, 60_000, u16::MAX] { let scene = f32::from(level) / f32::from(u16::MAX); let display = curve.channel(scene).min(1.0); @@ -96,7 +130,7 @@ fn highlights_above_one_stay_distinct() { eprintln!("skipping: no GPU adapter"); return; }; - let mut graph = EditGraph::default_chain(); + let mut graph = sigmoid_chain(); graph.set_param( dr_pipeline::ops::exposure::ID, dr_pipeline::ops::exposure::EXPOSURE, diff --git a/core/dr-pipeline/src/camera_raw.rs b/core/dr-pipeline/src/camera_raw.rs new file mode 100644 index 0000000..1d6893d --- /dev/null +++ b/core/dr-pipeline/src/camera_raw.rs @@ -0,0 +1,155 @@ +//! TRACES: FR-DEV-3j | FR-DEV-3e +//! Camera Raw's tone, as a rendering the view transform can choose (D21). +//! +//! Lightroom's colour is mostly its tone curve (camera-profiles.md §1): the +//! profile's `ProfileToneCurve`, or the ACR3 default for a profile with none. +//! Half of what the curve does is *how* it is applied. Camera Raw's +//! `RefBaselineRGBTone` runs it on the largest and the smallest channel, and +//! places the middle channel at the fraction between them it had before. Hue +//! is kept; saturation rises wherever the curve is steeper than the +//! diagonal, which for the ACR3 curve is the shadows and the midtones — +//! where Adobe Standard's look table desaturated to compensate. +//! +//! It runs in linear ProPhoto, as Camera Raw does, on values clipped to +//! `[0, 1]`; its output is linear and goes to the output transform as the +//! sigmoid's does. The curve is read from the profile buffer +//! (`ops::camera_profile::profile_buffer`), which always carries one. +//! +//! [`apply_reference`] is the arithmetic on the CPU; the GPU test holds the +//! shader to it. + +use crate::ops::camera_profile::{mul, working_prophoto}; +use crate::view::{DEFAULT_CONTRAST, DEFAULT_WHITE, SCENE_GREY}; + +/// The input scale for a white point: 1 at the default, so sensor white is +/// display white as in Camera Raw; each stop of `white` above it halves the +/// input. +pub fn input_scale(white: f32) -> f32 { + (DEFAULT_WHITE - white).exp2() +} + +/// The power the input is bent by about middle grey: 1 at the default +/// contrast, so the curve is Camera Raw's untouched. +pub fn contrast_power(contrast: f32) -> f32 { + contrast / DEFAULT_CONTRAST +} + +/// The curve, its scale and its contrast applied to one ProPhoto colour. +fn rgb_tone(curve: &[f32], p: [f32; 3]) -> [f32; 3] { + let p = p.map(|v| v.clamp(0.0, 1.0)); + let hi = p[0].max(p[1]).max(p[2]); + let lo = p[0].min(p[1]).min(p[2]); + let (c_hi, c_lo) = ( + dr_types::tone::evaluate(curve, hi), + dr_types::tone::evaluate(curve, lo), + ); + if hi - lo <= 1e-7 { + return [c_hi; 3]; + } + p.map(|v| c_lo + (c_hi - c_lo) * (v - lo) / (hi - lo)) +} + +/// TRACES: FR-DEV-3j +/// The view transform's Camera Raw rendering of one working-space colour. +pub fn apply_reference(curve: &[f32], c: [f32; 3], contrast: f32, white: f32) -> [f32; 3] { + let (to, back) = working_prophoto(); + let scale = input_scale(white); + let power = contrast_power(contrast); + let mut p = mul(to, c).map(|v| v * scale); + if power != 1.0 { + p = p.map(|v| SCENE_GREY * (v.max(0.0) / SCENE_GREY).powf(power)); + } + mul(back, rgb_tone(curve, p)) +} + +/// The WGSL, a helper the view transform asks for after +/// `ops::camera_profile`'s ProPhoto constants. Mirrors [`apply_reference`]. +pub const CAMERA_RAW_WGSL: &str = " +fn camera_raw_curve(x: f32) -> f32 { + let base = profile_curve_base(); + let n = u32(profile_table[2].x); + let s = clamp(x, 0.0, 1.0) * f32(n - 1u); + let i = min(u32(s), n - 2u); + return mix(profile_table[base + i].x, profile_table[base + i + 1u].x, s - f32(i)); +} + +// Camera Raw's RGBTone: the curve on the largest and smallest channel, the +// middle one kept at its fraction between them, so hue survives. +fn camera_raw_tone(c: vec3, scale: f32, power: f32, grey: f32) -> vec3 { + var p = PROFILE_FROM_WORKING * c * scale; + if (power != 1.0) { + p = grey * pow(max(p, vec3(0.0)) / grey, vec3(power)); + } + p = clamp(p, vec3(0.0), vec3(1.0)); + let hi = max(p.r, max(p.g, p.b)); + let lo = min(p.r, min(p.g, p.b)); + let c_hi = camera_raw_curve(hi); + let c_lo = camera_raw_curve(lo); + var out = vec3(c_hi); + if (hi - lo > 1e-7) { + out = vec3(c_lo) + (c_hi - c_lo) * (p - vec3(lo)) / (hi - lo); + } + return PROFILE_TO_WORKING * out; +} +"; + +#[cfg(test)] +mod tests { + use super::*; + use dr_types::tone::{evaluate, ACR3_DEFAULT}; + + fn identity() -> Vec { + (0..1025).map(|i| i as f32 / 1024.0).collect() + } + + #[test] + fn at_its_defaults_the_input_is_untouched() { + assert_eq!(input_scale(DEFAULT_WHITE), 1.0); + assert_eq!(contrast_power(DEFAULT_CONTRAST), 1.0); + } + + #[test] + fn grey_goes_through_the_curve_and_stays_grey() { + for v in [0.02, 0.13, 0.5] { + let out = apply_reference(&ACR3_DEFAULT, [v; 3], DEFAULT_CONTRAST, DEFAULT_WHITE); + let want = evaluate(&ACR3_DEFAULT, v); + assert!( + out.iter().all(|o| (o - want).abs() < 1e-4), + "{v}: {out:?} vs {want}" + ); + } + } + + #[test] + fn an_identity_curve_changes_nothing_inside_the_range() { + let c = [0.4, 0.2, 0.1]; + let out = apply_reference(&identity(), c, DEFAULT_CONTRAST, DEFAULT_WHITE); + assert!( + out.iter().zip(c).all(|(o, c)| (o - c).abs() < 1e-4), + "{out:?}" + ); + } + + #[test] + fn the_middle_channel_keeps_its_place_between_the_other_two() { + let p = [0.3, 0.12, 0.05]; + let out = rgb_tone(&ACR3_DEFAULT, p); + let before = (p[1] - p[2]) / (p[0] - p[2]); + let after = (out[1] - out[2]) / (out[0] - out[2]); + assert!((before - after).abs() < 1e-5, "{before} {after}"); + } + + #[test] + fn the_acr_curve_raises_saturation_in_the_midtones() { + let p = [0.15, 0.08, 0.05]; + let out = rgb_tone(&ACR3_DEFAULT, p); + let sat = |c: [f32; 3]| (c[0] - c[2]) / c[0]; + assert!(sat(out) > sat(p), "{p:?} -> {out:?}"); + } + + #[test] + fn white_halves_the_input_per_stop() { + assert_eq!(input_scale(DEFAULT_WHITE + 1.0), 0.5); + assert!(contrast_power(2.8) > 1.0); + } +} diff --git a/core/dr-pipeline/src/lib.rs b/core/dr-pipeline/src/lib.rs index 06293ec..b31f0be 100644 --- a/core/dr-pipeline/src/lib.rs +++ b/core/dr-pipeline/src/lib.rs @@ -33,6 +33,7 @@ //! data neither would be physically meaningful (ARCH §5.2). pub mod bundled; +pub mod camera_raw; pub mod coverage; pub mod declared; pub mod descriptor; diff --git a/core/dr-pipeline/src/ops/camera_profile.rs b/core/dr-pipeline/src/ops/camera_profile.rs index d1c8495..a236e71 100644 --- a/core/dr-pipeline/src/ops/camera_profile.rs +++ b/core/dr-pipeline/src/ops/camera_profile.rs @@ -51,10 +51,11 @@ pub const DEFAULT_LOOK: f32 = 100.0; /// Twice the profile's look: Lightroom's *Amount* reaches the same. pub const MAX_LOOK: f32 = 200.0; -/// Entries of the buffer's header: one `vec4` describing each table — -/// `(hue divisions, saturation divisions, value divisions, sRGB-encoded)`, -/// zero hue divisions meaning absent — before the entries themselves. -pub const HEADER_ENTRIES: usize = 2; +/// Entries of the buffer's header, before the entries themselves: one +/// `vec4` describing each table — `(hue divisions, saturation divisions, +/// value divisions, sRGB-encoded)`, zero hue divisions meaning absent — and +/// a third whose `.x` is the tone curve's length (camera-profiles.md §12). +pub const HEADER_ENTRIES: usize = 3; static DESCRIPTOR: LazyLock> = LazyLock::new(|| { Arc::new(OpDescriptor { @@ -80,7 +81,7 @@ static DESCRIPTOR: LazyLock> = LazyLock::new(|| { /// Linear sRGB (the working space) to linear ProPhoto, and back, row-major, /// each row scaled to sum to one so that working white is ProPhoto white /// exactly and a neutral reaches the tables with zero saturation. -fn working_prophoto() -> &'static ([f32; 9], [f32; 9]) { +pub(crate) fn working_prophoto() -> &'static ([f32; 9], [f32; 9]) { static M: LazyLock<([f32; 9], [f32; 9])> = LazyLock::new(|| { let to = normalise_rows(dr_types::ColourSpace::ProPhoto.from_linear_srgb()); let back = normalise_rows(invert(&to).expect("ProPhoto's matrix is invertible")); @@ -117,7 +118,7 @@ fn invert(m: &[f32; 9]) -> Option<[f32; 9]> { Some(inv.map(|v| v as f32)) } -fn mul(m: &[f32; 9], c: [f32; 3]) -> [f32; 3] { +pub(crate) fn mul(m: &[f32; 9], c: [f32; 3]) -> [f32; 3] { std::array::from_fn(|r| m[r * 3] * c[0] + m[r * 3 + 1] * c[1] + m[r * 3 + 2] * c[2]) } @@ -127,19 +128,48 @@ fn wgsl_mat(m: &[f32; 9]) -> String { format!("mat3x3({}, {}, {})", col(0), col(1), col(2)) } -static HELPERS: LazyLock<[Helper; 1]> = LazyLock::new(|| { +/// The working space to ProPhoto and back, as WGSL constants, and where +/// the profile buffer's sections begin. A helper of its own because the +/// view transform's Camera Raw curve needs it too, and helpers are emitted +/// once each, in the order first asked for. +pub(crate) static PROPHOTO_HELPER: LazyLock = LazyLock::new(|| { let (to, back) = working_prophoto(); let source = format!( - "const PROFILE_FROM_WORKING = {};\nconst PROFILE_TO_WORKING = {};\n{LOOKUP_WGSL}", + "const PROFILE_FROM_WORKING = {};\nconst PROFILE_TO_WORKING = {};\n{SECTIONS_WGSL}", wgsl_mat(to), wgsl_mat(back) ); - [Helper { - name: "profile_apply", + Helper { + name: "profile_curve_base", source: Box::leak(source.into_boxed_str()), - }] + } }); +static HELPERS: LazyLock<[Helper; 2]> = LazyLock::new(|| { + [ + *PROPHOTO_HELPER, + Helper { + name: "profile_apply", + source: LOOKUP_WGSL, + }, + ] +}); + +/// Where each section of the profile buffer starts, from its header. +const SECTIONS_WGSL: &str = " +fn profile_entries(dims: vec4) -> u32 { + return u32(dims.x * dims.y * dims.z); +} + +fn profile_look_base() -> u32 { + return 3u + profile_entries(profile_table[0]); +} + +fn profile_curve_base() -> u32 { + return profile_look_base() + profile_entries(profile_table[1]); +} +"; + /// The lookup, in WGSL. Mirrors [`apply_reference`] line for line. const LOOKUP_WGSL: &str = r#" fn profile_srgb_encode(v: f32) -> f32 { @@ -327,12 +357,11 @@ if (hue_sat_dims.x > 0.0 || look_dims.x > 0.0) { // A colour outside ProPhoto has no HSV the tables were made for; it // passes through rather than being floored, which would clip it (D19). if (min(p.r, min(p.g, p.b)) >= 0.0) { - let look_base = 2u + u32(hue_sat_dims.x * hue_sat_dims.y * hue_sat_dims.z); if (hue_sat_dims.x > 0.0) { - p = profile_apply(hue_sat_dims, 2u, p, 1.0); + p = profile_apply(hue_sat_dims, 3u, p, 1.0); } if (look_dims.x > 0.0 && look > 0.0) { - p = profile_apply(look_dims, look_base, p, look); + p = profile_apply(look_dims, profile_look_base(), p, look); } c = PROFILE_TO_WORKING * p; } @@ -352,13 +381,16 @@ if (hue_sat_dims.x > 0.0 || look_dims.x > 0.0) { } } -/// TRACES: FR-DEV-3e -/// The storage buffer a source's tables are uploaded as: the two header -/// `vec4`s, the HueSatMap's entries, then the LookTable's, each entry -/// `(hue shift, saturation scale, value scale, 0)`. +/// TRACES: FR-DEV-3e | FR-DEV-3j +/// The storage buffer a source's profile is uploaded as: the three header +/// `vec4`s, the HueSatMap's entries, the LookTable's, each entry +/// `(hue shift, saturation scale, value scale, 0)`, then the tone curve's +/// samples in `.x`. /// -/// Two zero `vec4`s where there are no tables — the placeholder every source -/// without a profile binds, and what makes the fragment pass through. +/// The curve is always there: the profile's own where it has one, Camera +/// Raw's ACR3 default otherwise — including in the placeholder every source +/// without a profile binds, whose tables are absent, so a raw with no +/// profile still renders through Camera Raw's tone (D21). pub fn profile_buffer(tables: Option<&ProfileTables>) -> Vec<[f32; 4]> { let header = |t: Option<&HueSatTable>| match t { Some(t) => [ @@ -371,10 +403,18 @@ pub fn profile_buffer(tables: Option<&ProfileTables>) -> Vec<[f32; 4]> { }; let hue_sat = tables.and_then(|t| t.hue_sat.as_ref()); let look = tables.and_then(|t| t.look.as_ref()); - let mut out = vec![header(hue_sat), header(look)]; + let curve: &[f32] = tables + .and_then(|t| t.tone_curve.as_deref()) + .unwrap_or(&dr_types::tone::ACR3_DEFAULT); + let mut out = vec![ + header(hue_sat), + header(look), + [curve.len() as f32, 0.0, 0.0, 0.0], + ]; for t in [hue_sat, look].into_iter().flatten() { out.extend(t.entries.iter().map(|e| [e[0], e[1], e[2], 0.0])); } + out.extend(curve.iter().map(|&v| [v, 0.0, 0.0, 0.0])); out } @@ -664,7 +704,10 @@ mod tests { #[test] fn the_buffer_puts_the_header_first_and_the_look_after_the_hue_sat_map() { - assert_eq!(profile_buffer(None), vec![[0.0; 4]; 2]); + let bare = profile_buffer(None); + assert_eq!(bare[..2], [[0.0; 4]; 2], "no tables"); + assert_eq!(bare[2][0], 1025.0, "and Camera Raw's default curve"); + assert_eq!(bare.len(), HEADER_ENTRIES + 1025); let t = tables( Some(uniform(2, 2, 1, [1.0, 2.0, 3.0])), Some(uniform(3, 2, 2, [4.0, 5.0, 6.0])), @@ -672,8 +715,9 @@ mod tests { let b = profile_buffer(Some(&t)); assert_eq!(b[0], [2.0, 2.0, 1.0, 0.0]); assert_eq!(b[1], [3.0, 2.0, 2.0, 0.0]); - assert_eq!(b.len(), HEADER_ENTRIES + 4 + 12); - assert_eq!(b[2], [1.0, 2.0, 3.0, 0.0]); + assert_eq!(b.len(), HEADER_ENTRIES + 4 + 12 + 1025); + assert_eq!(b[HEADER_ENTRIES], [1.0, 2.0, 3.0, 0.0]); assert_eq!(b[HEADER_ENTRIES + 4], [4.0, 5.0, 6.0, 0.0]); + assert_eq!(b[HEADER_ENTRIES + 16][0], dr_types::tone::ACR3_DEFAULT[0]); } } diff --git a/core/dr-pipeline/src/ops/view_transform.rs b/core/dr-pipeline/src/ops/view_transform.rs index 61de2f5..2beae69 100644 --- a/core/dr-pipeline/src/ops/view_transform.rs +++ b/core/dr-pipeline/src/ops/view_transform.rs @@ -33,11 +33,28 @@ use crate::view::{Sigmoid, CONTRAST_RANGE, DEFAULT_CONTRAST, DEFAULT_WHITE, WHIT pub const ID: OpId = OpId("view_transform"); pub const CONTRAST: ParamId = ParamId("contrast"); pub const WHITE: ParamId = ParamId("white"); +/// TRACES: FR-DEV-3j +/// Which curve renders: Camera Raw's (index 0, the default — D21) or D19's +/// sigmoid. +pub const CURVE: ParamId = ParamId("curve"); -static HELPERS: [Helper; 1] = [Helper { - name: "view_sigmoid", - source: crate::view::VIEW_SIGMOID_WGSL, -}]; +/// [`CURVE`]'s values, in the order of its variants. +pub const CAMERA_RAW: f32 = 0.0; +pub const SIGMOID: f32 = 1.0; + +static HELPERS: LazyLock<[Helper; 3]> = LazyLock::new(|| { + [ + Helper { + name: "view_sigmoid", + source: crate::view::VIEW_SIGMOID_WGSL, + }, + *crate::ops::camera_profile::PROPHOTO_HELPER, + Helper { + name: "camera_raw_tone", + source: crate::camera_raw::CAMERA_RAW_WGSL, + }, + ] +}); static DESCRIPTOR: LazyLock> = LazyLock::new(|| { Arc::new(OpDescriptor { @@ -67,6 +84,14 @@ static DESCRIPTOR: LazyLock> = LazyLock::new(|| { Scale::Linear, 1, ), + ParamDescriptor::choice( + "curve", + "param.view_transform.curve", + vec![ + LocalizedKey("param.view_transform.curve.camera_raw"), + LocalizedKey("param.view_transform.curve.sigmoid"), + ], + ), ], }) }); @@ -75,6 +100,7 @@ static DESCRIPTOR: LazyLock> = LazyLock::new(|| { pub struct ViewTransform { contrast: f32, white: f32, + curve: f32, } impl Default for ViewTransform { @@ -82,6 +108,7 @@ impl Default for ViewTransform { Self { contrast: DEFAULT_CONTRAST, white: DEFAULT_WHITE, + curve: CAMERA_RAW, } } } @@ -106,6 +133,7 @@ impl Operation for ViewTransform { match id { CONTRAST => self.contrast = value, WHITE => self.white = value, + CURVE => self.curve = value.round(), _ => log::warn!("view_transform: unknown parameter {id}"), } } @@ -114,12 +142,13 @@ impl Operation for ViewTransform { match id { CONTRAST => self.contrast, WHITE => self.white, + CURVE => self.curve, _ => 0.0, } } fn is_active(&self) -> bool { - self.contrast != DEFAULT_CONTRAST || self.white != DEFAULT_WHITE + self.contrast != DEFAULT_CONTRAST || self.white != DEFAULT_WHITE || self.curve != CAMERA_RAW } fn stage(&self) -> Stage { @@ -130,8 +159,13 @@ impl Operation for ViewTransform { "\ // Skipped for an already-rendered source: a JPEG is a display rendering // already, and rendering it again would compress it twice. +// Camera Raw's tone by default (D21), D19's sigmoid by choice. if (!non_linear) { - c = view_sigmoid(c, slope, inv_k, peak); + if (mode < 0.5) { + c = camera_raw_tone(c, cr_scale, cr_power, cr_grey); + } else { + c = view_sigmoid(c, slope, inv_k, peak); + } }" .into() } @@ -151,11 +185,27 @@ if (!non_linear) { name: "peak", value: s.w, }, + Uniform { + name: "mode", + value: self.curve, + }, + Uniform { + name: "cr_scale", + value: crate::camera_raw::input_scale(self.white), + }, + Uniform { + name: "cr_power", + value: crate::camera_raw::contrast_power(self.contrast), + }, + Uniform { + name: "cr_grey", + value: crate::view::SCENE_GREY, + }, ] } fn helpers(&self) -> &[Helper] { - &HELPERS + HELPERS.as_slice() } } @@ -191,7 +241,7 @@ mod tests { let s = Sigmoid::new(2.0, 6.0); let u = op.uniforms(); assert_eq!( - u.iter().map(|u| u.value).collect::>(), + u.iter().take(3).map(|u| u.value).collect::>(), vec![s.n, s.inv_k, s.w] ); } diff --git a/docs/dev/traceability.md b/docs/dev/traceability.md index 93439d1..cd28a58 100644 --- a/docs/dev/traceability.md +++ b/docs/dev/traceability.md @@ -9,8 +9,8 @@ Denominators are parsed from [`requirements.md`](requirements.md) at run time, n | Metric | Value | |---|---| -| Source files scanned | 498 | -| TRACES tags found | 2062 | +| Source files scanned | 499 | +| TRACES tags found | 2068 | | Requirements defined | 193 | | Requirements deferred (post-v1) | 24 | | Requirements covered | 166 | @@ -72,19 +72,19 @@ _None._ | FR-DEV-19a | [`core/dr-gpu/src/mask.rs:655`](../../core/dr-gpu/src/mask.rs#L655), [`core/dr-gpu/src/mask.rs:773`](../../core/dr-gpu/src/mask.rs#L773), [`core/dr-gpu/tests/local_adjustments.rs:793`](../../core/dr-gpu/tests/local_adjustments.rs#L793), [`core/dr-gpu/tests/local_adjustments.rs:841`](../../core/dr-gpu/tests/local_adjustments.rs#L841), [`core/dr-pipeline/src/mask.rs:1022`](../../core/dr-pipeline/src/mask.rs#L1022), [`core/dr-pipeline/src/mask.rs:1635`](../../core/dr-pipeline/src/mask.rs#L1635), [`core/dr-pipeline/src/mask.rs:3282`](../../core/dr-pipeline/src/mask.rs#L3282), [`core/dr-pipeline/src/mask.rs:3403`](../../core/dr-pipeline/src/mask.rs#L3403), [`core/dr-pipeline/src/mask.rs:3438`](../../core/dr-pipeline/src/mask.rs#L3438), [`core/dr-pipeline/src/mask.rs:929`](../../core/dr-pipeline/src/mask.rs#L929), [`core/dr-pipeline/src/mask.rs:964`](../../core/dr-pipeline/src/mask.rs#L964), [`core/dr-pipeline/src/sidecar.rs:1259`](../../core/dr-pipeline/src/sidecar.rs#L1259), [`core/dr-pipeline/tests/mask_sidecar.rs:1347`](../../core/dr-pipeline/tests/mask_sidecar.rs#L1347), [`core/dr-pipeline/tests/mask_sidecar.rs:1369`](../../core/dr-pipeline/tests/mask_sidecar.rs#L1369), [`core/dr-pipeline/tests/mask_sidecar.rs:1395`](../../core/dr-pipeline/tests/mask_sidecar.rs#L1395), [`ui/dr-ui/src/develop/masks.rs:432`](../../ui/dr-ui/src/develop/masks.rs#L432), [`ui/dr-ui/src/develop/masks.rs:493`](../../ui/dr-ui/src/develop/masks.rs#L493), [`ui/dr-ui/src/develop/masks.rs:512`](../../ui/dr-ui/src/develop/masks.rs#L512), [`ui/dr-ui/src/develop/masks.rs:547`](../../ui/dr-ui/src/develop/masks.rs#L547), [`ui/dr-ui/src/develop/session.rs:215`](../../ui/dr-ui/src/develop/session.rs#L215), [`ui/dr-ui/src/labels.rs:73`](../../ui/dr-ui/src/labels.rs#L73), [`ui/dr-ui/src/masks_ui.rs:1083`](../../ui/dr-ui/src/masks_ui.rs#L1083), [`ui/dr-ui/src/masks_ui.rs:1140`](../../ui/dr-ui/src/masks_ui.rs#L1140), [`ui/dr-ui/src/masks_ui.rs:1196`](../../ui/dr-ui/src/masks_ui.rs#L1196), [`ui/dr-ui/src/masks_ui.rs:1555`](../../ui/dr-ui/src/masks_ui.rs#L1555), [`ui/dr-ui/src/masks_ui.rs:1578`](../../ui/dr-ui/src/masks_ui.rs#L1578), [`ui/dr-ui/src/masks_ui.rs:270`](../../ui/dr-ui/src/masks_ui.rs#L270), [`ui/dr-ui/ui/app.slint:2694`](../../ui/dr-ui/ui/app.slint#L2694), [`ui/dr-ui/ui/masks.slint:151`](../../ui/dr-ui/ui/masks.slint#L151), [`ui/dr-ui/ui/masks.slint:176`](../../ui/dr-ui/ui/masks.slint#L176), [`ui/dr-ui/ui/masks.slint:339`](../../ui/dr-ui/ui/masks.slint#L339), [`ui/dr-ui/ui/masks.slint:379`](../../ui/dr-ui/ui/masks.slint#L379), [`ui/dr-ui/ui/masks.slint:422`](../../ui/dr-ui/ui/masks.slint#L422), [`ui/dr-ui/ui/masks.slint:468`](../../ui/dr-ui/ui/masks.slint#L468), [`ui/dr-ui/ui/masks.slint:796`](../../ui/dr-ui/ui/masks.slint#L796), [`ui/dr-ui/ui/masks.slint:881`](../../ui/dr-ui/ui/masks.slint#L881) | | FR-DEV-19b | [`ui/dr-ui/src/develop/mask_ops.rs:606`](../../ui/dr-ui/src/develop/mask_ops.rs#L606), [`ui/dr-ui/src/develop/masks.rs:595`](../../ui/dr-ui/src/develop/masks.rs#L595), [`ui/dr-ui/src/develop/session.rs:224`](../../ui/dr-ui/src/develop/session.rs#L224), [`ui/dr-ui/src/develop/session.rs:231`](../../ui/dr-ui/src/develop/session.rs#L231), [`ui/dr-ui/src/labels.rs:67`](../../ui/dr-ui/src/labels.rs#L67), [`ui/dr-ui/src/masks_ui.rs:1229`](../../ui/dr-ui/src/masks_ui.rs#L1229), [`ui/dr-ui/src/masks_ui.rs:1448`](../../ui/dr-ui/src/masks_ui.rs#L1448), [`ui/dr-ui/src/masks_ui.rs:1476`](../../ui/dr-ui/src/masks_ui.rs#L1476), [`ui/dr-ui/src/masks_ui.rs:1849`](../../ui/dr-ui/src/masks_ui.rs#L1849), [`ui/dr-ui/src/masks_ui.rs:908`](../../ui/dr-ui/src/masks_ui.rs#L908), [`ui/dr-ui/ui/app.slint:2229`](../../ui/dr-ui/ui/app.slint#L2229), [`ui/dr-ui/ui/app.slint:861`](../../ui/dr-ui/ui/app.slint#L861), [`ui/dr-ui/ui/masks.slint:1156`](../../ui/dr-ui/ui/masks.slint#L1156), [`ui/dr-ui/ui/masks.slint:479`](../../ui/dr-ui/ui/masks.slint#L479), [`ui/dr-ui/ui/masks.slint:800`](../../ui/dr-ui/ui/masks.slint#L800), [`ui/dr-ui/ui/masks.slint:874`](../../ui/dr-ui/ui/masks.slint#L874), [`ui/dr-ui/ui/masks.slint:894`](../../ui/dr-ui/ui/masks.slint#L894) | | FR-DEV-19c | [`core/dr-gpu/src/mask.rs:727`](../../core/dr-gpu/src/mask.rs#L727), [`core/dr-gpu/tests/local_adjustments.rs:1000`](../../core/dr-gpu/tests/local_adjustments.rs#L1000), [`core/dr-gpu/tests/local_adjustments.rs:1035`](../../core/dr-gpu/tests/local_adjustments.rs#L1035), [`core/dr-gpu/tests/local_adjustments.rs:1080`](../../core/dr-gpu/tests/local_adjustments.rs#L1080), [`core/dr-gpu/tests/local_adjustments.rs:943`](../../core/dr-gpu/tests/local_adjustments.rs#L943), [`core/dr-pipeline/src/graph.rs:1048`](../../core/dr-pipeline/src/graph.rs#L1048), [`core/dr-pipeline/src/mask.rs:1843`](../../core/dr-pipeline/src/mask.rs#L1843), [`core/dr-pipeline/src/mask.rs:1869`](../../core/dr-pipeline/src/mask.rs#L1869), [`core/dr-pipeline/src/mask.rs:1884`](../../core/dr-pipeline/src/mask.rs#L1884), [`core/dr-pipeline/src/mask.rs:2006`](../../core/dr-pipeline/src/mask.rs#L2006), [`core/dr-pipeline/src/mask.rs:2065`](../../core/dr-pipeline/src/mask.rs#L2065), [`core/dr-pipeline/src/mask.rs:2309`](../../core/dr-pipeline/src/mask.rs#L2309), [`core/dr-pipeline/src/mask.rs:2621`](../../core/dr-pipeline/src/mask.rs#L2621), [`core/dr-pipeline/src/operation.rs:1103`](../../core/dr-pipeline/src/operation.rs#L1103), [`core/dr-pipeline/src/operation.rs:2140`](../../core/dr-pipeline/src/operation.rs#L2140), [`core/dr-pipeline/src/operation.rs:738`](../../core/dr-pipeline/src/operation.rs#L738), [`ui/dr-ui/src/develop/mask_ops.rs:1199`](../../ui/dr-ui/src/develop/mask_ops.rs#L1199), [`ui/dr-ui/src/develop/mask_ops.rs:1235`](../../ui/dr-ui/src/develop/mask_ops.rs#L1235), [`ui/dr-ui/src/develop/mask_ops.rs:318`](../../ui/dr-ui/src/develop/mask_ops.rs#L318), [`ui/dr-ui/src/develop/mask_ops.rs:58`](../../ui/dr-ui/src/develop/mask_ops.rs#L58), [`ui/dr-ui/src/develop/masks.rs:12`](../../ui/dr-ui/src/develop/masks.rs#L12), [`ui/dr-ui/src/develop/masks.rs:176`](../../ui/dr-ui/src/develop/masks.rs#L176), [`ui/dr-ui/src/develop/masks.rs:21`](../../ui/dr-ui/src/develop/masks.rs#L21), [`ui/dr-ui/src/develop/masks.rs:43`](../../ui/dr-ui/src/develop/masks.rs#L43), [`ui/dr-ui/src/develop/render.rs:358`](../../ui/dr-ui/src/develop/render.rs#L358), [`ui/dr-ui/src/develop/session.rs:250`](../../ui/dr-ui/src/develop/session.rs#L250), [`ui/dr-ui/src/develop/session.rs:259`](../../ui/dr-ui/src/develop/session.rs#L259), [`ui/dr-ui/src/masks_ui.rs:1024`](../../ui/dr-ui/src/masks_ui.rs#L1024), [`ui/dr-ui/src/masks_ui.rs:1448`](../../ui/dr-ui/src/masks_ui.rs#L1448), [`ui/dr-ui/src/masks_ui.rs:152`](../../ui/dr-ui/src/masks_ui.rs#L152), [`ui/dr-ui/src/masks_ui.rs:1849`](../../ui/dr-ui/src/masks_ui.rs#L1849), [`ui/dr-ui/src/masks_ui.rs:291`](../../ui/dr-ui/src/masks_ui.rs#L291), [`ui/dr-ui/src/masks_ui.rs:317`](../../ui/dr-ui/src/masks_ui.rs#L317), [`ui/dr-ui/src/masks_ui.rs:677`](../../ui/dr-ui/src/masks_ui.rs#L677), [`ui/dr-ui/src/masks_ui.rs:996`](../../ui/dr-ui/src/masks_ui.rs#L996), [`ui/dr-ui/ui/icons.slint:340`](../../ui/dr-ui/ui/icons.slint#L340), [`ui/dr-ui/ui/masks.slint:1121`](../../ui/dr-ui/ui/masks.slint#L1121), [`ui/dr-ui/ui/masks.slint:184`](../../ui/dr-ui/ui/masks.slint#L184), [`ui/dr-ui/ui/masks.slint:294`](../../ui/dr-ui/ui/masks.slint#L294), [`ui/dr-ui/ui/masks.slint:543`](../../ui/dr-ui/ui/masks.slint#L543), [`ui/dr-ui/ui/masks.slint:70`](../../ui/dr-ui/ui/masks.slint#L70), [`ui/dr-ui/ui/masks.slint:808`](../../ui/dr-ui/ui/masks.slint#L808), [`ui/dr-ui/ui/masks.slint:876`](../../ui/dr-ui/ui/masks.slint#L876), [`ui/dr-ui/ui/masks.slint:968`](../../ui/dr-ui/ui/masks.slint#L968) | -| FR-DEV-2 | [`core/dr-gpu/tests/scene_referred.rs:145`](../../core/dr-gpu/tests/scene_referred.rs#L145), [`core/dr-gpu/tests/scene_referred.rs:1`](../../core/dr-gpu/tests/scene_referred.rs#L1), [`core/dr-gpu/tests/view_transform.rs:154`](../../core/dr-gpu/tests/view_transform.rs#L154), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:90`](../../core/dr-gpu/tests/view_transform.rs#L90), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2459`](../../core/dr-pipeline/src/operation.rs#L2459), [`core/dr-pipeline/src/operation.rs:2700`](../../core/dr-pipeline/src/operation.rs#L2700), [`core/dr-pipeline/src/operation.rs:369`](../../core/dr-pipeline/src/operation.rs#L369), [`core/dr-pipeline/src/operation.rs:443`](../../core/dr-pipeline/src/operation.rs#L443), [`core/dr-pipeline/src/operation.rs:463`](../../core/dr-pipeline/src/operation.rs#L463), [`core/dr-pipeline/src/operation.rs:505`](../../core/dr-pipeline/src/operation.rs#L505), [`core/dr-pipeline/src/ops/curve.rs:491`](../../core/dr-pipeline/src/ops/curve.rs#L491), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211) | +| FR-DEV-2 | [`core/dr-gpu/tests/scene_referred.rs:145`](../../core/dr-gpu/tests/scene_referred.rs#L145), [`core/dr-gpu/tests/scene_referred.rs:1`](../../core/dr-gpu/tests/scene_referred.rs#L1), [`core/dr-gpu/tests/view_transform.rs:124`](../../core/dr-gpu/tests/view_transform.rs#L124), [`core/dr-gpu/tests/view_transform.rs:188`](../../core/dr-gpu/tests/view_transform.rs#L188), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2459`](../../core/dr-pipeline/src/operation.rs#L2459), [`core/dr-pipeline/src/operation.rs:2700`](../../core/dr-pipeline/src/operation.rs#L2700), [`core/dr-pipeline/src/operation.rs:369`](../../core/dr-pipeline/src/operation.rs#L369), [`core/dr-pipeline/src/operation.rs:443`](../../core/dr-pipeline/src/operation.rs#L443), [`core/dr-pipeline/src/operation.rs:463`](../../core/dr-pipeline/src/operation.rs#L463), [`core/dr-pipeline/src/operation.rs:505`](../../core/dr-pipeline/src/operation.rs#L505), [`core/dr-pipeline/src/ops/curve.rs:491`](../../core/dr-pipeline/src/ops/curve.rs#L491), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211) | | FR-DEV-20 | [`core/dr-gpu/src/adjust.rs:2338`](../../core/dr-gpu/src/adjust.rs#L2338), [`core/dr-pipeline/src/framing.rs:1377`](../../core/dr-pipeline/src/framing.rs#L1377), [`core/dr-pipeline/src/framing.rs:170`](../../core/dr-pipeline/src/framing.rs#L170), [`core/dr-pipeline/src/framing.rs:401`](../../core/dr-pipeline/src/framing.rs#L401), [`core/dr-pipeline/src/framing.rs:495`](../../core/dr-pipeline/src/framing.rs#L495), [`core/dr-pipeline/src/framing.rs:652`](../../core/dr-pipeline/src/framing.rs#L652), [`core/dr-pipeline/src/framing.rs:663`](../../core/dr-pipeline/src/framing.rs#L663), [`core/dr-pipeline/src/framing.rs:88`](../../core/dr-pipeline/src/framing.rs#L88), [`core/dr-pipeline/src/framing.rs:92`](../../core/dr-pipeline/src/framing.rs#L92), [`core/dr-pipeline/src/framing.rs:938`](../../core/dr-pipeline/src/framing.rs#L938), [`core/dr-pipeline/src/framing.rs:994`](../../core/dr-pipeline/src/framing.rs#L994), [`core/dr-pipeline/src/preset.rs:1001`](../../core/dr-pipeline/src/preset.rs#L1001), [`core/dr-pipeline/src/sidecar.rs:2197`](../../core/dr-pipeline/src/sidecar.rs#L2197), [`ui/dr-ui/src/develop/framing.rs:1185`](../../ui/dr-ui/src/develop/framing.rs#L1185), [`ui/dr-ui/src/develop/framing.rs:418`](../../ui/dr-ui/src/develop/framing.rs#L418), [`ui/dr-ui/src/develop/framing.rs:474`](../../ui/dr-ui/src/develop/framing.rs#L474), [`ui/dr-ui/src/develop/framing.rs:480`](../../ui/dr-ui/src/develop/framing.rs#L480), [`ui/dr-ui/src/develop/framing.rs:489`](../../ui/dr-ui/src/develop/framing.rs#L489), [`ui/dr-ui/src/develop_ui.rs:1390`](../../ui/dr-ui/src/develop_ui.rs#L1390), [`ui/dr-ui/src/develop_ui.rs:1423`](../../ui/dr-ui/src/develop_ui.rs#L1423), [`ui/dr-ui/src/labels.rs:295`](../../ui/dr-ui/src/labels.rs#L295), [`ui/dr-ui/ui/adjust.slint:646`](../../ui/dr-ui/ui/adjust.slint#L646), [`ui/dr-ui/ui/adjust.slint:688`](../../ui/dr-ui/ui/adjust.slint#L688), [`ui/dr-ui/ui/adjust.slint:831`](../../ui/dr-ui/ui/adjust.slint#L831), [`ui/dr-ui/ui/app.slint:2718`](../../ui/dr-ui/ui/app.slint#L2718), [`ui/dr-ui/ui/app.slint:727`](../../ui/dr-ui/ui/app.slint#L727), [`ui/dr-ui/ui/app.slint:750`](../../ui/dr-ui/ui/app.slint#L750) | | FR-DEV-3 | [`core/dr-gpu/src/adjust.rs:1107`](../../core/dr-gpu/src/adjust.rs#L1107), [`core/dr-gpu/src/adjust.rs:2960`](../../core/dr-gpu/src/adjust.rs#L2960), [`core/dr-gpu/src/adjust.rs:82`](../../core/dr-gpu/src/adjust.rs#L82), [`core/dr-gpu/src/adjust.rs:969`](../../core/dr-gpu/src/adjust.rs#L969), [`core/dr-gpu/tests/tone_curve.rs:1`](../../core/dr-gpu/tests/tone_curve.rs#L1), [`core/dr-pipeline/src/coverage.rs:122`](../../core/dr-pipeline/src/coverage.rs#L122), [`core/dr-pipeline/src/coverage.rs:1`](../../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/detail.rs:491`](../../core/dr-pipeline/src/detail.rs#L491), [`core/dr-pipeline/src/detail.rs:592`](../../core/dr-pipeline/src/detail.rs#L592), [`core/dr-pipeline/src/framing.rs:1111`](../../core/dr-pipeline/src/framing.rs#L1111), [`core/dr-pipeline/src/framing.rs:251`](../../core/dr-pipeline/src/framing.rs#L251), [`core/dr-pipeline/src/framing.rs:321`](../../core/dr-pipeline/src/framing.rs#L321), [`core/dr-pipeline/src/framing.rs:481`](../../core/dr-pipeline/src/framing.rs#L481), [`core/dr-pipeline/src/framing.rs:717`](../../core/dr-pipeline/src/framing.rs#L717), [`core/dr-pipeline/src/graph.rs:1015`](../../core/dr-pipeline/src/graph.rs#L1015), [`core/dr-pipeline/src/graph.rs:1107`](../../core/dr-pipeline/src/graph.rs#L1107), [`core/dr-pipeline/src/graph.rs:1505`](../../core/dr-pipeline/src/graph.rs#L1505), [`core/dr-pipeline/src/graph.rs:1536`](../../core/dr-pipeline/src/graph.rs#L1536), [`core/dr-pipeline/src/graph.rs:1559`](../../core/dr-pipeline/src/graph.rs#L1559), [`core/dr-pipeline/src/graph.rs:1597`](../../core/dr-pipeline/src/graph.rs#L1597), [`core/dr-pipeline/src/graph.rs:1628`](../../core/dr-pipeline/src/graph.rs#L1628), [`core/dr-pipeline/src/graph.rs:247`](../../core/dr-pipeline/src/graph.rs#L247), [`core/dr-pipeline/src/graph.rs:379`](../../core/dr-pipeline/src/graph.rs#L379), [`core/dr-pipeline/src/graph.rs:437`](../../core/dr-pipeline/src/graph.rs#L437), [`core/dr-pipeline/src/graph.rs:443`](../../core/dr-pipeline/src/graph.rs#L443), [`core/dr-pipeline/src/lens.rs:93`](../../core/dr-pipeline/src/lens.rs#L93), [`core/dr-pipeline/src/mask.rs:205`](../../core/dr-pipeline/src/mask.rs#L205), [`core/dr-pipeline/src/mask.rs:558`](../../core/dr-pipeline/src/mask.rs#L558), [`core/dr-pipeline/src/neutral.rs:1`](../../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:306`](../../core/dr-pipeline/src/neutral.rs#L306), [`core/dr-pipeline/src/neutral.rs:322`](../../core/dr-pipeline/src/neutral.rs#L322), [`core/dr-pipeline/src/neutral.rs:338`](../../core/dr-pipeline/src/neutral.rs#L338), [`core/dr-pipeline/src/neutral.rs:360`](../../core/dr-pipeline/src/neutral.rs#L360), [`core/dr-pipeline/src/neutral.rs:81`](../../core/dr-pipeline/src/neutral.rs#L81), [`core/dr-pipeline/src/operation.rs:334`](../../core/dr-pipeline/src/operation.rs#L334), [`core/dr-pipeline/src/operation.rs:377`](../../core/dr-pipeline/src/operation.rs#L377), [`core/dr-pipeline/src/operation.rs:714`](../../core/dr-pipeline/src/operation.rs#L714), [`core/dr-pipeline/src/operation.rs:787`](../../core/dr-pipeline/src/operation.rs#L787), [`core/dr-pipeline/src/operation.rs:969`](../../core/dr-pipeline/src/operation.rs#L969), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:210`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L210), [`core/dr-pipeline/src/ops/curve.rs:100`](../../core/dr-pipeline/src/ops/curve.rs#L100), [`core/dr-pipeline/src/ops/curve.rs:1`](../../core/dr-pipeline/src/ops/curve.rs#L1), [`core/dr-pipeline/src/ops/curve.rs:219`](../../core/dr-pipeline/src/ops/curve.rs#L219), [`core/dr-pipeline/src/ops/curve.rs:669`](../../core/dr-pipeline/src/ops/curve.rs#L669), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:1`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:273`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L273), [`core/dr-pipeline/src/preset.rs:927`](../../core/dr-pipeline/src/preset.rs#L927), [`core/dr-pipeline/src/sidecar.rs:1433`](../../core/dr-pipeline/src/sidecar.rs#L1433), [`core/dr-pipeline/src/sidecar.rs:206`](../../core/dr-pipeline/src/sidecar.rs#L206), [`core/dr-pipeline/src/sidecar.rs:2275`](../../core/dr-pipeline/src/sidecar.rs#L2275), [`core/dr-pipeline/src/sidecar.rs:2355`](../../core/dr-pipeline/src/sidecar.rs#L2355), [`core/dr-pipeline/tests/tone_curve.rs:1`](../../core/dr-pipeline/tests/tone_curve.rs#L1), [`core/dr-segment/src/refine.rs:937`](../../core/dr-segment/src/refine.rs#L937), [`ui/dr-ui/src/develop/curves.rs:163`](../../ui/dr-ui/src/develop/curves.rs#L163), [`ui/dr-ui/src/develop/framing.rs:10`](../../ui/dr-ui/src/develop/framing.rs#L10), [`ui/dr-ui/src/develop/framing.rs:298`](../../ui/dr-ui/src/develop/framing.rs#L298), [`ui/dr-ui/src/develop/framing.rs:328`](../../ui/dr-ui/src/develop/framing.rs#L328), [`ui/dr-ui/src/develop/framing.rs:394`](../../ui/dr-ui/src/develop/framing.rs#L394), [`ui/dr-ui/src/develop/framing.rs:408`](../../ui/dr-ui/src/develop/framing.rs#L408), [`ui/dr-ui/src/develop/framing.rs:690`](../../ui/dr-ui/src/develop/framing.rs#L690), [`ui/dr-ui/src/develop/framing.rs:71`](../../ui/dr-ui/src/develop/framing.rs#L71), [`ui/dr-ui/src/develop/mask_ops.rs:1076`](../../ui/dr-ui/src/develop/mask_ops.rs#L1076), [`ui/dr-ui/src/develop/mask_ops.rs:1340`](../../ui/dr-ui/src/develop/mask_ops.rs#L1340), [`ui/dr-ui/src/develop/mask_ops.rs:178`](../../ui/dr-ui/src/develop/mask_ops.rs#L178), [`ui/dr-ui/src/develop/mask_ops.rs:969`](../../ui/dr-ui/src/develop/mask_ops.rs#L969), [`ui/dr-ui/src/develop/masks.rs:263`](../../ui/dr-ui/src/develop/masks.rs#L263), [`ui/dr-ui/src/develop/masks.rs:361`](../../ui/dr-ui/src/develop/masks.rs#L361), [`ui/dr-ui/src/develop/masks.rs:743`](../../ui/dr-ui/src/develop/masks.rs#L743), [`ui/dr-ui/src/develop/masks.rs:773`](../../ui/dr-ui/src/develop/masks.rs#L773), [`ui/dr-ui/src/develop/render.rs:1390`](../../ui/dr-ui/src/develop/render.rs#L1390), [`ui/dr-ui/src/develop/rows.rs:106`](../../ui/dr-ui/src/develop/rows.rs#L106), [`ui/dr-ui/src/develop/rows.rs:195`](../../ui/dr-ui/src/develop/rows.rs#L195), [`ui/dr-ui/src/develop/rows.rs:231`](../../ui/dr-ui/src/develop/rows.rs#L231), [`ui/dr-ui/src/develop/rows.rs:679`](../../ui/dr-ui/src/develop/rows.rs#L679), [`ui/dr-ui/src/develop/segmentation.rs:139`](../../ui/dr-ui/src/develop/segmentation.rs#L139), [`ui/dr-ui/src/develop/segmentation.rs:302`](../../ui/dr-ui/src/develop/segmentation.rs#L302), [`ui/dr-ui/src/develop/segmentation.rs:339`](../../ui/dr-ui/src/develop/segmentation.rs#L339), [`ui/dr-ui/src/develop/segmentation.rs:572`](../../ui/dr-ui/src/develop/segmentation.rs#L572), [`ui/dr-ui/src/develop/segmentation.rs:590`](../../ui/dr-ui/src/develop/segmentation.rs#L590), [`ui/dr-ui/src/develop/segmentation.rs:604`](../../ui/dr-ui/src/develop/segmentation.rs#L604), [`ui/dr-ui/src/develop/segmentation.rs:626`](../../ui/dr-ui/src/develop/segmentation.rs#L626), [`ui/dr-ui/src/develop/segmentation.rs:77`](../../ui/dr-ui/src/develop/segmentation.rs#L77), [`ui/dr-ui/src/develop/segmentation.rs:806`](../../ui/dr-ui/src/develop/segmentation.rs#L806), [`ui/dr-ui/src/develop/session.rs:185`](../../ui/dr-ui/src/develop/session.rs#L185), [`ui/dr-ui/src/develop/session.rs:278`](../../ui/dr-ui/src/develop/session.rs#L278), [`ui/dr-ui/src/develop/session.rs:307`](../../ui/dr-ui/src/develop/session.rs#L307), [`ui/dr-ui/src/develop/session.rs:505`](../../ui/dr-ui/src/develop/session.rs#L505), [`ui/dr-ui/src/develop/session.rs:565`](../../ui/dr-ui/src/develop/session.rs#L565), [`ui/dr-ui/src/develop/session.rs:705`](../../ui/dr-ui/src/develop/session.rs#L705), [`ui/dr-ui/src/develop/session.rs:964`](../../ui/dr-ui/src/develop/session.rs#L964), [`ui/dr-ui/src/develop/white_balance.rs:11`](../../ui/dr-ui/src/develop/white_balance.rs#L11), [`ui/dr-ui/src/develop/white_balance.rs:162`](../../ui/dr-ui/src/develop/white_balance.rs#L162), [`ui/dr-ui/src/develop/white_balance.rs:193`](../../ui/dr-ui/src/develop/white_balance.rs#L193), [`ui/dr-ui/src/develop/white_balance.rs:277`](../../ui/dr-ui/src/develop/white_balance.rs#L277), [`ui/dr-ui/src/develop/white_balance.rs:340`](../../ui/dr-ui/src/develop/white_balance.rs#L340), [`ui/dr-ui/src/develop_ui.rs:118`](../../ui/dr-ui/src/develop_ui.rs#L118), [`ui/dr-ui/src/develop_ui.rs:1203`](../../ui/dr-ui/src/develop_ui.rs#L1203), [`ui/dr-ui/src/develop_ui.rs:1300`](../../ui/dr-ui/src/develop_ui.rs#L1300), [`ui/dr-ui/src/develop_ui.rs:1354`](../../ui/dr-ui/src/develop_ui.rs#L1354), [`ui/dr-ui/src/develop_ui.rs:601`](../../ui/dr-ui/src/develop_ui.rs#L601), [`ui/dr-ui/src/develop_ui.rs:821`](../../ui/dr-ui/src/develop_ui.rs#L821), [`ui/dr-ui/src/labels.rs:35`](../../ui/dr-ui/src/labels.rs#L35), [`ui/dr-ui/src/lib.rs:2253`](../../ui/dr-ui/src/lib.rs#L2253), [`ui/dr-ui/src/lib.rs:468`](../../ui/dr-ui/src/lib.rs#L468), [`ui/dr-ui/src/lib.rs:498`](../../ui/dr-ui/src/lib.rs#L498), [`ui/dr-ui/src/lib.rs:606`](../../ui/dr-ui/src/lib.rs#L606), [`ui/dr-ui/src/lib.rs:630`](../../ui/dr-ui/src/lib.rs#L630), [`ui/dr-ui/src/library/sidecar.rs:66`](../../ui/dr-ui/src/library/sidecar.rs#L66), [`ui/dr-ui/src/masks_ui.rs:1608`](../../ui/dr-ui/src/masks_ui.rs#L1608), [`ui/dr-ui/src/masks_ui.rs:1722`](../../ui/dr-ui/src/masks_ui.rs#L1722), [`ui/dr-ui/src/masks_ui.rs:339`](../../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/masks_ui.rs:44`](../../ui/dr-ui/src/masks_ui.rs#L44), [`ui/dr-ui/src/presets.rs:414`](../../ui/dr-ui/src/presets.rs#L414), [`ui/dr-ui/src/segmentation.rs:117`](../../ui/dr-ui/src/segmentation.rs#L117), [`ui/dr-ui/src/segmentation.rs:353`](../../ui/dr-ui/src/segmentation.rs#L353), [`ui/dr-ui/src/segmentation.rs:369`](../../ui/dr-ui/src/segmentation.rs#L369), [`ui/dr-ui/src/segmentation.rs:499`](../../ui/dr-ui/src/segmentation.rs#L499), [`ui/dr-ui/src/segmentation.rs:527`](../../ui/dr-ui/src/segmentation.rs#L527), [`ui/dr-ui/ui/adjust.slint:1050`](../../ui/dr-ui/ui/adjust.slint#L1050), [`ui/dr-ui/ui/adjust.slint:127`](../../ui/dr-ui/ui/adjust.slint#L127), [`ui/dr-ui/ui/adjust.slint:1658`](../../ui/dr-ui/ui/adjust.slint#L1658), [`ui/dr-ui/ui/adjust.slint:173`](../../ui/dr-ui/ui/adjust.slint#L173), [`ui/dr-ui/ui/adjust.slint:47`](../../ui/dr-ui/ui/adjust.slint#L47), [`ui/dr-ui/ui/adjust.slint:626`](../../ui/dr-ui/ui/adjust.slint#L626), [`ui/dr-ui/ui/adjust.slint:662`](../../ui/dr-ui/ui/adjust.slint#L662), [`ui/dr-ui/ui/adjust.slint:681`](../../ui/dr-ui/ui/adjust.slint#L681), [`ui/dr-ui/ui/adjust.slint:874`](../../ui/dr-ui/ui/adjust.slint#L874), [`ui/dr-ui/ui/adjust.slint:973`](../../ui/dr-ui/ui/adjust.slint#L973), [`ui/dr-ui/ui/app.slint:2294`](../../ui/dr-ui/ui/app.slint#L2294), [`ui/dr-ui/ui/app.slint:2356`](../../ui/dr-ui/ui/app.slint#L2356), [`ui/dr-ui/ui/app.slint:242`](../../ui/dr-ui/ui/app.slint#L242), [`ui/dr-ui/ui/develop.slint:375`](../../ui/dr-ui/ui/develop.slint#L375), [`ui/dr-ui/ui/masks.slint:1246`](../../ui/dr-ui/ui/masks.slint#L1246), [`ui/dr-ui/ui/masks.slint:779`](../../ui/dr-ui/ui/masks.slint#L779), [`ui/dr-ui/ui/masks.slint:838`](../../ui/dr-ui/ui/masks.slint#L838) | | FR-DEV-3a | [`core/dr-pipeline/ops/exposure.yaml:1`](../../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/descriptor.rs:212`](../../core/dr-pipeline/src/descriptor.rs#L212), [`core/dr-pipeline/src/descriptor.rs:252`](../../core/dr-pipeline/src/descriptor.rs#L252), [`core/dr-pipeline/src/descriptor.rs:276`](../../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/descriptor.rs:331`](../../core/dr-pipeline/src/descriptor.rs#L331), [`core/dr-pipeline/src/framing.rs:568`](../../core/dr-pipeline/src/framing.rs#L568), [`core/dr-pipeline/src/graph.rs:25`](../../core/dr-pipeline/src/graph.rs#L25), [`core/dr-pipeline/src/graph.rs:47`](../../core/dr-pipeline/src/graph.rs#L47), [`core/dr-pipeline/src/graph.rs:486`](../../core/dr-pipeline/src/graph.rs#L486), [`core/dr-pipeline/src/graph.rs:60`](../../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/graph.rs:655`](../../core/dr-pipeline/src/graph.rs#L655), [`core/dr-pipeline/src/mask.rs:1746`](../../core/dr-pipeline/src/mask.rs#L1746), [`core/dr-pipeline/src/neutral.rs:1`](../../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:378`](../../core/dr-pipeline/src/neutral.rs#L378), [`core/dr-pipeline/src/operation.rs:232`](../../core/dr-pipeline/src/operation.rs#L232), [`core/dr-pipeline/src/operation.rs:412`](../../core/dr-pipeline/src/operation.rs#L412), [`core/dr-pipeline/src/ops/curve.rs:319`](../../core/dr-pipeline/src/ops/curve.rs#L319), [`ui/dr-ui/src/develop/curves.rs:36`](../../ui/dr-ui/src/develop/curves.rs#L36), [`ui/dr-ui/src/develop/rows.rs:118`](../../ui/dr-ui/src/develop/rows.rs#L118), [`ui/dr-ui/src/develop/rows.rs:679`](../../ui/dr-ui/src/develop/rows.rs#L679), [`ui/dr-ui/src/develop/rows.rs:877`](../../ui/dr-ui/src/develop/rows.rs#L877), [`ui/dr-ui/src/lib.rs:955`](../../ui/dr-ui/src/lib.rs#L955), [`ui/dr-ui/tests/ui_names_no_operation.rs:1`](../../ui/dr-ui/tests/ui_names_no_operation.rs#L1), [`ui/dr-ui/ui/app.slint:2748`](../../ui/dr-ui/ui/app.slint#L2748) | | FR-DEV-3b | [`core/dr-pipeline/src/descriptor.rs:276`](../../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/framing.rs:568`](../../core/dr-pipeline/src/framing.rs#L568), [`core/dr-pipeline/src/graph.rs:60`](../../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/operation.rs:412`](../../core/dr-pipeline/src/operation.rs#L412), [`ui/dr-ui/ui/app.slint:3027`](../../ui/dr-ui/ui/app.slint#L3027) | | FR-DEV-3c | [`core/dr-pipeline/ops/exposure.yaml:1`](../../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/graph.rs:47`](../../core/dr-pipeline/src/graph.rs#L47), [`core/dr-pipeline/src/graph.rs:486`](../../core/dr-pipeline/src/graph.rs#L486), [`core/dr-pipeline/src/mask.rs:1746`](../../core/dr-pipeline/src/mask.rs#L1746), [`core/dr-pipeline/src/preset.rs:927`](../../core/dr-pipeline/src/preset.rs#L927), [`ui/dr-ui/src/develop/rows.rs:928`](../../ui/dr-ui/src/develop/rows.rs#L928) | | FR-DEV-3d | [`core/dr-gpu/src/adjust.rs:1107`](../../core/dr-gpu/src/adjust.rs#L1107), [`core/dr-gpu/src/adjust.rs:112`](../../core/dr-gpu/src/adjust.rs#L112), [`core/dr-gpu/src/adjust.rs:1429`](../../core/dr-gpu/src/adjust.rs#L1429), [`core/dr-gpu/src/adjust.rs:1523`](../../core/dr-gpu/src/adjust.rs#L1523), [`core/dr-gpu/src/adjust.rs:82`](../../core/dr-gpu/src/adjust.rs#L82), [`core/dr-gpu/tests/capture_sharpen.rs:433`](../../core/dr-gpu/tests/capture_sharpen.rs#L433), [`core/dr-gpu/tests/detail_stage.rs:241`](../../core/dr-gpu/tests/detail_stage.rs#L241), [`core/dr-gpu/tests/local_contrast.rs:557`](../../core/dr-gpu/tests/local_contrast.rs#L557), [`core/dr-gpu/tests/noise_reduction.rs:555`](../../core/dr-gpu/tests/noise_reduction.rs#L555), [`core/dr-pipeline/src/framing.rs:481`](../../core/dr-pipeline/src/framing.rs#L481), [`core/dr-pipeline/src/graph.rs:1135`](../../core/dr-pipeline/src/graph.rs#L1135), [`core/dr-pipeline/src/operation.rs:32`](../../core/dr-pipeline/src/operation.rs#L32), [`core/dr-pipeline/src/operation.rs:505`](../../core/dr-pipeline/src/operation.rs#L505), [`core/dr-pipeline/src/operation.rs:53`](../../core/dr-pipeline/src/operation.rs#L53), [`core/dr-pipeline/src/operation.rs:71`](../../core/dr-pipeline/src/operation.rs#L71) | -| FR-DEV-3e | [`core/dr-decode/src/dcp.rs:132`](../../core/dr-decode/src/dcp.rs#L132), [`core/dr-decode/src/dcp.rs:163`](../../core/dr-decode/src/dcp.rs#L163), [`core/dr-decode/src/dcp.rs:182`](../../core/dr-decode/src/dcp.rs#L182), [`core/dr-decode/src/dcp.rs:1`](../../core/dr-decode/src/dcp.rs#L1), [`core/dr-decode/src/dcp.rs:205`](../../core/dr-decode/src/dcp.rs#L205), [`core/dr-decode/src/dcp.rs:240`](../../core/dr-decode/src/dcp.rs#L240), [`core/dr-decode/src/dcp.rs:431`](../../core/dr-decode/src/dcp.rs#L431), [`core/dr-decode/src/dcp.rs:482`](../../core/dr-decode/src/dcp.rs#L482), [`core/dr-decode/src/dcp.rs:493`](../../core/dr-decode/src/dcp.rs#L493), [`core/dr-decode/src/dcp.rs:526`](../../core/dr-decode/src/dcp.rs#L526), [`core/dr-decode/src/dcp.rs:546`](../../core/dr-decode/src/dcp.rs#L546), [`core/dr-decode/src/dcp.rs:559`](../../core/dr-decode/src/dcp.rs#L559), [`core/dr-decode/src/dcp.rs:79`](../../core/dr-decode/src/dcp.rs#L79), [`core/dr-decode/src/lib.rs:126`](../../core/dr-decode/src/lib.rs#L126), [`core/dr-decode/src/lib.rs:141`](../../core/dr-decode/src/lib.rs#L141), [`core/dr-decode/src/lib.rs:150`](../../core/dr-decode/src/lib.rs#L150), [`core/dr-decode/src/lib.rs:601`](../../core/dr-decode/src/lib.rs#L601), [`core/dr-decode/src/lib.rs:799`](../../core/dr-decode/src/lib.rs#L799), [`core/dr-decode/src/lib.rs:839`](../../core/dr-decode/src/lib.rs#L839), [`core/dr-decode/src/profile.rs:104`](../../core/dr-decode/src/profile.rs#L104), [`core/dr-decode/src/profile.rs:153`](../../core/dr-decode/src/profile.rs#L153), [`core/dr-decode/src/profile.rs:1`](../../core/dr-decode/src/profile.rs#L1), [`core/dr-decode/src/profile.rs:237`](../../core/dr-decode/src/profile.rs#L237), [`core/dr-decode/src/profile.rs:288`](../../core/dr-decode/src/profile.rs#L288), [`core/dr-decode/src/profile.rs:345`](../../core/dr-decode/src/profile.rs#L345), [`core/dr-decode/src/profile.rs:475`](../../core/dr-decode/src/profile.rs#L475), [`core/dr-decode/src/profile.rs:509`](../../core/dr-decode/src/profile.rs#L509), [`core/dr-decode/src/profile.rs:680`](../../core/dr-decode/src/profile.rs#L680), [`core/dr-gpu/src/adjust.rs:523`](../../core/dr-gpu/src/adjust.rs#L523), [`core/dr-gpu/src/adjust.rs:536`](../../core/dr-gpu/src/adjust.rs#L536), [`core/dr-gpu/src/adjust.rs:74`](../../core/dr-gpu/src/adjust.rs#L74), [`core/dr-gpu/src/demosaic.rs:110`](../../core/dr-gpu/src/demosaic.rs#L110), [`core/dr-gpu/src/demosaic.rs:215`](../../core/dr-gpu/src/demosaic.rs#L215), [`core/dr-gpu/tests/camera_profile.rs:1`](../../core/dr-gpu/tests/camera_profile.rs#L1), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2459`](../../core/dr-pipeline/src/operation.rs#L2459), [`core/dr-pipeline/src/operation.rs:2483`](../../core/dr-pipeline/src/operation.rs#L2483), [`core/dr-pipeline/src/operation.rs:273`](../../core/dr-pipeline/src/operation.rs#L273), [`core/dr-pipeline/src/operation.rs:349`](../../core/dr-pipeline/src/operation.rs#L349), [`core/dr-pipeline/src/operation.rs:369`](../../core/dr-pipeline/src/operation.rs#L369), [`core/dr-pipeline/src/operation.rs:443`](../../core/dr-pipeline/src/operation.rs#L443), [`core/dr-pipeline/src/operation.rs:463`](../../core/dr-pipeline/src/operation.rs#L463), [`core/dr-pipeline/src/ops/camera_profile.rs:1`](../../core/dr-pipeline/src/ops/camera_profile.rs#L1), [`core/dr-pipeline/src/ops/camera_profile.rs:355`](../../core/dr-pipeline/src/ops/camera_profile.rs#L355), [`core/dr-pipeline/src/ops/camera_profile.rs:381`](../../core/dr-pipeline/src/ops/camera_profile.rs#L381), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227), [`core/dr-types/src/hue_sat.rs:1`](../../core/dr-types/src/hue_sat.rs#L1), [`core/dr-types/src/tone.rs:157`](../../core/dr-types/src/tone.rs#L157), [`core/dr-types/src/tone.rs:1`](../../core/dr-types/src/tone.rs#L1), [`ui/dr-ui/src/develop/session.rs:600`](../../ui/dr-ui/src/develop/session.rs#L600), [`ui/dr-ui/src/develop/session.rs:613`](../../ui/dr-ui/src/develop/session.rs#L613), [`ui/dr-ui/src/develop/session.rs:648`](../../ui/dr-ui/src/develop/session.rs#L648), [`ui/dr-ui/src/develop/session.rs:657`](../../ui/dr-ui/src/develop/session.rs#L657), [`ui/dr-ui/src/develop/session.rs:73`](../../ui/dr-ui/src/develop/session.rs#L73), [`ui/dr-ui/src/develop/session.rs:849`](../../ui/dr-ui/src/develop/session.rs#L849), [`ui/dr-ui/src/develop/session.rs:893`](../../ui/dr-ui/src/develop/session.rs#L893), [`ui/dr-ui/src/lib.rs:1208`](../../ui/dr-ui/src/lib.rs#L1208), [`ui/dr-ui/src/lib.rs:1506`](../../ui/dr-ui/src/lib.rs#L1506), [`ui/dr-ui/src/lib.rs:1524`](../../ui/dr-ui/src/lib.rs#L1524), [`ui/dr-ui/src/lib.rs:330`](../../ui/dr-ui/src/lib.rs#L330), [`ui/dr-ui/ui/develop.slint:386`](../../ui/dr-ui/ui/develop.slint#L386), [`ui/dr-ui/ui/develop.slint:395`](../../ui/dr-ui/ui/develop.slint#L395) | +| FR-DEV-3e | [`core/dr-decode/src/dcp.rs:132`](../../core/dr-decode/src/dcp.rs#L132), [`core/dr-decode/src/dcp.rs:163`](../../core/dr-decode/src/dcp.rs#L163), [`core/dr-decode/src/dcp.rs:182`](../../core/dr-decode/src/dcp.rs#L182), [`core/dr-decode/src/dcp.rs:1`](../../core/dr-decode/src/dcp.rs#L1), [`core/dr-decode/src/dcp.rs:205`](../../core/dr-decode/src/dcp.rs#L205), [`core/dr-decode/src/dcp.rs:240`](../../core/dr-decode/src/dcp.rs#L240), [`core/dr-decode/src/dcp.rs:431`](../../core/dr-decode/src/dcp.rs#L431), [`core/dr-decode/src/dcp.rs:482`](../../core/dr-decode/src/dcp.rs#L482), [`core/dr-decode/src/dcp.rs:493`](../../core/dr-decode/src/dcp.rs#L493), [`core/dr-decode/src/dcp.rs:526`](../../core/dr-decode/src/dcp.rs#L526), [`core/dr-decode/src/dcp.rs:546`](../../core/dr-decode/src/dcp.rs#L546), [`core/dr-decode/src/dcp.rs:559`](../../core/dr-decode/src/dcp.rs#L559), [`core/dr-decode/src/dcp.rs:79`](../../core/dr-decode/src/dcp.rs#L79), [`core/dr-decode/src/lib.rs:126`](../../core/dr-decode/src/lib.rs#L126), [`core/dr-decode/src/lib.rs:141`](../../core/dr-decode/src/lib.rs#L141), [`core/dr-decode/src/lib.rs:150`](../../core/dr-decode/src/lib.rs#L150), [`core/dr-decode/src/lib.rs:601`](../../core/dr-decode/src/lib.rs#L601), [`core/dr-decode/src/lib.rs:799`](../../core/dr-decode/src/lib.rs#L799), [`core/dr-decode/src/lib.rs:839`](../../core/dr-decode/src/lib.rs#L839), [`core/dr-decode/src/profile.rs:104`](../../core/dr-decode/src/profile.rs#L104), [`core/dr-decode/src/profile.rs:153`](../../core/dr-decode/src/profile.rs#L153), [`core/dr-decode/src/profile.rs:1`](../../core/dr-decode/src/profile.rs#L1), [`core/dr-decode/src/profile.rs:237`](../../core/dr-decode/src/profile.rs#L237), [`core/dr-decode/src/profile.rs:288`](../../core/dr-decode/src/profile.rs#L288), [`core/dr-decode/src/profile.rs:345`](../../core/dr-decode/src/profile.rs#L345), [`core/dr-decode/src/profile.rs:475`](../../core/dr-decode/src/profile.rs#L475), [`core/dr-decode/src/profile.rs:509`](../../core/dr-decode/src/profile.rs#L509), [`core/dr-decode/src/profile.rs:680`](../../core/dr-decode/src/profile.rs#L680), [`core/dr-gpu/src/adjust.rs:523`](../../core/dr-gpu/src/adjust.rs#L523), [`core/dr-gpu/src/adjust.rs:536`](../../core/dr-gpu/src/adjust.rs#L536), [`core/dr-gpu/src/adjust.rs:74`](../../core/dr-gpu/src/adjust.rs#L74), [`core/dr-gpu/src/demosaic.rs:110`](../../core/dr-gpu/src/demosaic.rs#L110), [`core/dr-gpu/src/demosaic.rs:215`](../../core/dr-gpu/src/demosaic.rs#L215), [`core/dr-gpu/src/demosaic.rs:592`](../../core/dr-gpu/src/demosaic.rs#L592), [`core/dr-gpu/tests/camera_profile.rs:1`](../../core/dr-gpu/tests/camera_profile.rs#L1), [`core/dr-pipeline/src/camera_raw.rs:1`](../../core/dr-pipeline/src/camera_raw.rs#L1), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2459`](../../core/dr-pipeline/src/operation.rs#L2459), [`core/dr-pipeline/src/operation.rs:2483`](../../core/dr-pipeline/src/operation.rs#L2483), [`core/dr-pipeline/src/operation.rs:273`](../../core/dr-pipeline/src/operation.rs#L273), [`core/dr-pipeline/src/operation.rs:349`](../../core/dr-pipeline/src/operation.rs#L349), [`core/dr-pipeline/src/operation.rs:369`](../../core/dr-pipeline/src/operation.rs#L369), [`core/dr-pipeline/src/operation.rs:443`](../../core/dr-pipeline/src/operation.rs#L443), [`core/dr-pipeline/src/operation.rs:463`](../../core/dr-pipeline/src/operation.rs#L463), [`core/dr-pipeline/src/ops/camera_profile.rs:1`](../../core/dr-pipeline/src/ops/camera_profile.rs#L1), [`core/dr-pipeline/src/ops/camera_profile.rs:384`](../../core/dr-pipeline/src/ops/camera_profile.rs#L384), [`core/dr-pipeline/src/ops/camera_profile.rs:421`](../../core/dr-pipeline/src/ops/camera_profile.rs#L421), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227), [`core/dr-types/src/hue_sat.rs:1`](../../core/dr-types/src/hue_sat.rs#L1), [`core/dr-types/src/tone.rs:157`](../../core/dr-types/src/tone.rs#L157), [`core/dr-types/src/tone.rs:1`](../../core/dr-types/src/tone.rs#L1), [`ui/dr-ui/src/develop/session.rs:600`](../../ui/dr-ui/src/develop/session.rs#L600), [`ui/dr-ui/src/develop/session.rs:613`](../../ui/dr-ui/src/develop/session.rs#L613), [`ui/dr-ui/src/develop/session.rs:648`](../../ui/dr-ui/src/develop/session.rs#L648), [`ui/dr-ui/src/develop/session.rs:657`](../../ui/dr-ui/src/develop/session.rs#L657), [`ui/dr-ui/src/develop/session.rs:73`](../../ui/dr-ui/src/develop/session.rs#L73), [`ui/dr-ui/src/develop/session.rs:849`](../../ui/dr-ui/src/develop/session.rs#L849), [`ui/dr-ui/src/develop/session.rs:893`](../../ui/dr-ui/src/develop/session.rs#L893), [`ui/dr-ui/src/lib.rs:1208`](../../ui/dr-ui/src/lib.rs#L1208), [`ui/dr-ui/src/lib.rs:1506`](../../ui/dr-ui/src/lib.rs#L1506), [`ui/dr-ui/src/lib.rs:1524`](../../ui/dr-ui/src/lib.rs#L1524), [`ui/dr-ui/src/lib.rs:330`](../../ui/dr-ui/src/lib.rs#L330), [`ui/dr-ui/ui/develop.slint:386`](../../ui/dr-ui/ui/develop.slint#L386), [`ui/dr-ui/ui/develop.slint:395`](../../ui/dr-ui/ui/develop.slint#L395) | | FR-DEV-3f | [`core/dr-film/src/bake.rs:161`](../../core/dr-film/src/bake.rs#L161), [`core/dr-film/src/bake.rs:384`](../../core/dr-film/src/bake.rs#L384), [`core/dr-film/src/bake.rs:52`](../../core/dr-film/src/bake.rs#L52), [`core/dr-film/src/bake.rs:662`](../../core/dr-film/src/bake.rs#L662), [`core/dr-film/src/bake.rs:689`](../../core/dr-film/src/bake.rs#L689), [`core/dr-film/src/bake.rs:710`](../../core/dr-film/src/bake.rs#L710), [`core/dr-film/src/bake.rs:747`](../../core/dr-film/src/bake.rs#L747), [`core/dr-film/src/bake.rs:95`](../../core/dr-film/src/bake.rs#L95), [`core/dr-film/src/boolean_grain.rs:1`](../../core/dr-film/src/boolean_grain.rs#L1), [`core/dr-film/src/boolean_grain.rs:78`](../../core/dr-film/src/boolean_grain.rs#L78), [`core/dr-film/src/grain.rs:140`](../../core/dr-film/src/grain.rs#L140), [`core/dr-film/src/grain.rs:1`](../../core/dr-film/src/grain.rs#L1), [`core/dr-film/src/grain.rs:302`](../../core/dr-film/src/grain.rs#L302), [`core/dr-film/src/grain.rs:79`](../../core/dr-film/src/grain.rs#L79), [`core/dr-film/src/lib.rs:160`](../../core/dr-film/src/lib.rs#L160), [`core/dr-film/src/lib.rs:1`](../../core/dr-film/src/lib.rs#L1), [`core/dr-film/src/profile.rs:100`](../../core/dr-film/src/profile.rs#L100), [`core/dr-film/src/profile.rs:142`](../../core/dr-film/src/profile.rs#L142), [`core/dr-film/src/profile.rs:182`](../../core/dr-film/src/profile.rs#L182), [`core/dr-film/src/profile.rs:259`](../../core/dr-film/src/profile.rs#L259), [`core/dr-film/src/profile.rs:502`](../../core/dr-film/src/profile.rs#L502), [`core/dr-film/src/profile.rs:73`](../../core/dr-film/src/profile.rs#L73), [`core/dr-gpu/src/adjust.rs:152`](../../core/dr-gpu/src/adjust.rs#L152), [`core/dr-gpu/src/adjust.rs:422`](../../core/dr-gpu/src/adjust.rs#L422), [`core/dr-gpu/src/adjust.rs:632`](../../core/dr-gpu/src/adjust.rs#L632), [`core/dr-gpu/src/adjust.rs:67`](../../core/dr-gpu/src/adjust.rs#L67), [`core/dr-gpu/src/adjust.rs:765`](../../core/dr-gpu/src/adjust.rs#L765), [`core/dr-gpu/tests/film_sim.rs:1`](../../core/dr-gpu/tests/film_sim.rs#L1), [`core/dr-gpu/tests/film_sim.rs:215`](../../core/dr-gpu/tests/film_sim.rs#L215), [`core/dr-gpu/tests/film_sim.rs:349`](../../core/dr-gpu/tests/film_sim.rs#L349), [`core/dr-gpu/tests/film_sim.rs:388`](../../core/dr-gpu/tests/film_sim.rs#L388), [`core/dr-gpu/tests/film_sim.rs:417`](../../core/dr-gpu/tests/film_sim.rs#L417), [`core/dr-gpu/tests/film_sim.rs:457`](../../core/dr-gpu/tests/film_sim.rs#L457), [`core/dr-pipeline/src/graph.rs:110`](../../core/dr-pipeline/src/graph.rs#L110), [`core/dr-pipeline/src/graph.rs:187`](../../core/dr-pipeline/src/graph.rs#L187), [`core/dr-pipeline/src/graph.rs:687`](../../core/dr-pipeline/src/graph.rs#L687), [`core/dr-pipeline/src/mask.rs:2452`](../../core/dr-pipeline/src/mask.rs#L2452), [`core/dr-pipeline/src/mask.rs:2485`](../../core/dr-pipeline/src/mask.rs#L2485), [`core/dr-pipeline/src/operation.rs:1086`](../../core/dr-pipeline/src/operation.rs#L1086), [`core/dr-pipeline/src/operation.rs:1436`](../../core/dr-pipeline/src/operation.rs#L1436), [`core/dr-pipeline/src/operation.rs:1670`](../../core/dr-pipeline/src/operation.rs#L1670), [`core/dr-pipeline/src/operation.rs:1698`](../../core/dr-pipeline/src/operation.rs#L1698), [`core/dr-pipeline/src/operation.rs:1750`](../../core/dr-pipeline/src/operation.rs#L1750), [`core/dr-pipeline/src/operation.rs:2377`](../../core/dr-pipeline/src/operation.rs#L2377), [`core/dr-pipeline/src/operation.rs:309`](../../core/dr-pipeline/src/operation.rs#L309), [`core/dr-pipeline/src/operation.rs:323`](../../core/dr-pipeline/src/operation.rs#L323), [`core/dr-pipeline/src/operation.rs:334`](../../core/dr-pipeline/src/operation.rs#L334), [`core/dr-pipeline/src/operation.rs:349`](../../core/dr-pipeline/src/operation.rs#L349), [`core/dr-pipeline/src/ops/film_sim.rs:129`](../../core/dr-pipeline/src/ops/film_sim.rs#L129), [`core/dr-pipeline/src/ops/film_sim.rs:134`](../../core/dr-pipeline/src/ops/film_sim.rs#L134), [`core/dr-pipeline/src/ops/film_sim.rs:186`](../../core/dr-pipeline/src/ops/film_sim.rs#L186), [`core/dr-pipeline/src/ops/film_sim.rs:1`](../../core/dr-pipeline/src/ops/film_sim.rs#L1), [`core/dr-pipeline/src/ops/film_sim.rs:233`](../../core/dr-pipeline/src/ops/film_sim.rs#L233), [`core/dr-pipeline/src/ops/film_sim.rs:315`](../../core/dr-pipeline/src/ops/film_sim.rs#L315), [`core/dr-pipeline/src/ops/film_sim.rs:329`](../../core/dr-pipeline/src/ops/film_sim.rs#L329), [`core/dr-pipeline/src/ops/film_sim.rs:438`](../../core/dr-pipeline/src/ops/film_sim.rs#L438), [`core/dr-pipeline/src/ops/film_sim.rs:48`](../../core/dr-pipeline/src/ops/film_sim.rs#L48), [`core/dr-pipeline/src/ops/film_sim.rs:736`](../../core/dr-pipeline/src/ops/film_sim.rs#L736), [`core/dr-pipeline/src/preset.rs:1293`](../../core/dr-pipeline/src/preset.rs#L1293), [`core/dr-pipeline/src/preset.rs:1303`](../../core/dr-pipeline/src/preset.rs#L1303), [`core/dr-pipeline/src/preset.rs:1312`](../../core/dr-pipeline/src/preset.rs#L1312), [`core/dr-pipeline/src/preset.rs:1328`](../../core/dr-pipeline/src/preset.rs#L1328), [`core/dr-pipeline/src/preset.rs:1340`](../../core/dr-pipeline/src/preset.rs#L1340), [`core/dr-pipeline/src/preset.rs:1356`](../../core/dr-pipeline/src/preset.rs#L1356), [`core/dr-pipeline/src/preset.rs:1529`](../../core/dr-pipeline/src/preset.rs#L1529), [`core/dr-pipeline/src/preset.rs:1544`](../../core/dr-pipeline/src/preset.rs#L1544), [`core/dr-pipeline/src/preset.rs:248`](../../core/dr-pipeline/src/preset.rs#L248), [`core/dr-pipeline/src/preset.rs:689`](../../core/dr-pipeline/src/preset.rs#L689), [`core/dr-pipeline/src/preset.rs:778`](../../core/dr-pipeline/src/preset.rs#L778), [`core/dr-pipeline/src/sidecar.rs:1077`](../../core/dr-pipeline/src/sidecar.rs#L1077), [`core/dr-pipeline/src/sidecar.rs:133`](../../core/dr-pipeline/src/sidecar.rs#L133), [`core/dr-pipeline/src/sidecar.rs:217`](../../core/dr-pipeline/src/sidecar.rs#L217), [`core/dr-pipeline/src/sidecar.rs:2724`](../../core/dr-pipeline/src/sidecar.rs#L2724), [`core/dr-pipeline/src/sidecar.rs:2800`](../../core/dr-pipeline/src/sidecar.rs#L2800), [`core/dr-pipeline/src/sidecar.rs:595`](../../core/dr-pipeline/src/sidecar.rs#L595), [`core/dr-pipeline/src/sidecar.rs:898`](../../core/dr-pipeline/src/sidecar.rs#L898), [`core/dr-pipeline/src/state.rs:100`](../../core/dr-pipeline/src/state.rs#L100), [`core/dr-pipeline/src/state.rs:115`](../../core/dr-pipeline/src/state.rs#L115), [`core/dr-pipeline/src/state.rs:60`](../../core/dr-pipeline/src/state.rs#L60), [`ui/dr-ui/src/develop/render.rs:1002`](../../ui/dr-ui/src/develop/render.rs#L1002), [`ui/dr-ui/src/develop/render.rs:1053`](../../ui/dr-ui/src/develop/render.rs#L1053), [`ui/dr-ui/src/develop/render.rs:1079`](../../ui/dr-ui/src/develop/render.rs#L1079), [`ui/dr-ui/src/develop/render.rs:1402`](../../ui/dr-ui/src/develop/render.rs#L1402), [`ui/dr-ui/src/develop/render.rs:1442`](../../ui/dr-ui/src/develop/render.rs#L1442), [`ui/dr-ui/src/develop/render.rs:1477`](../../ui/dr-ui/src/develop/render.rs#L1477), [`ui/dr-ui/src/develop/render.rs:830`](../../ui/dr-ui/src/develop/render.rs#L830), [`ui/dr-ui/src/develop/render.rs:847`](../../ui/dr-ui/src/develop/render.rs#L847), [`ui/dr-ui/src/develop/render.rs:859`](../../ui/dr-ui/src/develop/render.rs#L859), [`ui/dr-ui/src/develop/render.rs:897`](../../ui/dr-ui/src/develop/render.rs#L897), [`ui/dr-ui/src/develop/render.rs:934`](../../ui/dr-ui/src/develop/render.rs#L934), [`ui/dr-ui/src/develop/render.rs:945`](../../ui/dr-ui/src/develop/render.rs#L945), [`ui/dr-ui/src/develop/session.rs:727`](../../ui/dr-ui/src/develop/session.rs#L727), [`ui/dr-ui/src/develop/session.rs:747`](../../ui/dr-ui/src/develop/session.rs#L747), [`ui/dr-ui/src/develop/tabs.rs:80`](../../ui/dr-ui/src/develop/tabs.rs#L80), [`ui/dr-ui/src/develop_ui.rs:534`](../../ui/dr-ui/src/develop_ui.rs#L534), [`ui/dr-ui/src/lib.rs:881`](../../ui/dr-ui/src/lib.rs#L881), [`ui/dr-ui/src/lib.rs:946`](../../ui/dr-ui/src/lib.rs#L946), [`ui/dr-ui/src/library/sidecar.rs:325`](../../ui/dr-ui/src/library/sidecar.rs#L325), [`ui/dr-ui/src/library/sidecar.rs:50`](../../ui/dr-ui/src/library/sidecar.rs#L50), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:602`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L602), [`ui/dr-ui/src/presets.rs:1892`](../../ui/dr-ui/src/presets.rs#L1892), [`ui/dr-ui/src/presets.rs:422`](../../ui/dr-ui/src/presets.rs#L422), [`ui/dr-ui/tests/film_list_reaches_every_stock.rs:1`](../../ui/dr-ui/tests/film_list_reaches_every_stock.rs#L1), [`ui/dr-ui/ui/adjust.slint:1071`](../../ui/dr-ui/ui/adjust.slint#L1071), [`ui/dr-ui/ui/adjust.slint:1081`](../../ui/dr-ui/ui/adjust.slint#L1081), [`ui/dr-ui/ui/adjust.slint:1298`](../../ui/dr-ui/ui/adjust.slint#L1298) | -| FR-DEV-3g | [`core/dr-decode/src/lib.rs:553`](../../core/dr-decode/src/lib.rs#L553), [`core/dr-decode/src/profile.rs:743`](../../core/dr-decode/src/profile.rs#L743), [`core/dr-denoise/src/lib.rs:1`](../../core/dr-denoise/src/lib.rs#L1), [`core/dr-denoise/src/noise.rs:1`](../../core/dr-denoise/src/noise.rs#L1), [`core/dr-denoise/src/onnx.rs:1`](../../core/dr-denoise/src/onnx.rs#L1), [`core/dr-denoise/src/tile.rs:1`](../../core/dr-denoise/src/tile.rs#L1), [`core/dr-gpu/src/demosaic.rs:1046`](../../core/dr-gpu/src/demosaic.rs#L1046), [`core/dr-gpu/src/demosaic.rs:349`](../../core/dr-gpu/src/demosaic.rs#L349), [`core/dr-gpu/src/grain.rs:1`](../../core/dr-gpu/src/grain.rs#L1), [`core/dr-gpu/tests/grain.rs:1`](../../core/dr-gpu/tests/grain.rs#L1), [`core/dr-pipeline/src/graph.rs:173`](../../core/dr-pipeline/src/graph.rs#L173), [`core/dr-pipeline/src/graph.rs:417`](../../core/dr-pipeline/src/graph.rs#L417), [`core/dr-pipeline/src/graph.rs:423`](../../core/dr-pipeline/src/graph.rs#L423), [`core/dr-pipeline/src/graph.rs:431`](../../core/dr-pipeline/src/graph.rs#L431), [`core/dr-pipeline/src/graph.rs:619`](../../core/dr-pipeline/src/graph.rs#L619), [`core/dr-pipeline/src/learned_denoise.rs:1`](../../core/dr-pipeline/src/learned_denoise.rs#L1), [`ui/dr-ui/src/activity.rs:86`](../../ui/dr-ui/src/activity.rs#L86), [`ui/dr-ui/src/develop/denoise.rs:1`](../../ui/dr-ui/src/develop/denoise.rs#L1), [`ui/dr-ui/src/develop/render.rs:238`](../../ui/dr-ui/src/develop/render.rs#L238), [`ui/dr-ui/src/develop/render.rs:712`](../../ui/dr-ui/src/develop/render.rs#L712), [`ui/dr-ui/src/develop/session.rs:121`](../../ui/dr-ui/src/develop/session.rs#L121), [`ui/dr-ui/src/develop/session.rs:384`](../../ui/dr-ui/src/develop/session.rs#L384), [`ui/dr-ui/src/develop_ui.rs:139`](../../ui/dr-ui/src/develop_ui.rs#L139), [`ui/dr-ui/src/lib.rs:327`](../../ui/dr-ui/src/lib.rs#L327), [`ui/dr-ui/src/library/paths.rs:378`](../../ui/dr-ui/src/library/paths.rs#L378), [`ui/dr-ui/src/library/paths.rs:382`](../../ui/dr-ui/src/library/paths.rs#L382) | +| FR-DEV-3g | [`core/dr-decode/src/lib.rs:553`](../../core/dr-decode/src/lib.rs#L553), [`core/dr-decode/src/profile.rs:743`](../../core/dr-decode/src/profile.rs#L743), [`core/dr-denoise/src/lib.rs:1`](../../core/dr-denoise/src/lib.rs#L1), [`core/dr-denoise/src/noise.rs:1`](../../core/dr-denoise/src/noise.rs#L1), [`core/dr-denoise/src/onnx.rs:1`](../../core/dr-denoise/src/onnx.rs#L1), [`core/dr-denoise/src/tile.rs:1`](../../core/dr-denoise/src/tile.rs#L1), [`core/dr-gpu/src/demosaic.rs:1063`](../../core/dr-gpu/src/demosaic.rs#L1063), [`core/dr-gpu/src/demosaic.rs:349`](../../core/dr-gpu/src/demosaic.rs#L349), [`core/dr-gpu/src/grain.rs:1`](../../core/dr-gpu/src/grain.rs#L1), [`core/dr-gpu/tests/grain.rs:1`](../../core/dr-gpu/tests/grain.rs#L1), [`core/dr-pipeline/src/graph.rs:173`](../../core/dr-pipeline/src/graph.rs#L173), [`core/dr-pipeline/src/graph.rs:417`](../../core/dr-pipeline/src/graph.rs#L417), [`core/dr-pipeline/src/graph.rs:423`](../../core/dr-pipeline/src/graph.rs#L423), [`core/dr-pipeline/src/graph.rs:431`](../../core/dr-pipeline/src/graph.rs#L431), [`core/dr-pipeline/src/graph.rs:619`](../../core/dr-pipeline/src/graph.rs#L619), [`core/dr-pipeline/src/learned_denoise.rs:1`](../../core/dr-pipeline/src/learned_denoise.rs#L1), [`ui/dr-ui/src/activity.rs:86`](../../ui/dr-ui/src/activity.rs#L86), [`ui/dr-ui/src/develop/denoise.rs:1`](../../ui/dr-ui/src/develop/denoise.rs#L1), [`ui/dr-ui/src/develop/render.rs:238`](../../ui/dr-ui/src/develop/render.rs#L238), [`ui/dr-ui/src/develop/render.rs:712`](../../ui/dr-ui/src/develop/render.rs#L712), [`ui/dr-ui/src/develop/session.rs:121`](../../ui/dr-ui/src/develop/session.rs#L121), [`ui/dr-ui/src/develop/session.rs:384`](../../ui/dr-ui/src/develop/session.rs#L384), [`ui/dr-ui/src/develop_ui.rs:139`](../../ui/dr-ui/src/develop_ui.rs#L139), [`ui/dr-ui/src/lib.rs:327`](../../ui/dr-ui/src/lib.rs#L327), [`ui/dr-ui/src/library/paths.rs:378`](../../ui/dr-ui/src/library/paths.rs#L378), [`ui/dr-ui/src/library/paths.rs:382`](../../ui/dr-ui/src/library/paths.rs#L382) | | FR-DEV-3h | [`core/dr-decode/src/lib.rs:451`](../../core/dr-decode/src/lib.rs#L451), [`core/dr-decode/src/preview.rs:29`](../../core/dr-decode/src/preview.rs#L29), [`core/dr-pipeline/src/framing.rs:1492`](../../core/dr-pipeline/src/framing.rs#L1492), [`core/dr-pipeline/src/framing.rs:499`](../../core/dr-pipeline/src/framing.rs#L499), [`core/dr-pipeline/src/framing.rs:717`](../../core/dr-pipeline/src/framing.rs#L717), [`core/dr-types/src/lib.rs:342`](../../core/dr-types/src/lib.rs#L342), [`core/dr-types/src/lib.rs:450`](../../core/dr-types/src/lib.rs#L450), [`core/dr-types/src/lib.rs:462`](../../core/dr-types/src/lib.rs#L462), [`core/dr-types/src/lib.rs:478`](../../core/dr-types/src/lib.rs#L478), [`ui/dr-ui/src/develop/masks.rs:280`](../../ui/dr-ui/src/develop/masks.rs#L280), [`ui/dr-ui/src/develop/segmentation.rs:114`](../../ui/dr-ui/src/develop/segmentation.rs#L114), [`ui/dr-ui/src/segmentation.rs:499`](../../ui/dr-ui/src/segmentation.rs#L499) | | FR-DEV-3i | [`core/dr-pipeline/src/mask.rs:558`](../../core/dr-pipeline/src/mask.rs#L558), [`core/dr-segment/src/lib.rs:1`](../../core/dr-segment/src/lib.rs#L1), [`ui/dr-ui/src/segmentation.rs:1`](../../ui/dr-ui/src/segmentation.rs#L1) | -| FR-DEV-3j | [`core/dr-gpu/src/adjust.rs:1301`](../../core/dr-gpu/src/adjust.rs#L1301), [`core/dr-gpu/src/adjust.rs:1539`](../../core/dr-gpu/src/adjust.rs#L1539), [`core/dr-gpu/src/adjust.rs:3396`](../../core/dr-gpu/src/adjust.rs#L3396), [`core/dr-gpu/tests/scene_referred.rs:145`](../../core/dr-gpu/tests/scene_referred.rs#L145), [`core/dr-gpu/tests/scene_referred.rs:1`](../../core/dr-gpu/tests/scene_referred.rs#L1), [`core/dr-gpu/tests/view_transform.rs:116`](../../core/dr-gpu/tests/view_transform.rs#L116), [`core/dr-gpu/tests/view_transform.rs:154`](../../core/dr-gpu/tests/view_transform.rs#L154), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:67`](../../core/dr-gpu/tests/view_transform.rs#L67), [`core/dr-gpu/tests/view_transform.rs:90`](../../core/dr-gpu/tests/view_transform.rs#L90), [`core/dr-pipeline/src/operation.rs:1414`](../../core/dr-pipeline/src/operation.rs#L1414), [`core/dr-pipeline/src/operation.rs:2377`](../../core/dr-pipeline/src/operation.rs#L2377), [`core/dr-pipeline/src/operation.rs:2493`](../../core/dr-pipeline/src/operation.rs#L2493), [`core/dr-pipeline/src/operation.rs:2510`](../../core/dr-pipeline/src/operation.rs#L2510), [`core/dr-pipeline/src/operation.rs:2700`](../../core/dr-pipeline/src/operation.rs#L2700), [`core/dr-pipeline/src/operation.rs:2738`](../../core/dr-pipeline/src/operation.rs#L2738), [`core/dr-pipeline/src/operation.rs:580`](../../core/dr-pipeline/src/operation.rs#L580), [`core/dr-pipeline/src/operation.rs:880`](../../core/dr-pipeline/src/operation.rs#L880), [`core/dr-pipeline/src/operation.rs:930`](../../core/dr-pipeline/src/operation.rs#L930), [`core/dr-pipeline/src/ops/film_sim.rs:315`](../../core/dr-pipeline/src/ops/film_sim.rs#L315), [`core/dr-pipeline/src/ops/view_transform.rs:168`](../../core/dr-pipeline/src/ops/view_transform.rs#L168), [`core/dr-pipeline/src/ops/view_transform.rs:1`](../../core/dr-pipeline/src/ops/view_transform.rs#L1), [`core/dr-pipeline/src/view.rs:184`](../../core/dr-pipeline/src/view.rs#L184), [`core/dr-pipeline/src/view.rs:197`](../../core/dr-pipeline/src/view.rs#L197), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227), [`core/dr-pipeline/src/view.rs:241`](../../core/dr-pipeline/src/view.rs#L241), [`core/dr-pipeline/src/view.rs:252`](../../core/dr-pipeline/src/view.rs#L252), [`core/dr-types/src/tone.rs:1`](../../core/dr-types/src/tone.rs#L1) | +| FR-DEV-3j | [`core/dr-gpu/src/adjust.rs:1301`](../../core/dr-gpu/src/adjust.rs#L1301), [`core/dr-gpu/src/adjust.rs:1539`](../../core/dr-gpu/src/adjust.rs#L1539), [`core/dr-gpu/src/adjust.rs:3396`](../../core/dr-gpu/src/adjust.rs#L3396), [`core/dr-gpu/tests/camera_profile.rs:197`](../../core/dr-gpu/tests/camera_profile.rs#L197), [`core/dr-gpu/tests/scene_referred.rs:145`](../../core/dr-gpu/tests/scene_referred.rs#L145), [`core/dr-gpu/tests/scene_referred.rs:1`](../../core/dr-gpu/tests/scene_referred.rs#L1), [`core/dr-gpu/tests/view_transform.rs:101`](../../core/dr-gpu/tests/view_transform.rs#L101), [`core/dr-gpu/tests/view_transform.rs:124`](../../core/dr-gpu/tests/view_transform.rs#L124), [`core/dr-gpu/tests/view_transform.rs:150`](../../core/dr-gpu/tests/view_transform.rs#L150), [`core/dr-gpu/tests/view_transform.rs:188`](../../core/dr-gpu/tests/view_transform.rs#L188), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:63`](../../core/dr-gpu/tests/view_transform.rs#L63), [`core/dr-pipeline/src/camera_raw.rs:1`](../../core/dr-pipeline/src/camera_raw.rs#L1), [`core/dr-pipeline/src/camera_raw.rs:52`](../../core/dr-pipeline/src/camera_raw.rs#L52), [`core/dr-pipeline/src/operation.rs:1414`](../../core/dr-pipeline/src/operation.rs#L1414), [`core/dr-pipeline/src/operation.rs:2377`](../../core/dr-pipeline/src/operation.rs#L2377), [`core/dr-pipeline/src/operation.rs:2493`](../../core/dr-pipeline/src/operation.rs#L2493), [`core/dr-pipeline/src/operation.rs:2510`](../../core/dr-pipeline/src/operation.rs#L2510), [`core/dr-pipeline/src/operation.rs:2700`](../../core/dr-pipeline/src/operation.rs#L2700), [`core/dr-pipeline/src/operation.rs:2738`](../../core/dr-pipeline/src/operation.rs#L2738), [`core/dr-pipeline/src/operation.rs:580`](../../core/dr-pipeline/src/operation.rs#L580), [`core/dr-pipeline/src/operation.rs:880`](../../core/dr-pipeline/src/operation.rs#L880), [`core/dr-pipeline/src/operation.rs:930`](../../core/dr-pipeline/src/operation.rs#L930), [`core/dr-pipeline/src/ops/camera_profile.rs:384`](../../core/dr-pipeline/src/ops/camera_profile.rs#L384), [`core/dr-pipeline/src/ops/film_sim.rs:315`](../../core/dr-pipeline/src/ops/film_sim.rs#L315), [`core/dr-pipeline/src/ops/view_transform.rs:1`](../../core/dr-pipeline/src/ops/view_transform.rs#L1), [`core/dr-pipeline/src/ops/view_transform.rs:218`](../../core/dr-pipeline/src/ops/view_transform.rs#L218), [`core/dr-pipeline/src/ops/view_transform.rs:36`](../../core/dr-pipeline/src/ops/view_transform.rs#L36), [`core/dr-pipeline/src/view.rs:184`](../../core/dr-pipeline/src/view.rs#L184), [`core/dr-pipeline/src/view.rs:197`](../../core/dr-pipeline/src/view.rs#L197), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227), [`core/dr-pipeline/src/view.rs:241`](../../core/dr-pipeline/src/view.rs#L241), [`core/dr-pipeline/src/view.rs:252`](../../core/dr-pipeline/src/view.rs#L252), [`core/dr-types/src/tone.rs:1`](../../core/dr-types/src/tone.rs#L1) | | FR-DEV-4 | [`core/dr-gpu/src/adjust.rs:1107`](../../core/dr-gpu/src/adjust.rs#L1107), [`core/dr-gpu/src/lib.rs:370`](../../core/dr-gpu/src/lib.rs#L370), [`ui/dr-ui/ui/crop.slint:1`](../../ui/dr-ui/ui/crop.slint#L1) | | FR-DEV-5 | [`core/dr-pipeline/src/graph.rs:1597`](../../core/dr-pipeline/src/graph.rs#L1597), [`core/dr-pipeline/src/graph.rs:708`](../../core/dr-pipeline/src/graph.rs#L708), [`core/dr-pipeline/src/graph.rs:768`](../../core/dr-pipeline/src/graph.rs#L768), [`core/dr-pipeline/src/history.rs:102`](../../core/dr-pipeline/src/history.rs#L102), [`core/dr-pipeline/src/history.rs:110`](../../core/dr-pipeline/src/history.rs#L110), [`core/dr-pipeline/src/history.rs:127`](../../core/dr-pipeline/src/history.rs#L127), [`core/dr-pipeline/src/history.rs:184`](../../core/dr-pipeline/src/history.rs#L184), [`core/dr-pipeline/src/history.rs:1`](../../core/dr-pipeline/src/history.rs#L1), [`core/dr-pipeline/src/history.rs:214`](../../core/dr-pipeline/src/history.rs#L214), [`core/dr-pipeline/src/history.rs:234`](../../core/dr-pipeline/src/history.rs#L234), [`core/dr-pipeline/src/history.rs:293`](../../core/dr-pipeline/src/history.rs#L293), [`core/dr-pipeline/src/history.rs:479`](../../core/dr-pipeline/src/history.rs#L479), [`core/dr-pipeline/src/history.rs:489`](../../core/dr-pipeline/src/history.rs#L489), [`core/dr-pipeline/src/history.rs:499`](../../core/dr-pipeline/src/history.rs#L499), [`core/dr-pipeline/src/history.rs:526`](../../core/dr-pipeline/src/history.rs#L526), [`core/dr-pipeline/src/history.rs:86`](../../core/dr-pipeline/src/history.rs#L86), [`core/dr-pipeline/src/sidecar.rs:1067`](../../core/dr-pipeline/src/sidecar.rs#L1067), [`core/dr-pipeline/src/sidecar.rs:147`](../../core/dr-pipeline/src/sidecar.rs#L147), [`core/dr-pipeline/src/sidecar.rs:2515`](../../core/dr-pipeline/src/sidecar.rs#L2515), [`core/dr-pipeline/src/sidecar.rs:2551`](../../core/dr-pipeline/src/sidecar.rs#L2551), [`core/dr-pipeline/src/sidecar.rs:2563`](../../core/dr-pipeline/src/sidecar.rs#L2563), [`core/dr-pipeline/src/sidecar.rs:318`](../../core/dr-pipeline/src/sidecar.rs#L318), [`core/dr-pipeline/src/sidecar.rs:713`](../../core/dr-pipeline/src/sidecar.rs#L713), [`core/dr-pipeline/src/sidecar.rs:729`](../../core/dr-pipeline/src/sidecar.rs#L729), [`core/dr-pipeline/src/sidecar.rs:876`](../../core/dr-pipeline/src/sidecar.rs#L876), [`core/dr-pipeline/src/state.rs:1`](../../core/dr-pipeline/src/state.rs#L1), [`core/dr-pipeline/src/state.rs:75`](../../core/dr-pipeline/src/state.rs#L75), [`ui/dr-ui/src/develop/framing.rs:945`](../../ui/dr-ui/src/develop/framing.rs#L945), [`ui/dr-ui/src/develop/history.rs:11`](../../ui/dr-ui/src/develop/history.rs#L11), [`ui/dr-ui/src/develop/history.rs:152`](../../ui/dr-ui/src/develop/history.rs#L152), [`ui/dr-ui/src/develop/history.rs:165`](../../ui/dr-ui/src/develop/history.rs#L165), [`ui/dr-ui/src/develop/history.rs:178`](../../ui/dr-ui/src/develop/history.rs#L178), [`ui/dr-ui/src/develop/history.rs:190`](../../ui/dr-ui/src/develop/history.rs#L190), [`ui/dr-ui/src/develop/history.rs:206`](../../ui/dr-ui/src/develop/history.rs#L206), [`ui/dr-ui/src/develop/history.rs:238`](../../ui/dr-ui/src/develop/history.rs#L238), [`ui/dr-ui/src/develop/history.rs:242`](../../ui/dr-ui/src/develop/history.rs#L242), [`ui/dr-ui/src/develop/history.rs:261`](../../ui/dr-ui/src/develop/history.rs#L261), [`ui/dr-ui/src/develop/history.rs:277`](../../ui/dr-ui/src/develop/history.rs#L277), [`ui/dr-ui/src/develop/history.rs:299`](../../ui/dr-ui/src/develop/history.rs#L299), [`ui/dr-ui/src/develop/history.rs:29`](../../ui/dr-ui/src/develop/history.rs#L29), [`ui/dr-ui/src/develop/history.rs:359`](../../ui/dr-ui/src/develop/history.rs#L359), [`ui/dr-ui/src/develop/history.rs:68`](../../ui/dr-ui/src/develop/history.rs#L68), [`ui/dr-ui/src/develop/history.rs:82`](../../ui/dr-ui/src/develop/history.rs#L82), [`ui/dr-ui/src/develop/history.rs:93`](../../ui/dr-ui/src/develop/history.rs#L93), [`ui/dr-ui/src/develop/render.rs:1079`](../../ui/dr-ui/src/develop/render.rs#L1079), [`ui/dr-ui/src/develop/render.rs:1115`](../../ui/dr-ui/src/develop/render.rs#L1115), [`ui/dr-ui/src/develop/render.rs:859`](../../ui/dr-ui/src/develop/render.rs#L859), [`ui/dr-ui/src/develop/session.rs:86`](../../ui/dr-ui/src/develop/session.rs#L86), [`ui/dr-ui/src/develop/session.rs:95`](../../ui/dr-ui/src/develop/session.rs#L95), [`ui/dr-ui/src/develop/white_balance.rs:11`](../../ui/dr-ui/src/develop/white_balance.rs#L11), [`ui/dr-ui/src/develop/white_balance.rs:162`](../../ui/dr-ui/src/develop/white_balance.rs#L162), [`ui/dr-ui/src/develop_ui.rs:852`](../../ui/dr-ui/src/develop_ui.rs#L852), [`ui/dr-ui/src/develop_ui.rs:872`](../../ui/dr-ui/src/develop_ui.rs#L872), [`ui/dr-ui/src/labels.rs:12`](../../ui/dr-ui/src/labels.rs#L12), [`ui/dr-ui/src/labels.rs:302`](../../ui/dr-ui/src/labels.rs#L302), [`ui/dr-ui/src/labels.rs:31`](../../ui/dr-ui/src/labels.rs#L31), [`ui/dr-ui/src/lib.rs:2170`](../../ui/dr-ui/src/lib.rs#L2170), [`ui/dr-ui/src/lib.rs:2175`](../../ui/dr-ui/src/lib.rs#L2175), [`ui/dr-ui/src/lib.rs:2207`](../../ui/dr-ui/src/lib.rs#L2207), [`ui/dr-ui/src/lib.rs:2216`](../../ui/dr-ui/src/lib.rs#L2216), [`ui/dr-ui/src/lib.rs:2233`](../../ui/dr-ui/src/lib.rs#L2233), [`ui/dr-ui/src/library/sidecar.rs:351`](../../ui/dr-ui/src/library/sidecar.rs#L351), [`ui/dr-ui/src/library/sidecar.rs:61`](../../ui/dr-ui/src/library/sidecar.rs#L61), [`ui/dr-ui/src/presets.rs:2076`](../../ui/dr-ui/src/presets.rs#L2076), [`ui/dr-ui/src/presets.rs:373`](../../ui/dr-ui/src/presets.rs#L373), [`ui/dr-ui/src/presets.rs:437`](../../ui/dr-ui/src/presets.rs#L437), [`ui/dr-ui/src/presets.rs:557`](../../ui/dr-ui/src/presets.rs#L557), [`ui/dr-ui/ui/history.slint:192`](../../ui/dr-ui/ui/history.slint#L192), [`ui/dr-ui/ui/history.slint:1`](../../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:219`](../../ui/dr-ui/ui/history.slint#L219), [`ui/dr-ui/ui/history.slint:304`](../../ui/dr-ui/ui/history.slint#L304), [`ui/dr-ui/ui/history.slint:43`](../../ui/dr-ui/ui/history.slint#L43), [`ui/dr-ui/ui/history.slint:53`](../../ui/dr-ui/ui/history.slint#L53) | | FR-DEV-6 | [`core/dr-pipeline/src/bundled.rs:1`](../../core/dr-pipeline/src/bundled.rs#L1), [`core/dr-pipeline/src/preset.rs:1293`](../../core/dr-pipeline/src/preset.rs#L1293), [`core/dr-pipeline/src/preset.rs:1303`](../../core/dr-pipeline/src/preset.rs#L1303), [`core/dr-pipeline/src/preset.rs:1312`](../../core/dr-pipeline/src/preset.rs#L1312), [`core/dr-pipeline/src/preset.rs:1328`](../../core/dr-pipeline/src/preset.rs#L1328), [`core/dr-pipeline/src/preset.rs:1340`](../../core/dr-pipeline/src/preset.rs#L1340), [`core/dr-pipeline/src/preset.rs:1356`](../../core/dr-pipeline/src/preset.rs#L1356), [`core/dr-pipeline/src/preset.rs:1382`](../../core/dr-pipeline/src/preset.rs#L1382), [`core/dr-pipeline/src/preset.rs:1404`](../../core/dr-pipeline/src/preset.rs#L1404), [`core/dr-pipeline/src/preset.rs:1418`](../../core/dr-pipeline/src/preset.rs#L1418), [`core/dr-pipeline/src/preset.rs:1436`](../../core/dr-pipeline/src/preset.rs#L1436), [`core/dr-pipeline/src/preset.rs:1529`](../../core/dr-pipeline/src/preset.rs#L1529), [`core/dr-pipeline/src/preset.rs:1544`](../../core/dr-pipeline/src/preset.rs#L1544), [`core/dr-pipeline/src/preset.rs:1`](../../core/dr-pipeline/src/preset.rs#L1), [`core/dr-pipeline/src/preset.rs:501`](../../core/dr-pipeline/src/preset.rs#L501), [`core/dr-pipeline/src/preset.rs:534`](../../core/dr-pipeline/src/preset.rs#L534), [`core/dr-preset-xmp/src/lib.rs:1`](../../core/dr-preset-xmp/src/lib.rs#L1), [`core/dr-preset-xmp/src/lib.rs:492`](../../core/dr-preset-xmp/src/lib.rs#L492), [`core/dr-types/src/settings.rs:443`](../../core/dr-types/src/settings.rs#L443), [`ui/dr-ui/src/develop/session.rs:699`](../../ui/dr-ui/src/develop/session.rs#L699), [`ui/dr-ui/src/develop/session.rs:720`](../../ui/dr-ui/src/develop/session.rs#L720), [`ui/dr-ui/src/develop_ui.rs:247`](../../ui/dr-ui/src/develop_ui.rs#L247), [`ui/dr-ui/src/develop_ui.rs:276`](../../ui/dr-ui/src/develop_ui.rs#L276), [`ui/dr-ui/src/lib.rs:1300`](../../ui/dr-ui/src/lib.rs#L1300), [`ui/dr-ui/src/library/sidecar.rs:12`](../../ui/dr-ui/src/library/sidecar.rs#L12), [`ui/dr-ui/src/library/sidecar.rs:40`](../../ui/dr-ui/src/library/sidecar.rs#L40), [`ui/dr-ui/src/library/thumbnails_fetch.rs:414`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L414), [`ui/dr-ui/src/library_ui/controller.rs:699`](../../ui/dr-ui/src/library_ui/controller.rs#L699), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:495`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L495), [`ui/dr-ui/src/library_ui/window.rs:823`](../../ui/dr-ui/src/library_ui/window.rs#L823), [`ui/dr-ui/src/preset_store.rs:1`](../../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/presets.rs:1892`](../../ui/dr-ui/src/presets.rs#L1892), [`ui/dr-ui/src/presets.rs:1`](../../ui/dr-ui/src/presets.rs#L1), [`ui/dr-ui/src/presets.rs:707`](../../ui/dr-ui/src/presets.rs#L707), [`ui/dr-ui/src/presets.rs:746`](../../ui/dr-ui/src/presets.rs#L746), [`ui/dr-ui/src/presets.rs:996`](../../ui/dr-ui/src/presets.rs#L996), [`ui/dr-ui/ui/adjust.slint:937`](../../ui/dr-ui/ui/adjust.slint#L937), [`ui/dr-ui/ui/adjust.slint:962`](../../ui/dr-ui/ui/adjust.slint#L962), [`ui/dr-ui/ui/app.slint:1094`](../../ui/dr-ui/ui/app.slint#L1094), [`ui/dr-ui/ui/app.slint:1518`](../../ui/dr-ui/ui/app.slint#L1518), [`ui/dr-ui/ui/app.slint:1802`](../../ui/dr-ui/ui/app.slint#L1802), [`ui/dr-ui/ui/app.slint:2550`](../../ui/dr-ui/ui/app.slint#L2550), [`ui/dr-ui/ui/app.slint:3483`](../../ui/dr-ui/ui/app.slint#L3483), [`ui/dr-ui/ui/app.slint:3529`](../../ui/dr-ui/ui/app.slint#L3529), [`ui/dr-ui/ui/app.slint:527`](../../ui/dr-ui/ui/app.slint#L527), [`ui/dr-ui/ui/app.slint:538`](../../ui/dr-ui/ui/app.slint#L538), [`ui/dr-ui/ui/app.slint:698`](../../ui/dr-ui/ui/app.slint#L698), [`ui/dr-ui/ui/develop.slint:257`](../../ui/dr-ui/ui/develop.slint#L257), [`ui/dr-ui/ui/icons.slint:390`](../../ui/dr-ui/ui/icons.slint#L390), [`ui/dr-ui/ui/library.slint:2026`](../../ui/dr-ui/ui/library.slint#L2026), [`ui/dr-ui/ui/library.slint:2032`](../../ui/dr-ui/ui/library.slint#L2032), [`ui/dr-ui/ui/library.slint:3229`](../../ui/dr-ui/ui/library.slint#L3229), [`ui/dr-ui/ui/library.slint:5167`](../../ui/dr-ui/ui/library.slint#L5167), [`ui/dr-ui/ui/library.slint:5185`](../../ui/dr-ui/ui/library.slint#L5185), [`ui/dr-ui/ui/presets.slint:114`](../../ui/dr-ui/ui/presets.slint#L114), [`ui/dr-ui/ui/presets.slint:155`](../../ui/dr-ui/ui/presets.slint#L155), [`ui/dr-ui/ui/presets.slint:203`](../../ui/dr-ui/ui/presets.slint#L203), [`ui/dr-ui/ui/presets.slint:211`](../../ui/dr-ui/ui/presets.slint#L211), [`ui/dr-ui/ui/presets.slint:21`](../../ui/dr-ui/ui/presets.slint#L21), [`ui/dr-ui/ui/presets.slint:33`](../../ui/dr-ui/ui/presets.slint#L33), [`ui/dr-ui/ui/presets.slint:394`](../../ui/dr-ui/ui/presets.slint#L394), [`ui/dr-ui/ui/presets.slint:432`](../../ui/dr-ui/ui/presets.slint#L432), [`ui/dr-ui/ui/presets.slint:467`](../../ui/dr-ui/ui/presets.slint#L467), [`ui/dr-ui/ui/presets.slint:62`](../../ui/dr-ui/ui/presets.slint#L62), [`ui/dr-ui/ui/presets.slint:7`](../../ui/dr-ui/ui/presets.slint#L7), [`ui/dr-ui/ui/settings.slint:126`](../../ui/dr-ui/ui/settings.slint#L126), [`ui/dr-ui/ui/settings.slint:690`](../../ui/dr-ui/ui/settings.slint#L690), [`ui/dr-ui/ui/toolrail.slint:123`](../../ui/dr-ui/ui/toolrail.slint#L123), [`ui/dr-ui/ui/toolrail.slint:453`](../../ui/dr-ui/ui/toolrail.slint#L453) | @@ -149,9 +149,9 @@ _None._ | FR-PLAT-WIN-3 | [`apps/darkroom-desktop/src/main.rs:19`](../../apps/darkroom-desktop/src/main.rs#L19) | | FR-RAW-1 | [`core/dr-decode/src/lib.rs:266`](../../core/dr-decode/src/lib.rs#L266), [`core/dr-types/src/lib.rs:135`](../../core/dr-types/src/lib.rs#L135), [`core/dr-types/src/lib.rs:206`](../../core/dr-types/src/lib.rs#L206) | | FR-RAW-2 | [`core/dr-decode/src/decoder.rs:1`](../../core/dr-decode/src/decoder.rs#L1), [`core/dr-decode/src/decoder.rs:26`](../../core/dr-decode/src/decoder.rs#L26), [`core/dr-decode/src/decoder.rs:59`](../../core/dr-decode/src/decoder.rs#L59), [`core/dr-decode/src/decoder.rs:95`](../../core/dr-decode/src/decoder.rs#L95), [`ui/dr-ui/src/decoder_seam.rs:185`](../../ui/dr-ui/src/decoder_seam.rs#L185), [`ui/dr-ui/src/decoder_seam.rs:1`](../../ui/dr-ui/src/decoder_seam.rs#L1), [`ui/dr-ui/src/decoder_seam.rs:216`](../../ui/dr-ui/src/decoder_seam.rs#L216), [`ui/dr-ui/src/decoder_seam.rs:257`](../../ui/dr-ui/src/decoder_seam.rs#L257), [`ui/dr-ui/src/export.rs:1238`](../../ui/dr-ui/src/export.rs#L1238), [`ui/dr-ui/src/export.rs:973`](../../ui/dr-ui/src/export.rs#L973), [`ui/dr-ui/src/import.rs:96`](../../ui/dr-ui/src/import.rs#L96), [`ui/dr-ui/src/library/sweep.rs:301`](../../ui/dr-ui/src/library/sweep.rs#L301), [`ui/dr-ui/src/library/sweep.rs:629`](../../ui/dr-ui/src/library/sweep.rs#L629), [`ui/dr-ui/src/library/thumbnails_gen.rs:101`](../../ui/dr-ui/src/library/thumbnails_gen.rs#L101), [`ui/dr-ui/src/merge.rs:119`](../../ui/dr-ui/src/merge.rs#L119), [`ui/dr-ui/src/repairs.rs:243`](../../ui/dr-ui/src/repairs.rs#L243) | -| FR-RAW-3 | [`core/dr-decode/src/lib.rs:162`](../../core/dr-decode/src/lib.rs#L162), [`core/dr-decode/src/lib.rs:564`](../../core/dr-decode/src/lib.rs#L564), [`core/dr-decode/src/locate.rs:1435`](../../core/dr-decode/src/locate.rs#L1435), [`core/dr-gpu/src/demosaic.rs:1046`](../../core/dr-gpu/src/demosaic.rs#L1046), [`core/dr-gpu/src/demosaic.rs:1392`](../../core/dr-gpu/src/demosaic.rs#L1392), [`core/dr-gpu/src/demosaic.rs:851`](../../core/dr-gpu/src/demosaic.rs#L851), [`core/dr-gpu/tests/hot_pixels.rs:1`](../../core/dr-gpu/tests/hot_pixels.rs#L1) | +| FR-RAW-3 | [`core/dr-decode/src/lib.rs:162`](../../core/dr-decode/src/lib.rs#L162), [`core/dr-decode/src/lib.rs:564`](../../core/dr-decode/src/lib.rs#L564), [`core/dr-decode/src/locate.rs:1435`](../../core/dr-decode/src/locate.rs#L1435), [`core/dr-gpu/src/demosaic.rs:1063`](../../core/dr-gpu/src/demosaic.rs#L1063), [`core/dr-gpu/src/demosaic.rs:1409`](../../core/dr-gpu/src/demosaic.rs#L1409), [`core/dr-gpu/src/demosaic.rs:868`](../../core/dr-gpu/src/demosaic.rs#L868), [`core/dr-gpu/tests/hot_pixels.rs:1`](../../core/dr-gpu/tests/hot_pixels.rs#L1) | | FR-RAW-4 | [`core/dr-decode/src/error.rs:1`](../../core/dr-decode/src/error.rs#L1), [`core/dr-decode/src/error.rs:30`](../../core/dr-decode/src/error.rs#L30), [`ui/dr-ui/src/lib.rs:295`](../../ui/dr-ui/src/lib.rs#L295) | -| FR-RAW-5 | [`core/dr-decode/src/lib.rs:190`](../../core/dr-decode/src/lib.rs#L190), [`core/dr-gpu/src/demosaic.rs:1187`](../../core/dr-gpu/src/demosaic.rs#L1187), [`core/dr-gpu/src/demosaic.rs:1266`](../../core/dr-gpu/src/demosaic.rs#L1266), [`core/dr-gpu/src/demosaic.rs:1390`](../../core/dr-gpu/src/demosaic.rs#L1390), [`core/dr-gpu/src/demosaic.rs:34`](../../core/dr-gpu/src/demosaic.rs#L34) | +| FR-RAW-5 | [`core/dr-decode/src/lib.rs:190`](../../core/dr-decode/src/lib.rs#L190), [`core/dr-gpu/src/demosaic.rs:1204`](../../core/dr-gpu/src/demosaic.rs#L1204), [`core/dr-gpu/src/demosaic.rs:1283`](../../core/dr-gpu/src/demosaic.rs#L1283), [`core/dr-gpu/src/demosaic.rs:1407`](../../core/dr-gpu/src/demosaic.rs#L1407), [`core/dr-gpu/src/demosaic.rs:34`](../../core/dr-gpu/src/demosaic.rs#L34) | | FR-UI-1 | [`core/dr-types/src/settings.rs:1390`](../../core/dr-types/src/settings.rs#L1390), [`core/dr-types/src/settings.rs:492`](../../core/dr-types/src/settings.rs#L492), [`core/dr-types/src/settings.rs:512`](../../core/dr-types/src/settings.rs#L512), [`ui/dr-ui/src/develop_ui.rs:284`](../../ui/dr-ui/src/develop_ui.rs#L284), [`ui/dr-ui/src/lib.rs:126`](../../ui/dr-ui/src/lib.rs#L126), [`ui/dr-ui/src/lib.rs:141`](../../ui/dr-ui/src/lib.rs#L141), [`ui/dr-ui/src/lib.rs:163`](../../ui/dr-ui/src/lib.rs#L163), [`ui/dr-ui/src/lib.rs:3347`](../../ui/dr-ui/src/lib.rs#L3347), [`ui/dr-ui/src/lib.rs:3366`](../../ui/dr-ui/src/lib.rs#L3366), [`ui/dr-ui/src/lib.rs:3393`](../../ui/dr-ui/src/lib.rs#L3393), [`ui/dr-ui/src/lib.rs:3444`](../../ui/dr-ui/src/lib.rs#L3444), [`ui/dr-ui/src/lib.rs:3477`](../../ui/dr-ui/src/lib.rs#L3477), [`ui/dr-ui/src/library_ui/grid.rs:242`](../../ui/dr-ui/src/library_ui/grid.rs#L242), [`ui/dr-ui/src/masks_ui.rs:1608`](../../ui/dr-ui/src/masks_ui.rs#L1608), [`ui/dr-ui/src/settings_ui.rs:143`](../../ui/dr-ui/src/settings_ui.rs#L143), [`ui/dr-ui/ui/adjust.slint:1000`](../../ui/dr-ui/ui/adjust.slint#L1000), [`ui/dr-ui/ui/app.slint:3147`](../../ui/dr-ui/ui/app.slint#L3147), [`ui/dr-ui/ui/app.slint:670`](../../ui/dr-ui/ui/app.slint#L670), [`ui/dr-ui/ui/app.slint:815`](../../ui/dr-ui/ui/app.slint#L815), [`ui/dr-ui/ui/identity.slint:249`](../../ui/dr-ui/ui/identity.slint#L249), [`ui/dr-ui/ui/library.slint:1469`](../../ui/dr-ui/ui/library.slint#L1469), [`ui/dr-ui/ui/settings.slint:129`](../../ui/dr-ui/ui/settings.slint#L129), [`ui/dr-ui/ui/settings.slint:660`](../../ui/dr-ui/ui/settings.slint#L660), [`ui/dr-ui/ui/toolrail.slint:180`](../../ui/dr-ui/ui/toolrail.slint#L180), [`ui/dr-ui/ui/toolrail.slint:92`](../../ui/dr-ui/ui/toolrail.slint#L92), [`ui/dr-ui/ui/widgets.slint:1117`](../../ui/dr-ui/ui/widgets.slint#L1117) | | FR-UI-2 | [`ui/dr-ui/src/collections_ui/controller.rs:45`](../../ui/dr-ui/src/collections_ui/controller.rs#L45), [`ui/dr-ui/src/collections_ui/controller.rs:83`](../../ui/dr-ui/src/collections_ui/controller.rs#L83), [`ui/dr-ui/src/collections_ui/drag.rs:246`](../../ui/dr-ui/src/collections_ui/drag.rs#L246), [`ui/dr-ui/src/collections_ui/drag.rs:256`](../../ui/dr-ui/src/collections_ui/drag.rs#L256), [`ui/dr-ui/src/collections_ui/press.rs:453`](../../ui/dr-ui/src/collections_ui/press.rs#L453), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:121`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L121), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:138`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L138), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:415`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L415), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/gestures.rs:1`](../../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:126`](../../ui/dr-ui/src/lib.rs#L126), [`ui/dr-ui/src/library_ui/filter_bar.rs:351`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L351), [`ui/dr-ui/src/library_ui/grid.rs:242`](../../ui/dr-ui/src/library_ui/grid.rs#L242), [`ui/dr-ui/src/library_ui/window.rs:1149`](../../ui/dr-ui/src/library_ui/window.rs#L1149), [`ui/dr-ui/tests/scroll_cue.rs:1`](../../ui/dr-ui/tests/scroll_cue.rs#L1), [`ui/dr-ui/ui/app.slint:137`](../../ui/dr-ui/ui/app.slint#L137), [`ui/dr-ui/ui/app.slint:3545`](../../ui/dr-ui/ui/app.slint#L3545), [`ui/dr-ui/ui/app.slint:799`](../../ui/dr-ui/ui/app.slint#L799), [`ui/dr-ui/ui/collections.slint:1354`](../../ui/dr-ui/ui/collections.slint#L1354), [`ui/dr-ui/ui/controls.slint:626`](../../ui/dr-ui/ui/controls.slint#L626), [`ui/dr-ui/ui/gestures.slint:1`](../../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/library.slint:1356`](../../ui/dr-ui/ui/library.slint#L1356), [`ui/dr-ui/ui/library.slint:1389`](../../ui/dr-ui/ui/library.slint#L1389), [`ui/dr-ui/ui/library.slint:1717`](../../ui/dr-ui/ui/library.slint#L1717), [`ui/dr-ui/ui/library.slint:1724`](../../ui/dr-ui/ui/library.slint#L1724), [`ui/dr-ui/ui/library.slint:1825`](../../ui/dr-ui/ui/library.slint#L1825), [`ui/dr-ui/ui/library.slint:3168`](../../ui/dr-ui/ui/library.slint#L3168), [`ui/dr-ui/ui/library.slint:586`](../../ui/dr-ui/ui/library.slint#L586), [`ui/dr-ui/ui/presets.slint:114`](../../ui/dr-ui/ui/presets.slint#L114), [`ui/dr-ui/ui/settings.slint:143`](../../ui/dr-ui/ui/settings.slint#L143), [`ui/dr-ui/ui/widgets.slint:1117`](../../ui/dr-ui/ui/widgets.slint#L1117) | | FR-UI-3 | [`ui/dr-ui/src/collections_ui/controller.rs:143`](../../ui/dr-ui/src/collections_ui/controller.rs#L143), [`ui/dr-ui/src/collections_ui/controller.rs:348`](../../ui/dr-ui/src/collections_ui/controller.rs#L348), [`ui/dr-ui/src/collections_ui/controller.rs:361`](../../ui/dr-ui/src/collections_ui/controller.rs#L361), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/develop/masks.rs:361`](../../ui/dr-ui/src/develop/masks.rs#L361), [`ui/dr-ui/src/develop/repairs.rs:49`](../../ui/dr-ui/src/develop/repairs.rs#L49), [`ui/dr-ui/src/library_ui/grid.rs:228`](../../ui/dr-ui/src/library_ui/grid.rs#L228), [`ui/dr-ui/src/masks_ui.rs:1700`](../../ui/dr-ui/src/masks_ui.rs#L1700), [`ui/dr-ui/src/masks_ui.rs:1722`](../../ui/dr-ui/src/masks_ui.rs#L1722), [`ui/dr-ui/src/masks_ui.rs:339`](../../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/spots_ui.rs:19`](../../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/ui/app.slint:2356`](../../ui/dr-ui/ui/app.slint#L2356), [`ui/dr-ui/ui/collections.slint:1228`](../../ui/dr-ui/ui/collections.slint#L1228), [`ui/dr-ui/ui/collections.slint:4`](../../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:78`](../../ui/dr-ui/ui/collections.slint#L78), [`ui/dr-ui/ui/collections.slint:978`](../../ui/dr-ui/ui/collections.slint#L978), [`ui/dr-ui/ui/masks.slint:1246`](../../ui/dr-ui/ui/masks.slint#L1246), [`ui/dr-ui/ui/widgets.slint:72`](../../ui/dr-ui/ui/widgets.slint#L72) |