diff --git a/apps/darkroom-android/src/lib.rs b/apps/darkroom-android/src/lib.rs index 11a6dd3..6d89b05 100644 --- a/apps/darkroom-android/src/lib.rs +++ b/apps/darkroom-android/src/lib.rs @@ -338,7 +338,7 @@ fn unpack_bundled_models(app: &slint::android::AndroidApp) { // sibling when the probe chose that rung and ignores it otherwise. The // segmenter's and XFeat's forms are compiled into the binary instead, // beside their f32 graphs. - const BUNDLED: [(&std::ffi::CStr, &str); 19] = [ + const BUNDLED: [(&std::ffi::CStr, &str); 23] = [ (c"models/scrfd_500m_640.onnx", "scrfd_500m_640.onnx"), ( c"models/scrfd_500m_640.a16w8.onnx", @@ -372,8 +372,23 @@ fn unpack_bundled_models(app: &slint::android::AndroidApp) { // The panorama border filler (FR-MRG-4); MIT, 28 MB. (c"models/migan-512.onnx", "migan-512.onnx"), (c"models/migan-512.a16w16.onnx", "migan-512.a16w16.onnx"), - (c"models/mosaic-1408.onnx", "mosaic-1408.onnx"), - (c"models/mosaic-1408.a16w16.onnx", "mosaic-1408.a16w16.onnx"), + // The learned demosaic and denoise, one network per method + // (FR-DEV-3g), each with the 16-bit form the Hexagon runs. + (c"models/mosaic-fast-1408.onnx", "mosaic-fast-1408.onnx"), + ( + c"models/mosaic-fast-1408.a16w16.onnx", + "mosaic-fast-1408.a16w16.onnx", + ), + (c"models/mosaic-medium-1408.onnx", "mosaic-medium-1408.onnx"), + ( + c"models/mosaic-medium-1408.a16w16.onnx", + "mosaic-medium-1408.a16w16.onnx", + ), + (c"models/mosaic-best-1408.onnx", "mosaic-best-1408.onnx"), + ( + c"models/mosaic-best-1408.a16w16.onnx", + "mosaic-best-1408.a16w16.onnx", + ), ]; let dir = dr_ui::shared_face_models_dir(); diff --git a/core/dr-denoise/examples/denoise_raw.rs b/core/dr-denoise/examples/denoise_raw.rs index 22740c4..123b63c 100644 --- a/core/dr-denoise/examples/denoise_raw.rs +++ b/core/dr-denoise/examples/denoise_raw.rs @@ -2,11 +2,11 @@ //! //! ```sh //! DARKROOM_ORT_DIR=~/.local/share/darkroom/runtime \ -//! cargo run --release -p dr-denoise --features native --example denoise_raw -- IMG.CR2 out +//! cargo run --release -p dr-denoise --features native --example denoise_raw -- IMG.CR2 out [fast|medium|best] //! ``` //! //! Decode, the app's hot-pixel pass, the frame's noise from its best source, -//! then the shipped network under the inference engine on whatever rung this +//! then one of the shipped networks (`best` unless named) under the inference engine on whatever rung this //! machine probes to. Writes `out.npy` — the active area, `h×w×3` f32 linear //! camera RGB — for comparison with the training repo's own path //! (`tools/compare_rust.py` in darkroom-denoise). `DARKROOM_ORT_DIR` points @@ -23,11 +23,21 @@ fn main() { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); let mut args = std::env::args().skip(1); let (Some(input), Some(out)) = (args.next(), args.next()) else { - eprintln!("usage: denoise_raw RAW OUT_PREFIX"); + eprintln!("usage: denoise_raw RAW OUT_PREFIX [fast|medium|best]"); std::process::exit(2); }; - let model = - PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../models/denoise/mosaic-1408.onnx"); + let shipped = match args.next().as_deref() { + None | Some("best") => dr_denoise::BEST, + Some("medium") => dr_denoise::MEDIUM, + Some("fast") => dr_denoise::FAST, + Some(other) => { + eprintln!("no network called {other}: fast, medium or best"); + std::process::exit(2); + } + }; + let model = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../models/denoise") + .join(shipped.file); let cache = std::env::var_os("DR_ENGINE_CACHE") .map(PathBuf::from) .unwrap_or_else(|| std::env::temp_dir().join("dr-denoise-engines")); @@ -91,7 +101,7 @@ fn main() { noise.col ); - let mut net = OnnxNet::from_path(&model).expect("model"); + let mut net = OnnxNet::from_path(&model, shipped.halo).expect("model"); println!( "rung {}", net.rung().map(|r| r.label()).unwrap_or("?") diff --git a/core/dr-denoise/src/lib.rs b/core/dr-denoise/src/lib.rs index 1e245c8..eb78e76 100644 --- a/core/dr-denoise/src/lib.rs +++ b/core/dr-denoise/src/lib.rs @@ -27,6 +27,33 @@ use dr_decode::RawImage; pub use noise::{NoiseModel, Source}; pub use tile::{TileNet, HALO}; +/// TRACES: FR-DEV-3g +/// A network the app ships in `models/denoise/`: its file, and the context +/// it needs past a tile's kept centre (docs/dev/denoise.md §13). +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Shipped { + pub file: &'static str, + pub halo: usize, +} + +/// The smallest student: 0.9 M parameters, 11 GMAC a megapixel. +pub const FAST: Shipped = Shipped { + file: "mosaic-fast-1408.onnx", + halo: HALO, +}; +/// A student of the mixture with the first release's shape: 3.2 M +/// parameters, 48 GMAC a megapixel. +pub const MEDIUM: Shipped = Shipped { + file: "mosaic-medium-1408.onnx", + halo: HALO, +}; +/// The mixture: a flat expert, an edge expert and the gate that blends them. +/// It reaches further than either, so it keeps a smaller centre of each tile. +pub const BEST: Shipped = Shipped { + file: "mosaic-best-1408.onnx", + halo: 256, +}; + #[derive(Debug, thiserror::Error)] pub enum DenoiseError { #[error("the network cannot take this photograph: {0}")] diff --git a/core/dr-denoise/src/onnx.rs b/core/dr-denoise/src/onnx.rs index 5b47052..748478f 100644 --- a/core/dr-denoise/src/onnx.rs +++ b/core/dr-denoise/src/onnx.rs @@ -21,15 +21,19 @@ pub const TILE: usize = 1408; pub struct OnnxNet { model: Model, tile: usize, + halo: usize, } impl OnnxNet { - pub fn from_path(path: &std::path::Path) -> Result { + /// The network at `path`, which needs `halo` photosites of context + /// ([`crate::Shipped::halo`]). + pub fn from_path(path: &std::path::Path, halo: usize) -> Result { let (path, form) = dr_inference_engine::resolve_model(Role::Denoiser, path); let bytes = std::fs::read(&path)?; Ok(OnnxNet { model: dr_inference_engine::open(Role::Denoiser, form, &bytes)?, tile: TILE, + halo, }) } @@ -44,6 +48,10 @@ impl TileNet for OnnxNet { self.tile } + fn halo(&self) -> usize { + self.halo + } + fn run( &mut self, mosaic: Vec, diff --git a/core/dr-denoise/src/tile.rs b/core/dr-denoise/src/tile.rs index 7057bd2..1cc9344 100644 --- a/core/dr-denoise/src/tile.rs +++ b/core/dr-denoise/src/tile.rs @@ -15,7 +15,9 @@ use dr_decode::CfaPattern; -/// Photosites of context beyond a tile's kept centre, on every side. +/// Photosites of context beyond a tile's kept centre, on every side, for a +/// single network; a mixture reaches further and says so through +/// [`TileNet::halo`]. pub const HALO: usize = 192; /// A fixed-shape network: `mosaic` and `sigma`, `n×n` RGGB, in; `3×n×n` @@ -28,6 +30,11 @@ pub const HALO: usize = 192; pub trait TileNet { /// The edge `n` of the square tile the network takes. fn tile(&self) -> usize; + /// Photosites of context it needs past a tile's kept centre: at least + /// its receptive field. [`HALO`] unless the network says otherwise. + fn halo(&self) -> usize { + HALO + } fn run( &mut self, mosaic: Vec, @@ -78,13 +85,13 @@ pub fn run_tiled( let (dy, dx) = rggb_offset(pattern).ok_or_else(|| { crate::DenoiseError::Unsupported(format!("{pattern:?} is not a Bayer pattern")) })?; - let n = net.tile(); - if n <= 2 * HALO || !(n - 2 * HALO).is_multiple_of(2) { + let (n, halo) = (net.tile(), net.halo()); + if n <= 2 * halo || !(n - 2 * halo).is_multiple_of(2) { return Err(crate::DenoiseError::Model(format!( - "tile {n} leaves no even centre past a {HALO} halo" + "tile {n} leaves no even centre past a {halo} halo" ))); } - let core = n - 2 * HALO; + let core = n - 2 * halo; // In unified coordinates the frame spans u ∈ [dy, dy + h), v ∈ [dx, dx + w). let (uh, uw) = (h + dy, w + dx); let (ty, tx) = (uh.div_ceil(core), uw.div_ceil(core)); @@ -108,11 +115,11 @@ pub fn run_tiled( scope.spawn(move || { for (i, (mrow, srow)) in m.chunks_mut(n).zip(s.chunks_mut(n)).enumerate() { let r = chunk * rows_per + i; - // Unified row u = u0 + r − HALO; frame row y = u − dy, reflected. - let u = u0 as isize + r as isize - HALO as isize; + // Unified row u = u0 + r − halo; frame row y = u − dy, reflected. + let u = u0 as isize + r as isize - halo as isize; let y = reflect(u - dy as isize, h); for c in 0..n { - let v = v0 as isize + c as isize - HALO as isize; + let v = v0 as isize + c as isize - halo as isize; let x = reflect(v - dx as isize, w); let val = at(y, x); mrow[c] = val; @@ -169,10 +176,10 @@ pub fn run_tiled( scope.spawn(move || { for (i, row) in block.chunks_mut(w * 3).enumerate() { let y = y_lo + chunk * per + i; - // Tile row of frame row y: u = y + dy = u0 + r − HALO. - let r = y + dy + HALO - u0; + // Tile row of frame row y: u = y + dy = u0 + r − halo. + let r = y + dy + halo - u0; for x in x_lo..x_hi { - let c = x + dx + HALO - v0; + let c = x + dx + halo - v0; for ch in 0..3 { row[x * 3 + ch] = rgb[ch * n * n + r * n + c]; } diff --git a/core/dr-pipeline/src/graph.rs b/core/dr-pipeline/src/graph.rs index e09376f..0cc1b3b 100644 --- a/core/dr-pipeline/src/graph.rs +++ b/core/dr-pipeline/src/graph.rs @@ -176,10 +176,10 @@ pub struct EditGraph { /// lens profile, so not in the state; it only decides whether the /// switch below is offered. denoise_available: bool, - /// Whether the learned denoise replaces the demosaic. An edit: published - /// as [`crate::learned_denoise`], captured, stored and undone with the - /// rest (FR-DEV-3c). - denoise_applied: bool, + /// Which demosaic develops the photograph: a network, or the classical + /// one. An edit: published as [`crate::learned_denoise`], captured, + /// stored and undone with the rest (FR-DEV-3c). + denoise_method: crate::learned_denoise::Method, /// How strongly to denoise, 0–100; what is not taken goes back as grain. denoise_strength: f32, } @@ -239,7 +239,7 @@ impl EditGraph { lens_profile: None, lens_profile_applied: true, denoise_available: false, - denoise_applied: true, + denoise_method: crate::learned_denoise::Method::DEFAULT, denoise_strength: 100.0, } } @@ -425,7 +425,13 @@ impl EditGraph { /// photograph that cannot take it is harmless and does nothing, as a /// lens switch with no profile does. pub fn denoise_applied(&self) -> bool { - self.denoise_applied + self.denoise_method.learned() + } + + /// TRACES: FR-DEV-3g + /// Which demosaic is asked for. + pub fn denoise_method(&self) -> crate::learned_denoise::Method { + self.denoise_method } /// TRACES: FR-DEV-3g @@ -625,7 +631,7 @@ impl EditGraph { OpCapability { id: desc.id, label: desc.label, - active: self.denoise_applied, + active: self.denoise_applied(), params: desc .params .iter() @@ -743,7 +749,7 @@ impl EditGraph { // Derived from the file, like the profile above. denoise_available: _, // Edits, in the state through `capabilities` like the lens switch. - denoise_applied: _, + denoise_method: _, denoise_strength: _, masks, film, @@ -818,7 +824,19 @@ impl EditGraph { pub fn set_param(&mut self, op: OpId, param: ParamId, value: f32) { if op == crate::learned_denoise::ID { match param { - p if p == crate::learned_denoise::APPLY => self.denoise_applied = value != 0.0, + p if p == crate::learned_denoise::METHOD => { + self.denoise_method = crate::learned_denoise::Method::from_index(value) + } + // 0.21 and 0.22's switch (see `APPLY`): off is the classical + // demosaic, on is a network — the one already chosen, if any. + p if p == crate::learned_denoise::APPLY => { + use crate::learned_denoise::Method; + if value == 0.0 { + self.denoise_method = Method::Bilinear; + } else if !self.denoise_method.learned() { + self.denoise_method = Method::DEFAULT; + } + } p if p == crate::learned_denoise::STRENGTH => { self.denoise_strength = value.clamp(0.0, 100.0) } @@ -889,8 +907,9 @@ impl EditGraph { pub fn param(&self, op: OpId, param: ParamId) -> Option { if op == crate::learned_denoise::ID { return match param { + p if p == crate::learned_denoise::METHOD => Some(self.denoise_method.index()), p if p == crate::learned_denoise::APPLY => { - Some(if self.denoise_applied { 1.0 } else { 0.0 }) + Some(if self.denoise_applied() { 1.0 } else { 0.0 }) } p if p == crate::learned_denoise::STRENGTH => Some(self.denoise_strength), p if p == crate::learned_denoise::GRAIN => Some(100.0 - self.denoise_strength), @@ -943,9 +962,9 @@ impl EditGraph { // a reset does not change which lens took the photograph. What returns // to default is the answer to whether to use it, which is on. self.set_lens_profile_applied(true); - // The learned denoise returns to off; whether it is available is the - // file's and stays. - self.denoise_applied = true; + // The learned denoise returns to its default network; whether it is + // available is the file's and stays. + self.denoise_method = crate::learned_denoise::Method::DEFAULT; self.denoise_strength = 100.0; } @@ -2106,9 +2125,14 @@ mod tests { .find(|c| c.id == learned_denoise::ID) .expect("offered"); assert!(cap.active, "on by default"); + assert_eq!(g.denoise_method(), learned_denoise::Method::Best); assert_eq!(g.denoise_grain(), 0.0, "at full strength"); assert_eq!(cap.id, g.capabilities()[0].id, "and first in the panel"); - g.set_param(learned_denoise::ID, learned_denoise::APPLY, 0.0); + g.set_param( + learned_denoise::ID, + learned_denoise::METHOD, + learned_denoise::Method::Bilinear.index(), + ); g.set_param(learned_denoise::ID, learned_denoise::STRENGTH, 70.0); assert!(!g.denoise_applied()); assert!((g.denoise_grain() - 0.3).abs() < 1e-6); @@ -2117,6 +2141,58 @@ mod tests { assert_eq!(g.denoise_grain(), 0.0); } + #[test] + fn an_untouched_raw_writes_nothing_and_develops_through_the_best() { + // TRACES: FR-DEV-3g + use crate::learned_denoise::{self, Method}; + let mut g = EditGraph::default_chain(); + g.set_denoise_available(true); + assert_eq!(g.denoise_method(), Method::Best); + let stored = |g: &EditGraph| { + crate::Preset::capture_params(g) + .params() + .keys() + .any(|(op, _)| op == learned_denoise::ID.0) + }; + assert!(!stored(&g), "the default is not written"); + g.set_param( + learned_denoise::ID, + learned_denoise::METHOD, + Method::Fast.index(), + ); + assert!(stored(&g), "a choice is"); + assert!( + !crate::Preset::capture_params(&g).params().contains_key(&( + learned_denoise::ID.0.into(), + learned_denoise::APPLY.0.into() + )), + "and the old switch never is" + ); + } + + #[test] + fn an_edit_saved_with_the_switch_keeps_its_look() { + // TRACES: FR-DEV-3g + // 0.21 and 0.22 stored on or off; off is the classical demosaic, and + // on keeps a network already chosen. + use crate::learned_denoise::{self, Method}; + let mut g = EditGraph::default_chain(); + g.set_param(learned_denoise::ID, learned_denoise::APPLY, 0.0); + assert_eq!(g.denoise_method(), Method::Bilinear); + g.set_param(learned_denoise::ID, learned_denoise::APPLY, 1.0); + assert_eq!(g.denoise_method(), Method::DEFAULT); + g.set_param( + learned_denoise::ID, + learned_denoise::METHOD, + Method::Fast.index(), + ); + g.set_param(learned_denoise::ID, learned_denoise::APPLY, 1.0); + assert_eq!(g.denoise_method(), Method::Fast); + // A number from a newer build with more methods is the default. + g.set_param(learned_denoise::ID, learned_denoise::METHOD, 9.0); + assert_eq!(g.denoise_method(), Method::DEFAULT); + } + #[test] fn an_edit_saved_with_grain_keeps_its_look() { // TRACES: FR-DEV-3g @@ -2137,11 +2213,16 @@ mod tests { let mut g = EditGraph::default_chain(); g.set_denoise_available(true); g.set_param(learned_denoise::ID, learned_denoise::STRENGTH, 60.0); + g.set_param( + learned_denoise::ID, + learned_denoise::METHOD, + learned_denoise::Method::Medium.index(), + ); let state = g.state(); let mut h = EditGraph::default_chain(); h.set_denoise_available(true); let _ = h.set_state(&state); - assert!(h.denoise_applied()); + assert_eq!(h.denoise_method(), learned_denoise::Method::Medium); assert!((h.denoise_grain() - 0.4).abs() < 1e-6); } } diff --git a/core/dr-pipeline/src/learned_denoise.rs b/core/dr-pipeline/src/learned_denoise.rs index fac1a2b..19c0f12 100644 --- a/core/dr-pipeline/src/learned_denoise.rs +++ b/core/dr-pipeline/src/learned_denoise.rs @@ -1,6 +1,6 @@ //! TRACES: FR-DEV-3g -//! The learned denoise's settings: whether to use it, and how much grain to -//! keep. +//! The learned denoise's settings: which network develops the photograph, +//! if any, and how much grain to keep. //! //! Not an [`crate::operation::Operation`]: the learned stage replaces the //! demosaic and runs once per photograph, off the render path @@ -17,6 +17,12 @@ use crate::descriptor::{Attribute, LocalizedKey, OpDescriptor, ParamDescriptor, use crate::{OpId, ParamId}; pub const ID: OpId = OpId("learned_denoise"); +/// TRACES: FR-DEV-3g +/// Which demosaic develops the photograph, a [`Method`] by index. +pub const METHOD: ParamId = ParamId("method"); +/// What 0.21 and 0.22 stored instead of [`METHOD`]: on or off. Still read — +/// off is [`Method::Bilinear`], on is the default network — so an edit saved +/// by those releases keeps its look; never written, and not offered. pub const APPLY: ParamId = ParamId("apply"); /// TRACES: FR-DEV-3g /// How strongly to denoise, 0–100: 100 is the network's result as it is, and @@ -27,9 +33,52 @@ pub const STRENGTH: ParamId = ParamId("strength"); /// written, and not offered as a control. pub const GRAIN: ParamId = ParamId("grain"); -/// On by default, at full strength: every Bayer raw is developed from the -/// learned demosaic, and the switch and the slider are there to take it back -/// or ease it off. It costs seconds per photograph the first time, while +/// TRACES: FR-DEV-3g +/// The demosaics a photograph can be developed with, in the order the +/// sidecar numbers them. Three networks that trade time for quality — the +/// same training, distilled into smaller students (docs/dev/denoise.md §13) +/// — and the classical demosaic, which is no network at all. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Method { + /// The classical demosaic: the noise stays. + Bilinear, + /// The smallest student: a quarter of the medium network's work. + Fast, + /// One network the size of the first release's. + Medium, + /// Two experts, one for flat areas and one for edges, and a gate. + Best, +} + +impl Method { + pub const ALL: [Method; 4] = [Method::Bilinear, Method::Fast, Method::Medium, Method::Best]; + pub const DEFAULT: Method = Method::Best; + + /// The sidecar's number for it. + pub fn index(self) -> f32 { + Self::ALL.iter().position(|m| *m == self).unwrap_or(0) as f32 + } + + /// The method a stored number names; out of range is the default, as + /// from a newer build with more of them. + pub fn from_index(value: f32) -> Method { + let i = value.round(); + if i >= 0.0 && (i as usize) < Self::ALL.len() { + Self::ALL[i as usize] + } else { + Self::DEFAULT + } + } + + /// Whether a network runs at all. + pub fn learned(self) -> bool { + self != Method::Bilinear + } +} + +/// The best network by default, at full strength: every Bayer raw is +/// developed from the learned demosaic, and the choice and the slider are +/// there to take it back, trade it for time, or ease it off. It costs seconds per photograph the first time, while /// the classical demosaic shows; the result is cached, so a photograph /// reopened or exported does not pay again (docs/dev/denoise.md §7). pub(crate) static DESCRIPTOR: LazyLock> = LazyLock::new(|| { @@ -37,7 +86,17 @@ pub(crate) static DESCRIPTOR: LazyLock> = LazyLock::new(|| { id: ID, label: LocalizedKey("op.learned_denoise"), params: vec![ - ParamDescriptor::switch_on("apply", "param.learned_denoise.apply"), + ParamDescriptor::choice( + "method", + "param.learned_denoise.method", + vec![ + LocalizedKey("param.learned_denoise.method.bilinear"), + LocalizedKey("param.learned_denoise.method.fast"), + LocalizedKey("param.learned_denoise.method.medium"), + LocalizedKey("param.learned_denoise.method.best"), + ], + ) + .with_default(Method::DEFAULT.index()), ParamDescriptor::scalar( "strength", "param.learned_denoise.strength", diff --git a/docs/dev/denoise.md b/docs/dev/denoise.md index 10e9154..c01d6b5 100644 --- a/docs/dev/denoise.md +++ b/docs/dev/denoise.md @@ -457,3 +457,72 @@ under Detail. So: What it costs: every raw opened runs the network once, with the classical demosaic shown until the result lands, and a first export of an unopened raw runs it too. Every raw renders differently from 0.21.0 unless switched off. + +## 13. Three networks and a method (after 0.22.0) + +The photographer asked for a choice between quality and time. `Method` replaces the Apply switch: +`Bilinear`, `Fast`, `Medium`, `Best`, by index in that order, default `Best`. An untouched raw +writes nothing and develops through `Best`. `apply` is still read and never written: 0 is +`Bilinear`, 1 keeps a network already chosen or is the default. A number past the list, from a newer +build, reads as the default. A build before this one ignores `method` and develops through its own +network, which is the most an older peer can do. + +**The networks** (darkroom-denoise, every one trained on the same data and noise as §11, plus 1,201 +further frames cropped from the library and 6,000 drawn scenes — polygons, lines of one to four +photosites, text, gratings — rendered at 4× through a random affine and smooth displacement, so +edges fall off the photosite grid): + +| Method | File | Network | Parameters | GMAC / MP | Halo | +|---|---|---|---|---|---| +| Best | `mosaic-best-1408.onnx` | two U-Nets of §11's shape (a flat expert from `m2`, an edge expert from the ×100 edge-weighted run) and a 128 k-parameter gate that blends them per photosite | 6.4 M | 110 | 256 | +| Medium | `mosaic-medium-1408.onnx` | §11's U-Net, distilled from Best (75 % its output, 25 % the truth) | 3.2 M | 48 | 192 | +| Fast | `mosaic-fast-1408.onnx` | widths 16-32-64-128, blocks 1-1-1-2, distilled the same way | 0.93 M | 11 | 192 | + +The gate learned on its own to trust the edge expert at 0.77–0.88 on edges and not at all on flat +areas. The mixture's receptive field is the experts' plus the gate's, so it keeps the centre of a +1408 tile past a 256 halo, where the single networks keep 1024 past 192. `dr_denoise::Shipped` +carries each file's halo, and `TileNet::halo` hands it to the tiler. + +**Quality.** PSNR after the display transform on 1,842 held-out crops, and the width of a hard +edge on the drawn chart at ISO 6400 (truth 0.80 photosites; lower is sharper): + +| | ISO 400 | 1600 | 6400 | 25600 | Edge width | +|---|---|---|---|---|---| +| §11's network | 40.61 | 39.77 | 38.43 | 36.67 | 1.77 | +| Best | 40.69 | 39.84 | 38.47 | 36.71 | 0.82 | +| Medium | 40.59 | 39.75 | 38.40 | 36.65 | 1.30 | +| Fast | 39.90 | 39.06 | 37.54 | 35.33 | 1.84 | +| Bilinear | 36.15 | 33.26 | 28.72 | 23.83 | 2.15 | + +On photographs the three are close; on hard edges Best is half as wide as §11's network and +Medium most of the way there. Fast costs a dB at high ISO and edges as soft as §11's. + +**Speed**, a whole 20 MP 6D frame, the network alone, TensorRT fp16 on the laptop's RTX 3050 +(uncapped: memory at 5 GHz), engine already built: Best 2.48 s, Medium 0.79 s, Fast 0.57 s. Decode +and the hot-pixel pass add about 0.5 s. The first build of each TensorRT engine takes 80 s (Fast) to +190 s (Best), in the background at first launch, cached after. + +**Before the network, two passes changed since §11.** + +- *A noise-aware repair* (`dr_denoise::repair`) after the app's hot-pixel pass: a photosite more + than 8σ beyond every same-colour neighbour *and* every adjacent photosite, and more than twice + each adjacent one, is clamped to the brightest of its same-colour neighbours; a dead one, to the + darkest. The ratio test is what spares a point of light, whose neighbours are lit too. The networks + were trained behind the same pass (the Python and Rust agree: 935 repairs on an ISO 25600 frame). +- *The tiler feeds the network without waiting*: tiles are gathered on every core by a producer + thread one tile ahead, and the output is written back in parallel from the runtime's own buffer. + 0.14 s of tiler for a frame, which is what keeps Fast under a second. + +**The Hexagon.** Each network has an `.a16w16.onnx` sibling made by `tools/quantise-models.sh +--ranges`, the ranges from darkroom-3e's gate (96 training tiles, a third at noise ×2 and ×4). On +the 6D gate A16W16 loses 0.00 dB for all three; with the noise scaled ×0.5–×4 at most 0.11 dB. +A16W8 holds the gate (≤ 0.27 dB) but loses 0.63 dB on Medium at ×4, so A16W16 stays the form. + +**Cache.** Each network keys its own results (§7.1 keys on the model's file name), and the file is +hashed once at open, so changing the method never re-reads it. Choosing `Bilinear` keeps the +network's result in memory for the way back; changing to another network drops it, and coming back +reads the cache. + +**Packaging.** All six files in the APK (`BUNDLED`, 23 entries, +44.6 MB, ~41 MB compressed); the +three f32 networks in the Arch package and the Windows installer, which stage `models/denoise` by +directory. diff --git a/docs/dev/traceability.md b/docs/dev/traceability.md index 460aff5..2e97ada 100644 --- a/docs/dev/traceability.md +++ b/docs/dev/traceability.md @@ -10,7 +10,7 @@ Denominators are parsed from [`requirements.md`](requirements.md) at run time, n | Metric | Value | |---|---| | Source files scanned | 502 | -| TRACES tags found | 2106 | +| TRACES tags found | 2112 | | Requirements defined | 193 | | Requirements deferred (post-v1) | 24 | | Requirements covered | 166 | @@ -48,7 +48,7 @@ _None._ | FR-CAT-5 | [`core/dr-catalog/src/keywords.rs:1`](../../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/merge.rs:1`](../../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/name_dates.rs:1`](../../core/dr-catalog/src/name_dates.rs#L1), [`core/dr-catalog/src/rating.rs:1`](../../core/dr-catalog/src/rating.rs#L1), [`core/dr-catalog/src/rating.rs:396`](../../core/dr-catalog/src/rating.rs#L396), [`core/dr-catalog/src/rating.rs:411`](../../core/dr-catalog/src/rating.rs#L411), [`core/dr-catalog/src/rating.rs:422`](../../core/dr-catalog/src/rating.rs#L422), [`core/dr-catalog/src/rating.rs:449`](../../core/dr-catalog/src/rating.rs#L449), [`core/dr-catalog/src/rating.rs:52`](../../core/dr-catalog/src/rating.rs#L52), [`core/dr-catalog/src/rating.rs:827`](../../core/dr-catalog/src/rating.rs#L827), [`core/dr-catalog/src/rating.rs:851`](../../core/dr-catalog/src/rating.rs#L851), [`core/dr-catalog/src/rating.rs:870`](../../core/dr-catalog/src/rating.rs#L870), [`core/dr-catalog/src/schema.rs:1164`](../../core/dr-catalog/src/schema.rs#L1164), [`core/dr-catalog/src/schema.rs:1751`](../../core/dr-catalog/src/schema.rs#L1751), [`core/dr-catalog/src/schema.rs:359`](../../core/dr-catalog/src/schema.rs#L359), [`core/dr-decode/src/lib.rs:308`](../../core/dr-decode/src/lib.rs#L308), [`core/dr-decode/src/lib.rs:314`](../../core/dr-decode/src/lib.rs#L314), [`core/dr-decode/src/lib.rs:324`](../../core/dr-decode/src/lib.rs#L324), [`core/dr-decode/src/lib.rs:451`](../../core/dr-decode/src/lib.rs#L451), [`core/dr-export/src/dng.rs:308`](../../core/dr-export/src/dng.rs#L308), [`core/dr-pipeline/src/sidecar.rs:1093`](../../core/dr-pipeline/src/sidecar.rs#L1093), [`core/dr-pipeline/src/sidecar.rs:174`](../../core/dr-pipeline/src/sidecar.rs#L174), [`core/dr-pipeline/src/sidecar.rs:193`](../../core/dr-pipeline/src/sidecar.rs#L193), [`core/dr-pipeline/src/sidecar.rs:2876`](../../core/dr-pipeline/src/sidecar.rs#L2876), [`core/dr-pipeline/src/sidecar.rs:2894`](../../core/dr-pipeline/src/sidecar.rs#L2894), [`core/dr-pipeline/src/sidecar.rs:590`](../../core/dr-pipeline/src/sidecar.rs#L590), [`ui/dr-ui/src/collections_ui/controller.rs:16`](../../ui/dr-ui/src/collections_ui/controller.rs#L16), [`ui/dr-ui/src/collections_ui/controller.rs:209`](../../ui/dr-ui/src/collections_ui/controller.rs#L209), [`ui/dr-ui/src/collections_ui/controller.rs:418`](../../ui/dr-ui/src/collections_ui/controller.rs#L418), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:150`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L150), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:264`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L264), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:323`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L323), [`ui/dr-ui/src/decoder_seam.rs:185`](../../ui/dr-ui/src/decoder_seam.rs#L185), [`ui/dr-ui/src/library/cells.rs:202`](../../ui/dr-ui/src/library/cells.rs#L202), [`ui/dr-ui/src/library/scan.rs:527`](../../ui/dr-ui/src/library/scan.rs#L527), [`ui/dr-ui/src/library/scan.rs:917`](../../ui/dr-ui/src/library/scan.rs#L917), [`ui/dr-ui/src/library_ui/controller.rs:863`](../../ui/dr-ui/src/library_ui/controller.rs#L863), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1154`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1154), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1178`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1178), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:118`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L118), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1195`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1195), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1401`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1401), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1412`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1412), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1425`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1425), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1440`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1440), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1449`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1449), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:97`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L97), [`ui/dr-ui/tests/status_is_not_colour_alone.rs:177`](../../ui/dr-ui/tests/status_is_not_colour_alone.rs#L177), [`ui/dr-ui/tests/status_is_not_colour_alone.rs:215`](../../ui/dr-ui/tests/status_is_not_colour_alone.rs#L215), [`ui/dr-ui/ui/app.slint:1678`](../../ui/dr-ui/ui/app.slint#L1678), [`ui/dr-ui/ui/app.slint:2877`](../../ui/dr-ui/ui/app.slint#L2877), [`ui/dr-ui/ui/develop.slint:142`](../../ui/dr-ui/ui/develop.slint#L142), [`ui/dr-ui/ui/develop.slint:48`](../../ui/dr-ui/ui/develop.slint#L48), [`ui/dr-ui/ui/labels.slint:19`](../../ui/dr-ui/ui/labels.slint#L19), [`ui/dr-ui/ui/labels.slint:1`](../../ui/dr-ui/ui/labels.slint#L1), [`ui/dr-ui/ui/labels.slint:40`](../../ui/dr-ui/ui/labels.slint#L40), [`ui/dr-ui/ui/labels.slint:74`](../../ui/dr-ui/ui/labels.slint#L74), [`ui/dr-ui/ui/library.slint:1640`](../../ui/dr-ui/ui/library.slint#L1640), [`ui/dr-ui/ui/library.slint:1643`](../../ui/dr-ui/ui/library.slint#L1643), [`ui/dr-ui/ui/library.slint:1794`](../../ui/dr-ui/ui/library.slint#L1794), [`ui/dr-ui/ui/library.slint:1818`](../../ui/dr-ui/ui/library.slint#L1818), [`ui/dr-ui/ui/library.slint:1875`](../../ui/dr-ui/ui/library.slint#L1875), [`ui/dr-ui/ui/library.slint:21`](../../ui/dr-ui/ui/library.slint#L21), [`ui/dr-ui/ui/library.slint:3235`](../../ui/dr-ui/ui/library.slint#L3235), [`ui/dr-ui/ui/library.slint:3242`](../../ui/dr-ui/ui/library.slint#L3242), [`ui/dr-ui/ui/library.slint:3262`](../../ui/dr-ui/ui/library.slint#L3262), [`ui/dr-ui/ui/library.slint:3351`](../../ui/dr-ui/ui/library.slint#L3351), [`ui/dr-ui/ui/library.slint:3967`](../../ui/dr-ui/ui/library.slint#L3967), [`ui/dr-ui/ui/library.slint:467`](../../ui/dr-ui/ui/library.slint#L467), [`ui/dr-ui/ui/library.slint:495`](../../ui/dr-ui/ui/library.slint#L495), [`ui/dr-ui/ui/library.slint:5095`](../../ui/dr-ui/ui/library.slint#L5095), [`ui/dr-ui/ui/library.slint:5111`](../../ui/dr-ui/ui/library.slint#L5111), [`ui/dr-ui/ui/library.slint:522`](../../ui/dr-ui/ui/library.slint#L522), [`ui/dr-ui/ui/library.slint:643`](../../ui/dr-ui/ui/library.slint#L643), [`ui/dr-ui/ui/library.slint:687`](../../ui/dr-ui/ui/library.slint#L687), [`ui/dr-ui/ui/library.slint:693`](../../ui/dr-ui/ui/library.slint#L693), [`ui/dr-ui/ui/library.slint:697`](../../ui/dr-ui/ui/library.slint#L697) | | FR-CAT-6 | [`core/dr-catalog/src/collections.rs:1`](../../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/keywords.rs:1`](../../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/lib.rs:1`](../../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/query.rs:1`](../../core/dr-catalog/src/query.rs#L1), [`core/dr-catalog/src/rating.rs:1`](../../core/dr-catalog/src/rating.rs#L1), [`core/dr-catalog/src/rating.rs:449`](../../core/dr-catalog/src/rating.rs#L449), [`core/dr-catalog/src/rating.rs:880`](../../core/dr-catalog/src/rating.rs#L880), [`core/dr-catalog/src/schema.rs:1164`](../../core/dr-catalog/src/schema.rs#L1164), [`core/dr-types/src/place.rs:138`](../../core/dr-types/src/place.rs#L138), [`core/dr-types/src/place.rs:1`](../../core/dr-types/src/place.rs#L1), [`core/dr-types/src/selector.rs:1`](../../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:64`](../../core/dr-types/src/settings.rs#L64), [`core/dr-types/src/time.rs:67`](../../core/dr-types/src/time.rs#L67), [`core/dr-types/src/time.rs:90`](../../core/dr-types/src/time.rs#L90), [`ui/dr-ui/src/library/filters.rs:156`](../../ui/dr-ui/src/library/filters.rs#L156), [`ui/dr-ui/src/library/filters.rs:357`](../../ui/dr-ui/src/library/filters.rs#L357), [`ui/dr-ui/src/library/filters.rs:442`](../../ui/dr-ui/src/library/filters.rs#L442), [`ui/dr-ui/src/library/filters.rs:64`](../../ui/dr-ui/src/library/filters.rs#L64), [`ui/dr-ui/src/library/spans.rs:262`](../../ui/dr-ui/src/library/spans.rs#L262), [`ui/dr-ui/src/library_ui/controller.rs:435`](../../ui/dr-ui/src/library_ui/controller.rs#L435), [`ui/dr-ui/src/library_ui/controller.rs:551`](../../ui/dr-ui/src/library_ui/controller.rs#L551), [`ui/dr-ui/src/library_ui/filter_bar.rs:256`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L256), [`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/filter_bar.rs:406`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L406), [`ui/dr-ui/src/library_ui/filter_bar.rs:841`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L841), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:85`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L85), [`ui/dr-ui/ui/app.slint:660`](../../ui/dr-ui/ui/app.slint#L660), [`ui/dr-ui/ui/library.slint:113`](../../ui/dr-ui/ui/library.slint#L113), [`ui/dr-ui/ui/library.slint:1962`](../../ui/dr-ui/ui/library.slint#L1962), [`ui/dr-ui/ui/library.slint:1999`](../../ui/dr-ui/ui/library.slint#L1999), [`ui/dr-ui/ui/library.slint:2736`](../../ui/dr-ui/ui/library.slint#L2736), [`ui/dr-ui/ui/library.slint:3262`](../../ui/dr-ui/ui/library.slint#L3262), [`ui/dr-ui/ui/library.slint:495`](../../ui/dr-ui/ui/library.slint#L495), [`ui/dr-ui/ui/library.slint:5095`](../../ui/dr-ui/ui/library.slint#L5095), [`ui/dr-ui/ui/library.slint:643`](../../ui/dr-ui/ui/library.slint#L643), [`ui/dr-ui/ui/library.slint:701`](../../ui/dr-ui/ui/library.slint#L701), [`ui/dr-ui/ui/library.slint:723`](../../ui/dr-ui/ui/library.slint#L723), [`ui/dr-ui/ui/settings.slint:202`](../../ui/dr-ui/ui/settings.slint#L202), [`ui/dr-ui/ui/widgets.slint:271`](../../ui/dr-ui/ui/widgets.slint#L271) | | FR-CAT-7 | [`core/dr-catalog/src/albums.rs:1`](../../core/dr-catalog/src/albums.rs#L1), [`core/dr-catalog/src/collections.rs:1`](../../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/dedup_people.rs:1`](../../core/dr-catalog/src/dedup_people.rs#L1), [`core/dr-catalog/src/merge.rs:1`](../../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/sync.rs:1`](../../core/dr-catalog/src/sync.rs#L1), [`core/dr-types/src/selector.rs:1`](../../core/dr-types/src/selector.rs#L1), [`ui/dr-ui/src/collections_ui/controller.rs:263`](../../ui/dr-ui/src/collections_ui/controller.rs#L263), [`ui/dr-ui/src/collections_ui/controller.rs:273`](../../ui/dr-ui/src/collections_ui/controller.rs#L273), [`ui/dr-ui/src/collections_ui/controller.rs:296`](../../ui/dr-ui/src/collections_ui/controller.rs#L296), [`ui/dr-ui/src/collections_ui/controller.rs:317`](../../ui/dr-ui/src/collections_ui/controller.rs#L317), [`ui/dr-ui/src/collections_ui/controller.rs:46`](../../ui/dr-ui/src/collections_ui/controller.rs#L46), [`ui/dr-ui/src/collections_ui/drag.rs:274`](../../ui/dr-ui/src/collections_ui/drag.rs#L274), [`ui/dr-ui/src/collections_ui/mod.rs:1`](../../ui/dr-ui/src/collections_ui/mod.rs#L1), [`ui/dr-ui/src/collections_ui/press.rs:258`](../../ui/dr-ui/src/collections_ui/press.rs#L258), [`ui/dr-ui/src/collections_ui/press.rs:490`](../../ui/dr-ui/src/collections_ui/press.rs#L490), [`ui/dr-ui/src/collections_ui/press.rs:54`](../../ui/dr-ui/src/collections_ui/press.rs#L54), [`ui/dr-ui/src/collections_ui/rename_menu.rs:196`](../../ui/dr-ui/src/collections_ui/rename_menu.rs#L196), [`ui/dr-ui/src/collections_ui/rename_menu.rs:21`](../../ui/dr-ui/src/collections_ui/rename_menu.rs#L21), [`ui/dr-ui/src/collections_ui/tree_sync.rs:251`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L251), [`ui/dr-ui/src/collections_ui/tree_sync.rs:322`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L322), [`ui/dr-ui/src/collections_ui/tree_sync.rs:344`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L344), [`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:171`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L171), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:444`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L444), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:522`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L522), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:586`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L586), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:344`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L344), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:394`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L394), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:517`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L517), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:581`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L581), [`ui/dr-ui/src/derived_sync.rs:1`](../../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/library/spans.rs:131`](../../ui/dr-ui/src/library/spans.rs#L131), [`ui/dr-ui/src/library/spans.rs:50`](../../ui/dr-ui/src/library/spans.rs#L50), [`ui/dr-ui/src/library/spans.rs:76`](../../ui/dr-ui/src/library/spans.rs#L76), [`ui/dr-ui/src/library_ui/sync.rs:226`](../../ui/dr-ui/src/library_ui/sync.rs#L226), [`ui/dr-ui/src/library_ui/timeline.rs:510`](../../ui/dr-ui/src/library_ui/timeline.rs#L510), [`ui/dr-ui/src/library_ui/window.rs:400`](../../ui/dr-ui/src/library_ui/window.rs#L400), [`ui/dr-ui/src/library_ui/window.rs:436`](../../ui/dr-ui/src/library_ui/window.rs#L436), [`ui/dr-ui/ui/app.slint:3572`](../../ui/dr-ui/ui/app.slint#L3572), [`ui/dr-ui/ui/collections.slint:1283`](../../ui/dr-ui/ui/collections.slint#L1283), [`ui/dr-ui/ui/collections.slint:4`](../../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:616`](../../ui/dr-ui/ui/collections.slint#L616), [`ui/dr-ui/ui/library.slint:1389`](../../ui/dr-ui/ui/library.slint#L1389), [`ui/dr-ui/ui/library.slint:1760`](../../ui/dr-ui/ui/library.slint#L1760), [`ui/dr-ui/ui/library.slint:3716`](../../ui/dr-ui/ui/library.slint#L3716), [`ui/dr-ui/ui/library.slint:495`](../../ui/dr-ui/ui/library.slint#L495), [`ui/dr-ui/ui/library.slint:5073`](../../ui/dr-ui/ui/library.slint#L5073), [`ui/dr-ui/ui/library.slint:5215`](../../ui/dr-ui/ui/library.slint#L5215), [`ui/dr-ui/ui/library.slint:525`](../../ui/dr-ui/ui/library.slint#L525), [`ui/dr-ui/ui/library.slint:581`](../../ui/dr-ui/ui/library.slint#L581), [`ui/dr-ui/ui/library.slint:591`](../../ui/dr-ui/ui/library.slint#L591) | -| FR-CAT-8 | [`core/dr-catalog/src/schema.rs:779`](../../core/dr-catalog/src/schema.rs#L779), [`core/dr-pipeline/src/coverage.rs:1`](../../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/graph.rs:710`](../../core/dr-pipeline/src/graph.rs#L710), [`core/dr-pipeline/src/graph.rs:770`](../../core/dr-pipeline/src/graph.rs#L770), [`core/dr-pipeline/src/ops/curve.rs:137`](../../core/dr-pipeline/src/ops/curve.rs#L137), [`core/dr-pipeline/src/ops/curve.rs:690`](../../core/dr-pipeline/src/ops/curve.rs#L690), [`core/dr-pipeline/src/sidecar.rs:1433`](../../core/dr-pipeline/src/sidecar.rs#L1433), [`core/dr-pipeline/src/sidecar.rs:2275`](../../core/dr-pipeline/src/sidecar.rs#L2275), [`core/dr-pipeline/src/sidecar.rs:99`](../../core/dr-pipeline/src/sidecar.rs#L99), [`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), [`core/dr-pipeline/tests/tone_curve.rs:34`](../../core/dr-pipeline/tests/tone_curve.rs#L34), [`core/dr-sync/src/scan.rs:31`](../../core/dr-sync/src/scan.rs#L31), [`core/dr-sync/src/scan.rs:56`](../../core/dr-sync/src/scan.rs#L56), [`core/dr-sync/src/scan.rs:926`](../../core/dr-sync/src/scan.rs#L926), [`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:1130`](../../ui/dr-ui/src/develop/mask_ops.rs#L1130), [`ui/dr-ui/src/develop/mask_ops.rs:178`](../../ui/dr-ui/src/develop/mask_ops.rs#L178), [`ui/dr-ui/src/develop/masks.rs:743`](../../ui/dr-ui/src/develop/masks.rs#L743), [`ui/dr-ui/src/develop/session.rs:738`](../../ui/dr-ui/src/develop/session.rs#L738), [`ui/dr-ui/src/develop/session.rs:772`](../../ui/dr-ui/src/develop/session.rs#L772), [`ui/dr-ui/src/export.rs:1312`](../../ui/dr-ui/src/export.rs#L1312), [`ui/dr-ui/src/lib.rs:1274`](../../ui/dr-ui/src/lib.rs#L1274), [`ui/dr-ui/src/lib.rs:1335`](../../ui/dr-ui/src/lib.rs#L1335), [`ui/dr-ui/src/lib.rs:2809`](../../ui/dr-ui/src/lib.rs#L2809), [`ui/dr-ui/src/lib.rs:3015`](../../ui/dr-ui/src/lib.rs#L3015), [`ui/dr-ui/src/lib.rs:810`](../../ui/dr-ui/src/lib.rs#L810), [`ui/dr-ui/src/lib.rs:880`](../../ui/dr-ui/src/lib.rs#L880), [`ui/dr-ui/src/library/scan.rs:227`](../../ui/dr-ui/src/library/scan.rs#L227), [`ui/dr-ui/src/library/scan.rs:262`](../../ui/dr-ui/src/library/scan.rs#L262), [`ui/dr-ui/src/library/scan.rs:35`](../../ui/dr-ui/src/library/scan.rs#L35), [`ui/dr-ui/src/library/sidecar.rs:103`](../../ui/dr-ui/src/library/sidecar.rs#L103), [`ui/dr-ui/src/library/sidecar.rs:12`](../../ui/dr-ui/src/library/sidecar.rs#L12), [`ui/dr-ui/src/library/sidecar.rs:381`](../../ui/dr-ui/src/library/sidecar.rs#L381), [`ui/dr-ui/src/library/sidecar.rs:66`](../../ui/dr-ui/src/library/sidecar.rs#L66), [`ui/dr-ui/src/library/thumbnails_fetch.rs:414`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L414), [`ui/dr-ui/src/library/thumbnails_fetch.rs:549`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L549), [`ui/dr-ui/src/library_ui/grid.rs:825`](../../ui/dr-ui/src/library_ui/grid.rs#L825), [`ui/dr-ui/src/library_ui/open.rs:519`](../../ui/dr-ui/src/library_ui/open.rs#L519), [`ui/dr-ui/src/sidecar_cache.rs:1`](../../ui/dr-ui/src/sidecar_cache.rs#L1) | +| FR-CAT-8 | [`core/dr-catalog/src/schema.rs:779`](../../core/dr-catalog/src/schema.rs#L779), [`core/dr-pipeline/src/coverage.rs:1`](../../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/graph.rs:716`](../../core/dr-pipeline/src/graph.rs#L716), [`core/dr-pipeline/src/graph.rs:776`](../../core/dr-pipeline/src/graph.rs#L776), [`core/dr-pipeline/src/ops/curve.rs:137`](../../core/dr-pipeline/src/ops/curve.rs#L137), [`core/dr-pipeline/src/ops/curve.rs:690`](../../core/dr-pipeline/src/ops/curve.rs#L690), [`core/dr-pipeline/src/sidecar.rs:1433`](../../core/dr-pipeline/src/sidecar.rs#L1433), [`core/dr-pipeline/src/sidecar.rs:2275`](../../core/dr-pipeline/src/sidecar.rs#L2275), [`core/dr-pipeline/src/sidecar.rs:99`](../../core/dr-pipeline/src/sidecar.rs#L99), [`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), [`core/dr-pipeline/tests/tone_curve.rs:34`](../../core/dr-pipeline/tests/tone_curve.rs#L34), [`core/dr-sync/src/scan.rs:31`](../../core/dr-sync/src/scan.rs#L31), [`core/dr-sync/src/scan.rs:56`](../../core/dr-sync/src/scan.rs#L56), [`core/dr-sync/src/scan.rs:926`](../../core/dr-sync/src/scan.rs#L926), [`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:1130`](../../ui/dr-ui/src/develop/mask_ops.rs#L1130), [`ui/dr-ui/src/develop/mask_ops.rs:178`](../../ui/dr-ui/src/develop/mask_ops.rs#L178), [`ui/dr-ui/src/develop/masks.rs:743`](../../ui/dr-ui/src/develop/masks.rs#L743), [`ui/dr-ui/src/develop/session.rs:738`](../../ui/dr-ui/src/develop/session.rs#L738), [`ui/dr-ui/src/develop/session.rs:772`](../../ui/dr-ui/src/develop/session.rs#L772), [`ui/dr-ui/src/export.rs:1312`](../../ui/dr-ui/src/export.rs#L1312), [`ui/dr-ui/src/lib.rs:1274`](../../ui/dr-ui/src/lib.rs#L1274), [`ui/dr-ui/src/lib.rs:1335`](../../ui/dr-ui/src/lib.rs#L1335), [`ui/dr-ui/src/lib.rs:2809`](../../ui/dr-ui/src/lib.rs#L2809), [`ui/dr-ui/src/lib.rs:3015`](../../ui/dr-ui/src/lib.rs#L3015), [`ui/dr-ui/src/lib.rs:810`](../../ui/dr-ui/src/lib.rs#L810), [`ui/dr-ui/src/lib.rs:880`](../../ui/dr-ui/src/lib.rs#L880), [`ui/dr-ui/src/library/scan.rs:227`](../../ui/dr-ui/src/library/scan.rs#L227), [`ui/dr-ui/src/library/scan.rs:262`](../../ui/dr-ui/src/library/scan.rs#L262), [`ui/dr-ui/src/library/scan.rs:35`](../../ui/dr-ui/src/library/scan.rs#L35), [`ui/dr-ui/src/library/sidecar.rs:103`](../../ui/dr-ui/src/library/sidecar.rs#L103), [`ui/dr-ui/src/library/sidecar.rs:12`](../../ui/dr-ui/src/library/sidecar.rs#L12), [`ui/dr-ui/src/library/sidecar.rs:381`](../../ui/dr-ui/src/library/sidecar.rs#L381), [`ui/dr-ui/src/library/sidecar.rs:66`](../../ui/dr-ui/src/library/sidecar.rs#L66), [`ui/dr-ui/src/library/thumbnails_fetch.rs:414`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L414), [`ui/dr-ui/src/library/thumbnails_fetch.rs:549`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L549), [`ui/dr-ui/src/library_ui/grid.rs:825`](../../ui/dr-ui/src/library_ui/grid.rs#L825), [`ui/dr-ui/src/library_ui/open.rs:519`](../../ui/dr-ui/src/library_ui/open.rs#L519), [`ui/dr-ui/src/sidecar_cache.rs:1`](../../ui/dr-ui/src/sidecar_cache.rs#L1) | | FR-CAT-9 | [`core/dr-catalog/src/cache.rs:1`](../../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/scan.rs:1`](../../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/schema.rs:1221`](../../core/dr-catalog/src/schema.rs#L1221), [`core/dr-catalog/src/walk.rs:1000`](../../core/dr-catalog/src/walk.rs#L1000), [`core/dr-catalog/src/walk.rs:161`](../../core/dr-catalog/src/walk.rs#L161), [`core/dr-catalog/src/walk.rs:1`](../../core/dr-catalog/src/walk.rs#L1), [`core/dr-catalog/src/walk.rs:432`](../../core/dr-catalog/src/walk.rs#L432), [`core/dr-catalog/src/walk.rs:695`](../../core/dr-catalog/src/walk.rs#L695), [`core/dr-sync-nextcloud/src/desktop_client.rs:35`](../../core/dr-sync-nextcloud/src/desktop_client.rs#L35), [`core/dr-sync/src/error.rs:113`](../../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/reachability.rs:1`](../../core/dr-sync/src/reachability.rs#L1), [`core/dr-sync/src/scan.rs:211`](../../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../../core/dr-sync/src/scan.rs#L519), [`core/dr-types/src/lib.rs:125`](../../core/dr-types/src/lib.rs#L125), [`ui/dr-ui/src/develop/render.rs:723`](../../ui/dr-ui/src/develop/render.rs#L723), [`ui/dr-ui/src/develop/render.rs:815`](../../ui/dr-ui/src/develop/render.rs#L815), [`ui/dr-ui/src/library/filters.rs:89`](../../ui/dr-ui/src/library/filters.rs#L89), [`ui/dr-ui/src/library/scan.rs:127`](../../ui/dr-ui/src/library/scan.rs#L127), [`ui/dr-ui/src/library/scan.rs:180`](../../ui/dr-ui/src/library/scan.rs#L180), [`ui/dr-ui/src/library/scan.rs:211`](../../ui/dr-ui/src/library/scan.rs#L211), [`ui/dr-ui/src/library/scan.rs:262`](../../ui/dr-ui/src/library/scan.rs#L262), [`ui/dr-ui/src/library/scan.rs:636`](../../ui/dr-ui/src/library/scan.rs#L636), [`ui/dr-ui/src/library/sidecar.rs:103`](../../ui/dr-ui/src/library/sidecar.rs#L103), [`ui/dr-ui/src/library/sidecar.rs:365`](../../ui/dr-ui/src/library/sidecar.rs#L365), [`ui/dr-ui/src/library/sidecar.rs:381`](../../ui/dr-ui/src/library/sidecar.rs#L381), [`ui/dr-ui/src/library/sidecar.rs:435`](../../ui/dr-ui/src/library/sidecar.rs#L435), [`ui/dr-ui/src/library/spans.rs:378`](../../ui/dr-ui/src/library/spans.rs#L378), [`ui/dr-ui/src/library/thumbnails_fetch.rs:394`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L394), [`ui/dr-ui/src/library/thumbnails_fetch.rs:450`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L450), [`ui/dr-ui/src/library/thumbnails_gen.rs:83`](../../ui/dr-ui/src/library/thumbnails_gen.rs#L83), [`ui/dr-ui/src/library_ui/controller.rs:323`](../../ui/dr-ui/src/library_ui/controller.rs#L323), [`ui/dr-ui/src/library_ui/controller.rs:359`](../../ui/dr-ui/src/library_ui/controller.rs#L359), [`ui/dr-ui/src/library_ui/controller.rs:367`](../../ui/dr-ui/src/library_ui/controller.rs#L367), [`ui/dr-ui/src/library_ui/controller.rs:619`](../../ui/dr-ui/src/library_ui/controller.rs#L619), [`ui/dr-ui/src/library_ui/controller.rs:736`](../../ui/dr-ui/src/library_ui/controller.rs#L736), [`ui/dr-ui/src/library_ui/filter_bar.rs:461`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L461), [`ui/dr-ui/src/library_ui/filter_bar.rs:547`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L547), [`ui/dr-ui/src/library_ui/offline.rs:561`](../../ui/dr-ui/src/library_ui/offline.rs#L561), [`ui/dr-ui/src/library_ui/offline.rs:607`](../../ui/dr-ui/src/library_ui/offline.rs#L607), [`ui/dr-ui/src/library_ui/offline.rs:623`](../../ui/dr-ui/src/library_ui/offline.rs#L623), [`ui/dr-ui/src/library_ui/open.rs:599`](../../ui/dr-ui/src/library_ui/open.rs#L599), [`ui/dr-ui/src/library_ui/open.rs:679`](../../ui/dr-ui/src/library_ui/open.rs#L679), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:75`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L75), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:890`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L890), [`ui/dr-ui/src/library_ui/sync.rs:292`](../../ui/dr-ui/src/library_ui/sync.rs#L292), [`ui/dr-ui/src/library_ui/sync.rs:426`](../../ui/dr-ui/src/library_ui/sync.rs#L426), [`ui/dr-ui/src/library_ui/sync.rs:84`](../../ui/dr-ui/src/library_ui/sync.rs#L84), [`ui/dr-ui/src/library_ui/window.rs:1122`](../../ui/dr-ui/src/library_ui/window.rs#L1122), [`ui/dr-ui/src/library_ui/window.rs:835`](../../ui/dr-ui/src/library_ui/window.rs#L835), [`ui/dr-ui/src/presets.rs:486`](../../ui/dr-ui/src/presets.rs#L486), [`ui/dr-ui/src/presets.rs:498`](../../ui/dr-ui/src/presets.rs#L498), [`ui/dr-ui/src/sidecar_cache.rs:1`](../../ui/dr-ui/src/sidecar_cache.rs#L1), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../../ui/dr-ui/tests/export_ignores_the_viewport.rs#L1) | | FR-CULL-1 | [`core/dr-decode/src/preview.rs:121`](../../core/dr-decode/src/preview.rs#L121) | | FR-CULL-10 | [`core/dr-catalog/src/dedup_people.rs:1`](../../core/dr-catalog/src/dedup_people.rs#L1), [`core/dr-catalog/src/faces.rs:1662`](../../core/dr-catalog/src/faces.rs#L1662), [`core/dr-catalog/src/faces.rs:1680`](../../core/dr-catalog/src/faces.rs#L1680), [`core/dr-catalog/src/faces.rs:1`](../../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:1050`](../../core/dr-catalog/src/schema.rs#L1050), [`core/dr-catalog/src/schema.rs:642`](../../core/dr-catalog/src/schema.rs#L642), [`core/dr-catalog/src/schema.rs:820`](../../core/dr-catalog/src/schema.rs#L820), [`core/dr-face/src/assign.rs:1`](../../core/dr-face/src/assign.rs#L1), [`core/dr-face/src/neighbours.rs:1`](../../core/dr-face/src/neighbours.rs#L1), [`core/dr-face/src/references.rs:1`](../../core/dr-face/src/references.rs#L1), [`core/dr-types/src/settings.rs:129`](../../core/dr-types/src/settings.rs#L129), [`ui/dr-ui/src/develop/segmentation.rs:104`](../../ui/dr-ui/src/develop/segmentation.rs#L104), [`ui/dr-ui/src/develop/segmentation.rs:170`](../../ui/dr-ui/src/develop/segmentation.rs#L170), [`ui/dr-ui/src/develop/segmentation.rs:590`](../../ui/dr-ui/src/develop/segmentation.rs#L590), [`ui/dr-ui/src/develop/segmentation.rs:95`](../../ui/dr-ui/src/develop/segmentation.rs#L95), [`ui/dr-ui/src/develop/session.rs:23`](../../ui/dr-ui/src/develop/session.rs#L23), [`ui/dr-ui/src/faces.rs:1`](../../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/identity.rs:1`](../../ui/dr-ui/src/identity.rs#L1), [`ui/dr-ui/src/identity_ui.rs:1472`](../../ui/dr-ui/src/identity_ui.rs#L1472), [`ui/dr-ui/src/identity_ui.rs:1`](../../ui/dr-ui/src/identity_ui.rs#L1), [`ui/dr-ui/src/lib.rs:2987`](../../ui/dr-ui/src/lib.rs#L2987), [`ui/dr-ui/src/repairs.rs:1`](../../ui/dr-ui/src/repairs.rs#L1), [`ui/dr-ui/ui/identity.slint:1`](../../ui/dr-ui/ui/identity.slint#L1), [`ui/dr-ui/ui/settings.slint:469`](../../ui/dr-ui/ui/settings.slint#L469), [`ui/dr-ui/ui/settings.slint:95`](../../ui/dr-ui/ui/settings.slint#L95) | @@ -71,26 +71,26 @@ _None._ | FR-DEV-19 | [`core/dr-pipeline/src/mask.rs:1341`](../../core/dr-pipeline/src/mask.rs#L1341) | | 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:220`](../../ui/dr-ui/src/develop/session.rs#L220), [`ui/dr-ui/src/labels.rs:76`](../../ui/dr-ui/src/labels.rs#L76), [`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:229`](../../ui/dr-ui/src/develop/session.rs#L229), [`ui/dr-ui/src/develop/session.rs:236`](../../ui/dr-ui/src/develop/session.rs#L236), [`ui/dr-ui/src/labels.rs:70`](../../ui/dr-ui/src/labels.rs#L70), [`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:1055`](../../core/dr-pipeline/src/graph.rs#L1055), [`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:255`](../../ui/dr-ui/src/develop/session.rs#L255), [`ui/dr-ui/src/develop/session.rs:264`](../../ui/dr-ui/src/develop/session.rs#L264), [`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-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:1074`](../../core/dr-pipeline/src/graph.rs#L1074), [`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:255`](../../ui/dr-ui/src/develop/session.rs#L255), [`ui/dr-ui/src/develop/session.rs:264`](../../ui/dr-ui/src/develop/session.rs#L264), [`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:137`](../../core/dr-gpu/tests/view_transform.rs#L137), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:201`](../../core/dr-gpu/tests/view_transform.rs#L201), [`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:222`](../../core/dr-pipeline/src/view.rs#L222) | -| 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:1051`](../../core/dr-pipeline/src/preset.rs#L1051), [`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:305`](../../ui/dr-ui/src/labels.rs#L305), [`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:1022`](../../core/dr-pipeline/src/graph.rs#L1022), [`core/dr-pipeline/src/graph.rs:1114`](../../core/dr-pipeline/src/graph.rs#L1114), [`core/dr-pipeline/src/graph.rs:1512`](../../core/dr-pipeline/src/graph.rs#L1512), [`core/dr-pipeline/src/graph.rs:1543`](../../core/dr-pipeline/src/graph.rs#L1543), [`core/dr-pipeline/src/graph.rs:1566`](../../core/dr-pipeline/src/graph.rs#L1566), [`core/dr-pipeline/src/graph.rs:1604`](../../core/dr-pipeline/src/graph.rs#L1604), [`core/dr-pipeline/src/graph.rs:1635`](../../core/dr-pipeline/src/graph.rs#L1635), [`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:977`](../../core/dr-pipeline/src/preset.rs#L977), [`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:1026`](../../ui/dr-ui/src/develop/session.rs#L1026), [`ui/dr-ui/src/develop/session.rs:190`](../../ui/dr-ui/src/develop/session.rs#L190), [`ui/dr-ui/src/develop/session.rs:283`](../../ui/dr-ui/src/develop/session.rs#L283), [`ui/dr-ui/src/develop/session.rs:312`](../../ui/dr-ui/src/develop/session.rs#L312), [`ui/dr-ui/src/develop/session.rs:511`](../../ui/dr-ui/src/develop/session.rs#L511), [`ui/dr-ui/src/develop/session.rs:571`](../../ui/dr-ui/src/develop/session.rs#L571), [`ui/dr-ui/src/develop/session.rs:738`](../../ui/dr-ui/src/develop/session.rs#L738), [`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:38`](../../ui/dr-ui/src/labels.rs#L38), [`ui/dr-ui/src/lib.rs:2288`](../../ui/dr-ui/src/lib.rs#L2288), [`ui/dr-ui/src/lib.rs:472`](../../ui/dr-ui/src/lib.rs#L472), [`ui/dr-ui/src/lib.rs:502`](../../ui/dr-ui/src/lib.rs#L502), [`ui/dr-ui/src/lib.rs:610`](../../ui/dr-ui/src/lib.rs#L610), [`ui/dr-ui/src/lib.rs:634`](../../ui/dr-ui/src/lib.rs#L634), [`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:657`](../../core/dr-pipeline/src/graph.rs#L657), [`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:990`](../../ui/dr-ui/src/lib.rs#L990), [`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-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:1051`](../../core/dr-pipeline/src/preset.rs#L1051), [`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:311`](../../ui/dr-ui/src/labels.rs#L311), [`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:1041`](../../core/dr-pipeline/src/graph.rs#L1041), [`core/dr-pipeline/src/graph.rs:1133`](../../core/dr-pipeline/src/graph.rs#L1133), [`core/dr-pipeline/src/graph.rs:1531`](../../core/dr-pipeline/src/graph.rs#L1531), [`core/dr-pipeline/src/graph.rs:1562`](../../core/dr-pipeline/src/graph.rs#L1562), [`core/dr-pipeline/src/graph.rs:1585`](../../core/dr-pipeline/src/graph.rs#L1585), [`core/dr-pipeline/src/graph.rs:1623`](../../core/dr-pipeline/src/graph.rs#L1623), [`core/dr-pipeline/src/graph.rs:1654`](../../core/dr-pipeline/src/graph.rs#L1654), [`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:443`](../../core/dr-pipeline/src/graph.rs#L443), [`core/dr-pipeline/src/graph.rs:449`](../../core/dr-pipeline/src/graph.rs#L449), [`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:977`](../../core/dr-pipeline/src/preset.rs#L977), [`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:1026`](../../ui/dr-ui/src/develop/session.rs#L1026), [`ui/dr-ui/src/develop/session.rs:190`](../../ui/dr-ui/src/develop/session.rs#L190), [`ui/dr-ui/src/develop/session.rs:283`](../../ui/dr-ui/src/develop/session.rs#L283), [`ui/dr-ui/src/develop/session.rs:312`](../../ui/dr-ui/src/develop/session.rs#L312), [`ui/dr-ui/src/develop/session.rs:511`](../../ui/dr-ui/src/develop/session.rs#L511), [`ui/dr-ui/src/develop/session.rs:571`](../../ui/dr-ui/src/develop/session.rs#L571), [`ui/dr-ui/src/develop/session.rs:738`](../../ui/dr-ui/src/develop/session.rs#L738), [`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:38`](../../ui/dr-ui/src/labels.rs#L38), [`ui/dr-ui/src/lib.rs:2288`](../../ui/dr-ui/src/lib.rs#L2288), [`ui/dr-ui/src/lib.rs:472`](../../ui/dr-ui/src/lib.rs#L472), [`ui/dr-ui/src/lib.rs:502`](../../ui/dr-ui/src/lib.rs#L502), [`ui/dr-ui/src/lib.rs:610`](../../ui/dr-ui/src/lib.rs#L610), [`ui/dr-ui/src/lib.rs:634`](../../ui/dr-ui/src/lib.rs#L634), [`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:492`](../../core/dr-pipeline/src/graph.rs#L492), [`core/dr-pipeline/src/graph.rs:60`](../../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/graph.rs:663`](../../core/dr-pipeline/src/graph.rs#L663), [`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:990`](../../ui/dr-ui/src/lib.rs#L990), [`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:977`](../../core/dr-pipeline/src/preset.rs#L977), [`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:1142`](../../core/dr-pipeline/src/graph.rs#L1142), [`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-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:492`](../../core/dr-pipeline/src/graph.rs#L492), [`core/dr-pipeline/src/mask.rs:1746`](../../core/dr-pipeline/src/mask.rs#L1746), [`core/dr-pipeline/src/preset.rs:977`](../../core/dr-pipeline/src/preset.rs#L977), [`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:1161`](../../core/dr-pipeline/src/graph.rs#L1161), [`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/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:393`](../../core/dr-pipeline/src/ops/camera_profile.rs#L393), [`core/dr-pipeline/src/ops/camera_profile.rs:430`](../../core/dr-pipeline/src/ops/camera_profile.rs#L430), [`core/dr-pipeline/src/view.rs:238`](../../core/dr-pipeline/src/view.rs#L238), [`core/dr-types/src/hue_sat.rs:1`](../../core/dr-types/src/hue_sat.rs#L1), [`core/dr-types/src/tone.rs:162`](../../core/dr-types/src/tone.rs#L162), [`core/dr-types/src/tone.rs:1`](../../core/dr-types/src/tone.rs#L1), [`ui/dr-ui/src/derived_sync.rs:1031`](../../ui/dr-ui/src/derived_sync.rs#L1031), [`ui/dr-ui/src/derived_sync.rs:2056`](../../ui/dr-ui/src/derived_sync.rs#L2056), [`ui/dr-ui/src/derived_sync.rs:244`](../../ui/dr-ui/src/derived_sync.rs#L244), [`ui/dr-ui/src/derived_sync.rs:94`](../../ui/dr-ui/src/derived_sync.rs#L94), [`ui/dr-ui/src/develop/session.rs:606`](../../ui/dr-ui/src/develop/session.rs#L606), [`ui/dr-ui/src/develop/session.rs:646`](../../ui/dr-ui/src/develop/session.rs#L646), [`ui/dr-ui/src/develop/session.rs:681`](../../ui/dr-ui/src/develop/session.rs#L681), [`ui/dr-ui/src/develop/session.rs:690`](../../ui/dr-ui/src/develop/session.rs#L690), [`ui/dr-ui/src/develop/session.rs:73`](../../ui/dr-ui/src/develop/session.rs#L73), [`ui/dr-ui/src/develop/session.rs:882`](../../ui/dr-ui/src/develop/session.rs#L882), [`ui/dr-ui/src/develop/session.rs:955`](../../ui/dr-ui/src/develop/session.rs#L955), [`ui/dr-ui/src/lib.rs:1243`](../../ui/dr-ui/src/lib.rs#L1243), [`ui/dr-ui/src/lib.rs:1541`](../../ui/dr-ui/src/lib.rs#L1541), [`ui/dr-ui/src/lib.rs:1559`](../../ui/dr-ui/src/lib.rs#L1559), [`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:689`](../../core/dr-pipeline/src/graph.rs#L689), [`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:1343`](../../core/dr-pipeline/src/preset.rs#L1343), [`core/dr-pipeline/src/preset.rs:1353`](../../core/dr-pipeline/src/preset.rs#L1353), [`core/dr-pipeline/src/preset.rs:1362`](../../core/dr-pipeline/src/preset.rs#L1362), [`core/dr-pipeline/src/preset.rs:1378`](../../core/dr-pipeline/src/preset.rs#L1378), [`core/dr-pipeline/src/preset.rs:1390`](../../core/dr-pipeline/src/preset.rs#L1390), [`core/dr-pipeline/src/preset.rs:1406`](../../core/dr-pipeline/src/preset.rs#L1406), [`core/dr-pipeline/src/preset.rs:1670`](../../core/dr-pipeline/src/preset.rs#L1670), [`core/dr-pipeline/src/preset.rs:1685`](../../core/dr-pipeline/src/preset.rs#L1685), [`core/dr-pipeline/src/preset.rs:248`](../../core/dr-pipeline/src/preset.rs#L248), [`core/dr-pipeline/src/preset.rs:739`](../../core/dr-pipeline/src/preset.rs#L739), [`core/dr-pipeline/src/preset.rs:828`](../../core/dr-pipeline/src/preset.rs#L828), [`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:760`](../../ui/dr-ui/src/develop/session.rs#L760), [`ui/dr-ui/src/develop/session.rs:780`](../../ui/dr-ui/src/develop/session.rs#L780), [`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:916`](../../ui/dr-ui/src/lib.rs#L916), [`ui/dr-ui/src/lib.rs:981`](../../ui/dr-ui/src/lib.rs#L981), [`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:1933`](../../ui/dr-ui/src/presets.rs#L1933), [`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/repair.rs:1`](../../core/dr-denoise/src/repair.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:2122`](../../core/dr-pipeline/src/graph.rs#L2122), [`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), [`core/dr-pipeline/src/learned_denoise.rs:21`](../../core/dr-pipeline/src/learned_denoise.rs#L21), [`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/denoise.rs:292`](../../ui/dr-ui/src/develop/denoise.rs#L292), [`ui/dr-ui/src/develop/denoise.rs:95`](../../ui/dr-ui/src/develop/denoise.rs#L95), [`ui/dr-ui/src/develop/denoise_cache.rs:1`](../../ui/dr-ui/src/develop/denoise_cache.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:126`](../../ui/dr-ui/src/develop/session.rs#L126), [`ui/dr-ui/src/develop/session.rs:389`](../../ui/dr-ui/src/develop/session.rs#L389), [`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:392`](../../ui/dr-ui/src/library/paths.rs#L392), [`ui/dr-ui/src/library/paths.rs:396`](../../ui/dr-ui/src/library/paths.rs#L396) | +| 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:695`](../../core/dr-pipeline/src/graph.rs#L695), [`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:1343`](../../core/dr-pipeline/src/preset.rs#L1343), [`core/dr-pipeline/src/preset.rs:1353`](../../core/dr-pipeline/src/preset.rs#L1353), [`core/dr-pipeline/src/preset.rs:1362`](../../core/dr-pipeline/src/preset.rs#L1362), [`core/dr-pipeline/src/preset.rs:1378`](../../core/dr-pipeline/src/preset.rs#L1378), [`core/dr-pipeline/src/preset.rs:1390`](../../core/dr-pipeline/src/preset.rs#L1390), [`core/dr-pipeline/src/preset.rs:1406`](../../core/dr-pipeline/src/preset.rs#L1406), [`core/dr-pipeline/src/preset.rs:1670`](../../core/dr-pipeline/src/preset.rs#L1670), [`core/dr-pipeline/src/preset.rs:1685`](../../core/dr-pipeline/src/preset.rs#L1685), [`core/dr-pipeline/src/preset.rs:248`](../../core/dr-pipeline/src/preset.rs#L248), [`core/dr-pipeline/src/preset.rs:739`](../../core/dr-pipeline/src/preset.rs#L739), [`core/dr-pipeline/src/preset.rs:828`](../../core/dr-pipeline/src/preset.rs#L828), [`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:760`](../../ui/dr-ui/src/develop/session.rs#L760), [`ui/dr-ui/src/develop/session.rs:780`](../../ui/dr-ui/src/develop/session.rs#L780), [`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:916`](../../ui/dr-ui/src/lib.rs#L916), [`ui/dr-ui/src/lib.rs:981`](../../ui/dr-ui/src/lib.rs#L981), [`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:1933`](../../ui/dr-ui/src/presets.rs#L1933), [`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/lib.rs:30`](../../core/dr-denoise/src/lib.rs#L30), [`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/repair.rs:1`](../../core/dr-denoise/src/repair.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:2146`](../../core/dr-pipeline/src/graph.rs#L2146), [`core/dr-pipeline/src/graph.rs:2175`](../../core/dr-pipeline/src/graph.rs#L2175), [`core/dr-pipeline/src/graph.rs:2198`](../../core/dr-pipeline/src/graph.rs#L2198), [`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:437`](../../core/dr-pipeline/src/graph.rs#L437), [`core/dr-pipeline/src/graph.rs:625`](../../core/dr-pipeline/src/graph.rs#L625), [`core/dr-pipeline/src/learned_denoise.rs:1`](../../core/dr-pipeline/src/learned_denoise.rs#L1), [`core/dr-pipeline/src/learned_denoise.rs:20`](../../core/dr-pipeline/src/learned_denoise.rs#L20), [`core/dr-pipeline/src/learned_denoise.rs:27`](../../core/dr-pipeline/src/learned_denoise.rs#L27), [`core/dr-pipeline/src/learned_denoise.rs:36`](../../core/dr-pipeline/src/learned_denoise.rs#L36), [`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/denoise.rs:328`](../../ui/dr-ui/src/develop/denoise.rs#L328), [`ui/dr-ui/src/develop/denoise.rs:99`](../../ui/dr-ui/src/develop/denoise.rs#L99), [`ui/dr-ui/src/develop/denoise_cache.rs:1`](../../ui/dr-ui/src/develop/denoise_cache.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:126`](../../ui/dr-ui/src/develop/session.rs#L126), [`ui/dr-ui/src/develop/session.rs:389`](../../ui/dr-ui/src/develop/session.rs#L389), [`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:392`](../../ui/dr-ui/src/library/paths.rs#L392), [`ui/dr-ui/src/library/paths.rs:407`](../../ui/dr-ui/src/library/paths.rs#L407) | | 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/camera_profile.rs:209`](../../core/dr-gpu/tests/camera_profile.rs#L209), [`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:114`](../../core/dr-gpu/tests/view_transform.rs#L114), [`core/dr-gpu/tests/view_transform.rs:137`](../../core/dr-gpu/tests/view_transform.rs#L137), [`core/dr-gpu/tests/view_transform.rs:163`](../../core/dr-gpu/tests/view_transform.rs#L163), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:201`](../../core/dr-gpu/tests/view_transform.rs#L201), [`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:56`](../../core/dr-pipeline/src/camera_raw.rs#L56), [`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:393`](../../core/dr-pipeline/src/ops/camera_profile.rs#L393), [`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:224`](../../core/dr-pipeline/src/ops/view_transform.rs#L224), [`core/dr-pipeline/src/ops/view_transform.rs:36`](../../core/dr-pipeline/src/ops/view_transform.rs#L36), [`core/dr-pipeline/src/view.rs:195`](../../core/dr-pipeline/src/view.rs#L195), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:208`](../../core/dr-pipeline/src/view.rs#L208), [`core/dr-pipeline/src/view.rs:222`](../../core/dr-pipeline/src/view.rs#L222), [`core/dr-pipeline/src/view.rs:238`](../../core/dr-pipeline/src/view.rs#L238), [`core/dr-pipeline/src/view.rs:254`](../../core/dr-pipeline/src/view.rs#L254), [`core/dr-pipeline/src/view.rs:265`](../../core/dr-pipeline/src/view.rs#L265), [`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:1604`](../../core/dr-pipeline/src/graph.rs#L1604), [`core/dr-pipeline/src/graph.rs:710`](../../core/dr-pipeline/src/graph.rs#L710), [`core/dr-pipeline/src/graph.rs:770`](../../core/dr-pipeline/src/graph.rs#L770), [`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:100`](../../ui/dr-ui/src/develop/session.rs#L100), [`ui/dr-ui/src/develop/session.rs:91`](../../ui/dr-ui/src/develop/session.rs#L91), [`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:312`](../../ui/dr-ui/src/labels.rs#L312), [`ui/dr-ui/src/labels.rs:34`](../../ui/dr-ui/src/labels.rs#L34), [`ui/dr-ui/src/lib.rs:2205`](../../ui/dr-ui/src/lib.rs#L2205), [`ui/dr-ui/src/lib.rs:2210`](../../ui/dr-ui/src/lib.rs#L2210), [`ui/dr-ui/src/lib.rs:2242`](../../ui/dr-ui/src/lib.rs#L2242), [`ui/dr-ui/src/lib.rs:2251`](../../ui/dr-ui/src/lib.rs#L2251), [`ui/dr-ui/src/lib.rs:2268`](../../ui/dr-ui/src/lib.rs#L2268), [`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:2155`](../../ui/dr-ui/src/presets.rs#L2155), [`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-5 | [`core/dr-pipeline/src/graph.rs:1623`](../../core/dr-pipeline/src/graph.rs#L1623), [`core/dr-pipeline/src/graph.rs:716`](../../core/dr-pipeline/src/graph.rs#L716), [`core/dr-pipeline/src/graph.rs:776`](../../core/dr-pipeline/src/graph.rs#L776), [`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:100`](../../ui/dr-ui/src/develop/session.rs#L100), [`ui/dr-ui/src/develop/session.rs:91`](../../ui/dr-ui/src/develop/session.rs#L91), [`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:318`](../../ui/dr-ui/src/labels.rs#L318), [`ui/dr-ui/src/labels.rs:34`](../../ui/dr-ui/src/labels.rs#L34), [`ui/dr-ui/src/lib.rs:2205`](../../ui/dr-ui/src/lib.rs#L2205), [`ui/dr-ui/src/lib.rs:2210`](../../ui/dr-ui/src/lib.rs#L2210), [`ui/dr-ui/src/lib.rs:2242`](../../ui/dr-ui/src/lib.rs#L2242), [`ui/dr-ui/src/lib.rs:2251`](../../ui/dr-ui/src/lib.rs#L2251), [`ui/dr-ui/src/lib.rs:2268`](../../ui/dr-ui/src/lib.rs#L2268), [`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:2155`](../../ui/dr-ui/src/presets.rs#L2155), [`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:1343`](../../core/dr-pipeline/src/preset.rs#L1343), [`core/dr-pipeline/src/preset.rs:1353`](../../core/dr-pipeline/src/preset.rs#L1353), [`core/dr-pipeline/src/preset.rs:1362`](../../core/dr-pipeline/src/preset.rs#L1362), [`core/dr-pipeline/src/preset.rs:1378`](../../core/dr-pipeline/src/preset.rs#L1378), [`core/dr-pipeline/src/preset.rs:1390`](../../core/dr-pipeline/src/preset.rs#L1390), [`core/dr-pipeline/src/preset.rs:1406`](../../core/dr-pipeline/src/preset.rs#L1406), [`core/dr-pipeline/src/preset.rs:1432`](../../core/dr-pipeline/src/preset.rs#L1432), [`core/dr-pipeline/src/preset.rs:1454`](../../core/dr-pipeline/src/preset.rs#L1454), [`core/dr-pipeline/src/preset.rs:1468`](../../core/dr-pipeline/src/preset.rs#L1468), [`core/dr-pipeline/src/preset.rs:1486`](../../core/dr-pipeline/src/preset.rs#L1486), [`core/dr-pipeline/src/preset.rs:1670`](../../core/dr-pipeline/src/preset.rs#L1670), [`core/dr-pipeline/src/preset.rs:1685`](../../core/dr-pipeline/src/preset.rs#L1685), [`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-pipeline/src/preset.rs:678`](../../core/dr-pipeline/src/preset.rs#L678), [`core/dr-preset-xmp/src/lib.rs:148`](../../core/dr-preset-xmp/src/lib.rs#L148), [`core/dr-preset-xmp/src/lib.rs:1`](../../core/dr-preset-xmp/src/lib.rs#L1), [`core/dr-preset-xmp/src/lib.rs:460`](../../core/dr-preset-xmp/src/lib.rs#L460), [`core/dr-preset-xmp/src/lib.rs:671`](../../core/dr-preset-xmp/src/lib.rs#L671), [`core/dr-preset-xmp/src/lib.rs:699`](../../core/dr-preset-xmp/src/lib.rs#L699), [`core/dr-preset-xmp/src/lib.rs:854`](../../core/dr-preset-xmp/src/lib.rs#L854), [`core/dr-types/src/settings.rs:456`](../../core/dr-types/src/settings.rs#L456), [`ui/dr-ui/src/derived_sync.rs:1142`](../../ui/dr-ui/src/derived_sync.rs#L1142), [`ui/dr-ui/src/derived_sync.rs:1160`](../../ui/dr-ui/src/derived_sync.rs#L1160), [`ui/dr-ui/src/derived_sync.rs:2134`](../../ui/dr-ui/src/derived_sync.rs#L2134), [`ui/dr-ui/src/derived_sync.rs:2169`](../../ui/dr-ui/src/derived_sync.rs#L2169), [`ui/dr-ui/src/derived_sync.rs:254`](../../ui/dr-ui/src/derived_sync.rs#L254), [`ui/dr-ui/src/derived_sync.rs:99`](../../ui/dr-ui/src/derived_sync.rs#L99), [`ui/dr-ui/src/develop/session.rs:619`](../../ui/dr-ui/src/develop/session.rs#L619), [`ui/dr-ui/src/develop/session.rs:625`](../../ui/dr-ui/src/develop/session.rs#L625), [`ui/dr-ui/src/develop/session.rs:732`](../../ui/dr-ui/src/develop/session.rs#L732), [`ui/dr-ui/src/develop/session.rs:753`](../../ui/dr-ui/src/develop/session.rs#L753), [`ui/dr-ui/src/develop/session.rs:79`](../../ui/dr-ui/src/develop/session.rs#L79), [`ui/dr-ui/src/develop/session.rs:926`](../../ui/dr-ui/src/develop/session.rs#L926), [`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/export.rs:1322`](../../ui/dr-ui/src/export.rs#L1322), [`ui/dr-ui/src/labels.rs:30`](../../ui/dr-ui/src/labels.rs#L30), [`ui/dr-ui/src/lib.rs:1335`](../../ui/dr-ui/src/lib.rs#L1335), [`ui/dr-ui/src/lib.rs:2662`](../../ui/dr-ui/src/lib.rs#L2662), [`ui/dr-ui/src/lib.rs:337`](../../ui/dr-ui/src/lib.rs#L337), [`ui/dr-ui/src/lib.rs:880`](../../ui/dr-ui/src/lib.rs#L880), [`ui/dr-ui/src/lib.rs:898`](../../ui/dr-ui/src/lib.rs#L898), [`ui/dr-ui/src/library/paths.rs:42`](../../ui/dr-ui/src/library/paths.rs#L42), [`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/thumbnails_fetch.rs:549`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L549), [`ui/dr-ui/src/library_ui/controller.rs:293`](../../ui/dr-ui/src/library_ui/controller.rs#L293), [`ui/dr-ui/src/library_ui/controller.rs:704`](../../ui/dr-ui/src/library_ui/controller.rs#L704), [`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/sync.rs:246`](../../ui/dr-ui/src/library_ui/sync.rs#L246), [`ui/dr-ui/src/library_ui/window.rs:835`](../../ui/dr-ui/src/library_ui/window.rs#L835), [`ui/dr-ui/src/preset_store.rs:1`](../../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/presets.rs:1036`](../../ui/dr-ui/src/presets.rs#L1036), [`ui/dr-ui/src/presets.rs:1933`](../../ui/dr-ui/src/presets.rs#L1933), [`ui/dr-ui/src/presets.rs:1`](../../ui/dr-ui/src/presets.rs#L1), [`ui/dr-ui/src/presets.rs:2020`](../../ui/dr-ui/src/presets.rs#L2020), [`ui/dr-ui/src/presets.rs:2043`](../../ui/dr-ui/src/presets.rs#L2043), [`ui/dr-ui/src/presets.rs:707`](../../ui/dr-ui/src/presets.rs#L707), [`ui/dr-ui/src/presets.rs:754`](../../ui/dr-ui/src/presets.rs#L754), [`ui/dr-ui/src/presets.rs:783`](../../ui/dr-ui/src/presets.rs#L783), [`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) | | FR-DEV-7 | [`core/dr-pipeline/src/history.rs:214`](../../core/dr-pipeline/src/history.rs#L214), [`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), [`ui/dr-ui/src/develop/history.rs:107`](../../ui/dr-ui/src/develop/history.rs#L107), [`ui/dr-ui/src/develop/history.rs:124`](../../ui/dr-ui/src/develop/history.rs#L124), [`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:359`](../../ui/dr-ui/src/develop/history.rs#L359), [`ui/dr-ui/src/develop/render.rs:1115`](../../ui/dr-ui/src/develop/render.rs#L1115), [`ui/dr-ui/src/develop/render.rs:586`](../../ui/dr-ui/src/develop/render.rs#L586), [`ui/dr-ui/src/develop/render.rs:627`](../../ui/dr-ui/src/develop/render.rs#L627), [`ui/dr-ui/src/develop/session.rs:116`](../../ui/dr-ui/src/develop/session.rs#L116), [`ui/dr-ui/src/develop_ui.rs:793`](../../ui/dr-ui/src/develop_ui.rs#L793), [`ui/dr-ui/src/develop_ui.rs:852`](../../ui/dr-ui/src/develop_ui.rs#L852), [`ui/dr-ui/src/develop_ui.rs:924`](../../ui/dr-ui/src/develop_ui.rs#L924), [`ui/dr-ui/src/lib.rs:2251`](../../ui/dr-ui/src/lib.rs#L2251), [`ui/dr-ui/src/lib.rs:2337`](../../ui/dr-ui/src/lib.rs#L2337), [`ui/dr-ui/src/lib.rs:2351`](../../ui/dr-ui/src/lib.rs#L2351), [`ui/dr-ui/src/lib.rs:464`](../../ui/dr-ui/src/lib.rs#L464), [`ui/dr-ui/ui/app.slint:224`](../../ui/dr-ui/ui/app.slint#L224), [`ui/dr-ui/ui/app.slint:2417`](../../ui/dr-ui/ui/app.slint#L2417), [`ui/dr-ui/ui/app.slint:2463`](../../ui/dr-ui/ui/app.slint#L2463), [`ui/dr-ui/ui/app.slint:3027`](../../ui/dr-ui/ui/app.slint#L3027), [`ui/dr-ui/ui/history.slint:103`](../../ui/dr-ui/ui/history.slint#L103), [`ui/dr-ui/ui/history.slint:1`](../../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:227`](../../ui/dr-ui/ui/history.slint#L227), [`ui/dr-ui/ui/history.slint:53`](../../ui/dr-ui/ui/history.slint#L53), [`ui/dr-ui/ui/widgets.slint:72`](../../ui/dr-ui/ui/widgets.slint#L72) | -| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:397`](../../core/dr-gpu/src/detail.rs#L397), [`core/dr-gpu/src/detail.rs:609`](../../core/dr-gpu/src/detail.rs#L609), [`core/dr-gpu/tests/detail_instances.rs:1`](../../core/dr-gpu/tests/detail_instances.rs#L1), [`core/dr-gpu/tests/spot_removal.rs:1`](../../core/dr-gpu/tests/spot_removal.rs#L1), [`core/dr-pipeline/src/detail.rs:449`](../../core/dr-pipeline/src/detail.rs#L449), [`core/dr-pipeline/src/detail.rs:491`](../../core/dr-pipeline/src/detail.rs#L491), [`core/dr-pipeline/src/detail.rs:526`](../../core/dr-pipeline/src/detail.rs#L526), [`core/dr-pipeline/src/detail.rs:620`](../../core/dr-pipeline/src/detail.rs#L620), [`core/dr-pipeline/src/graph.rs:122`](../../core/dr-pipeline/src/graph.rs#L122), [`core/dr-pipeline/src/graph.rs:1243`](../../core/dr-pipeline/src/graph.rs#L1243), [`core/dr-pipeline/src/graph.rs:269`](../../core/dr-pipeline/src/graph.rs#L269), [`core/dr-pipeline/src/operation.rs:377`](../../core/dr-pipeline/src/operation.rs#L377), [`core/dr-pipeline/src/operation.rs:869`](../../core/dr-pipeline/src/operation.rs#L869), [`core/dr-pipeline/src/sidecar.rs:1104`](../../core/dr-pipeline/src/sidecar.rs#L1104), [`core/dr-pipeline/src/sidecar.rs:1158`](../../core/dr-pipeline/src/sidecar.rs#L1158), [`core/dr-pipeline/src/sidecar.rs:1188`](../../core/dr-pipeline/src/sidecar.rs#L1188), [`core/dr-pipeline/src/sidecar.rs:233`](../../core/dr-pipeline/src/sidecar.rs#L233), [`core/dr-pipeline/src/sidecar.rs:410`](../../core/dr-pipeline/src/sidecar.rs#L410), [`core/dr-pipeline/src/sidecar.rs:910`](../../core/dr-pipeline/src/sidecar.rs#L910), [`core/dr-pipeline/src/spot.rs:115`](../../core/dr-pipeline/src/spot.rs#L115), [`core/dr-pipeline/src/spot.rs:151`](../../core/dr-pipeline/src/spot.rs#L151), [`core/dr-pipeline/src/spot.rs:1`](../../core/dr-pipeline/src/spot.rs#L1), [`core/dr-pipeline/src/spot.rs:207`](../../core/dr-pipeline/src/spot.rs#L207), [`core/dr-pipeline/src/spot.rs:387`](../../core/dr-pipeline/src/spot.rs#L387), [`core/dr-pipeline/src/spot.rs:472`](../../core/dr-pipeline/src/spot.rs#L472), [`core/dr-pipeline/src/spot.rs:582`](../../core/dr-pipeline/src/spot.rs#L582), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`core/dr-pipeline/src/state.rs:103`](../../core/dr-pipeline/src/state.rs#L103), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-pipeline/tests/spots.rs:1`](../../core/dr-pipeline/tests/spots.rs#L1), [`ui/dr-ui/src/develop/repairs.rs:114`](../../ui/dr-ui/src/develop/repairs.rs#L114), [`ui/dr-ui/src/develop/repairs.rs:11`](../../ui/dr-ui/src/develop/repairs.rs#L11), [`ui/dr-ui/src/develop/repairs.rs:197`](../../ui/dr-ui/src/develop/repairs.rs#L197), [`ui/dr-ui/src/develop/repairs.rs:211`](../../ui/dr-ui/src/develop/repairs.rs#L211), [`ui/dr-ui/src/develop/repairs.rs:49`](../../ui/dr-ui/src/develop/repairs.rs#L49), [`ui/dr-ui/src/develop/session.rs:244`](../../ui/dr-ui/src/develop/session.rs#L244), [`ui/dr-ui/src/develop_ui.rs:1081`](../../ui/dr-ui/src/develop_ui.rs#L1081), [`ui/dr-ui/src/labels.rs:83`](../../ui/dr-ui/src/labels.rs#L83), [`ui/dr-ui/src/lib.rs:2295`](../../ui/dr-ui/src/lib.rs#L2295), [`ui/dr-ui/src/lib.rs:507`](../../ui/dr-ui/src/lib.rs#L507), [`ui/dr-ui/src/spots_ui.rs:19`](../../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/src/spots_ui.rs:1`](../../ui/dr-ui/src/spots_ui.rs#L1), [`ui/dr-ui/src/spots_ui.rs:265`](../../ui/dr-ui/src/spots_ui.rs#L265), [`ui/dr-ui/ui/app.slint:2270`](../../ui/dr-ui/ui/app.slint#L2270), [`ui/dr-ui/ui/app.slint:2513`](../../ui/dr-ui/ui/app.slint#L2513), [`ui/dr-ui/ui/app.slint:3376`](../../ui/dr-ui/ui/app.slint#L3376), [`ui/dr-ui/ui/icons.slint:378`](../../ui/dr-ui/ui/icons.slint#L378), [`ui/dr-ui/ui/session.slint:102`](../../ui/dr-ui/ui/session.slint#L102), [`ui/dr-ui/ui/session.slint:52`](../../ui/dr-ui/ui/session.slint#L52), [`ui/dr-ui/ui/spots.slint:191`](../../ui/dr-ui/ui/spots.slint#L191), [`ui/dr-ui/ui/spots.slint:49`](../../ui/dr-ui/ui/spots.slint#L49), [`ui/dr-ui/ui/spots.slint:6`](../../ui/dr-ui/ui/spots.slint#L6), [`ui/dr-ui/ui/spots.slint:91`](../../ui/dr-ui/ui/spots.slint#L91) | -| FR-DSP-1 | [`core/dr-gpu/src/adjust.rs:1107`](../../core/dr-gpu/src/adjust.rs#L1107), [`core/dr-gpu/src/adjust.rs:2883`](../../core/dr-gpu/src/adjust.rs#L2883), [`core/dr-gpu/src/adjust.rs:2960`](../../core/dr-gpu/src/adjust.rs#L2960), [`core/dr-gpu/src/adjust.rs:3045`](../../core/dr-gpu/src/adjust.rs#L3045), [`core/dr-gpu/src/adjust.rs:44`](../../core/dr-gpu/src/adjust.rs#L44), [`core/dr-gpu/src/lib.rs:176`](../../core/dr-gpu/src/lib.rs#L176), [`core/dr-gpu/src/lib.rs:196`](../../core/dr-gpu/src/lib.rs#L196), [`core/dr-gpu/src/lib.rs:74`](../../core/dr-gpu/src/lib.rs#L74), [`core/dr-gpu/src/lib.rs:97`](../../core/dr-gpu/src/lib.rs#L97), [`core/dr-gpu/tests/capture_sharpen.rs:199`](../../core/dr-gpu/tests/capture_sharpen.rs#L199), [`core/dr-gpu/tests/detail_stage.rs:327`](../../core/dr-gpu/tests/detail_stage.rs#L327), [`core/dr-gpu/tests/local_contrast.rs:263`](../../core/dr-gpu/tests/local_contrast.rs#L263), [`core/dr-gpu/tests/noise_reduction.rs:377`](../../core/dr-gpu/tests/noise_reduction.rs#L377), [`core/dr-pipeline/src/detail.rs:142`](../../core/dr-pipeline/src/detail.rs#L142), [`core/dr-pipeline/src/detail.rs:231`](../../core/dr-pipeline/src/detail.rs#L231), [`core/dr-pipeline/src/detail.rs:592`](../../core/dr-pipeline/src/detail.rs#L592), [`core/dr-pipeline/src/detail.rs:980`](../../core/dr-pipeline/src/detail.rs#L980), [`core/dr-pipeline/src/graph.rs:1084`](../../core/dr-pipeline/src/graph.rs#L1084), [`core/dr-pipeline/src/graph.rs:1114`](../../core/dr-pipeline/src/graph.rs#L1114), [`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:628`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L628), [`core/dr-pipeline/src/ops/dehaze.rs:1`](../../core/dr-pipeline/src/ops/dehaze.rs#L1), [`core/dr-pipeline/src/ops/dehaze.rs:564`](../../core/dr-pipeline/src/ops/dehaze.rs#L564), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/local_contrast.rs:970`](../../core/dr-pipeline/src/ops/local_contrast.rs#L970), [`core/dr-pipeline/src/ops/noise_reduction.rs:694`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L694), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`ui/dr-ui/src/develop/framing.rs:640`](../../ui/dr-ui/src/develop/framing.rs#L640), [`ui/dr-ui/src/develop/mod.rs:58`](../../ui/dr-ui/src/develop/mod.rs#L58), [`ui/dr-ui/src/develop/render.rs:1172`](../../ui/dr-ui/src/develop/render.rs#L1172), [`ui/dr-ui/src/develop/render.rs:1206`](../../ui/dr-ui/src/develop/render.rs#L1206), [`ui/dr-ui/src/develop/render.rs:1344`](../../ui/dr-ui/src/develop/render.rs#L1344), [`ui/dr-ui/src/develop/render.rs:315`](../../ui/dr-ui/src/develop/render.rs#L315), [`ui/dr-ui/src/develop/render.rs:97`](../../ui/dr-ui/src/develop/render.rs#L97), [`ui/dr-ui/src/lib.rs:1137`](../../ui/dr-ui/src/lib.rs#L1137), [`ui/dr-ui/src/lib.rs:118`](../../ui/dr-ui/src/lib.rs#L118) | +| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:397`](../../core/dr-gpu/src/detail.rs#L397), [`core/dr-gpu/src/detail.rs:609`](../../core/dr-gpu/src/detail.rs#L609), [`core/dr-gpu/tests/detail_instances.rs:1`](../../core/dr-gpu/tests/detail_instances.rs#L1), [`core/dr-gpu/tests/spot_removal.rs:1`](../../core/dr-gpu/tests/spot_removal.rs#L1), [`core/dr-pipeline/src/detail.rs:449`](../../core/dr-pipeline/src/detail.rs#L449), [`core/dr-pipeline/src/detail.rs:491`](../../core/dr-pipeline/src/detail.rs#L491), [`core/dr-pipeline/src/detail.rs:526`](../../core/dr-pipeline/src/detail.rs#L526), [`core/dr-pipeline/src/detail.rs:620`](../../core/dr-pipeline/src/detail.rs#L620), [`core/dr-pipeline/src/graph.rs:122`](../../core/dr-pipeline/src/graph.rs#L122), [`core/dr-pipeline/src/graph.rs:1262`](../../core/dr-pipeline/src/graph.rs#L1262), [`core/dr-pipeline/src/graph.rs:269`](../../core/dr-pipeline/src/graph.rs#L269), [`core/dr-pipeline/src/operation.rs:377`](../../core/dr-pipeline/src/operation.rs#L377), [`core/dr-pipeline/src/operation.rs:869`](../../core/dr-pipeline/src/operation.rs#L869), [`core/dr-pipeline/src/sidecar.rs:1104`](../../core/dr-pipeline/src/sidecar.rs#L1104), [`core/dr-pipeline/src/sidecar.rs:1158`](../../core/dr-pipeline/src/sidecar.rs#L1158), [`core/dr-pipeline/src/sidecar.rs:1188`](../../core/dr-pipeline/src/sidecar.rs#L1188), [`core/dr-pipeline/src/sidecar.rs:233`](../../core/dr-pipeline/src/sidecar.rs#L233), [`core/dr-pipeline/src/sidecar.rs:410`](../../core/dr-pipeline/src/sidecar.rs#L410), [`core/dr-pipeline/src/sidecar.rs:910`](../../core/dr-pipeline/src/sidecar.rs#L910), [`core/dr-pipeline/src/spot.rs:115`](../../core/dr-pipeline/src/spot.rs#L115), [`core/dr-pipeline/src/spot.rs:151`](../../core/dr-pipeline/src/spot.rs#L151), [`core/dr-pipeline/src/spot.rs:1`](../../core/dr-pipeline/src/spot.rs#L1), [`core/dr-pipeline/src/spot.rs:207`](../../core/dr-pipeline/src/spot.rs#L207), [`core/dr-pipeline/src/spot.rs:387`](../../core/dr-pipeline/src/spot.rs#L387), [`core/dr-pipeline/src/spot.rs:472`](../../core/dr-pipeline/src/spot.rs#L472), [`core/dr-pipeline/src/spot.rs:582`](../../core/dr-pipeline/src/spot.rs#L582), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`core/dr-pipeline/src/state.rs:103`](../../core/dr-pipeline/src/state.rs#L103), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-pipeline/tests/spots.rs:1`](../../core/dr-pipeline/tests/spots.rs#L1), [`ui/dr-ui/src/develop/repairs.rs:114`](../../ui/dr-ui/src/develop/repairs.rs#L114), [`ui/dr-ui/src/develop/repairs.rs:11`](../../ui/dr-ui/src/develop/repairs.rs#L11), [`ui/dr-ui/src/develop/repairs.rs:197`](../../ui/dr-ui/src/develop/repairs.rs#L197), [`ui/dr-ui/src/develop/repairs.rs:211`](../../ui/dr-ui/src/develop/repairs.rs#L211), [`ui/dr-ui/src/develop/repairs.rs:49`](../../ui/dr-ui/src/develop/repairs.rs#L49), [`ui/dr-ui/src/develop/session.rs:244`](../../ui/dr-ui/src/develop/session.rs#L244), [`ui/dr-ui/src/develop_ui.rs:1081`](../../ui/dr-ui/src/develop_ui.rs#L1081), [`ui/dr-ui/src/labels.rs:83`](../../ui/dr-ui/src/labels.rs#L83), [`ui/dr-ui/src/lib.rs:2295`](../../ui/dr-ui/src/lib.rs#L2295), [`ui/dr-ui/src/lib.rs:507`](../../ui/dr-ui/src/lib.rs#L507), [`ui/dr-ui/src/spots_ui.rs:19`](../../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/src/spots_ui.rs:1`](../../ui/dr-ui/src/spots_ui.rs#L1), [`ui/dr-ui/src/spots_ui.rs:265`](../../ui/dr-ui/src/spots_ui.rs#L265), [`ui/dr-ui/ui/app.slint:2270`](../../ui/dr-ui/ui/app.slint#L2270), [`ui/dr-ui/ui/app.slint:2513`](../../ui/dr-ui/ui/app.slint#L2513), [`ui/dr-ui/ui/app.slint:3376`](../../ui/dr-ui/ui/app.slint#L3376), [`ui/dr-ui/ui/icons.slint:378`](../../ui/dr-ui/ui/icons.slint#L378), [`ui/dr-ui/ui/session.slint:102`](../../ui/dr-ui/ui/session.slint#L102), [`ui/dr-ui/ui/session.slint:52`](../../ui/dr-ui/ui/session.slint#L52), [`ui/dr-ui/ui/spots.slint:191`](../../ui/dr-ui/ui/spots.slint#L191), [`ui/dr-ui/ui/spots.slint:49`](../../ui/dr-ui/ui/spots.slint#L49), [`ui/dr-ui/ui/spots.slint:6`](../../ui/dr-ui/ui/spots.slint#L6), [`ui/dr-ui/ui/spots.slint:91`](../../ui/dr-ui/ui/spots.slint#L91) | +| FR-DSP-1 | [`core/dr-gpu/src/adjust.rs:1107`](../../core/dr-gpu/src/adjust.rs#L1107), [`core/dr-gpu/src/adjust.rs:2883`](../../core/dr-gpu/src/adjust.rs#L2883), [`core/dr-gpu/src/adjust.rs:2960`](../../core/dr-gpu/src/adjust.rs#L2960), [`core/dr-gpu/src/adjust.rs:3045`](../../core/dr-gpu/src/adjust.rs#L3045), [`core/dr-gpu/src/adjust.rs:44`](../../core/dr-gpu/src/adjust.rs#L44), [`core/dr-gpu/src/lib.rs:176`](../../core/dr-gpu/src/lib.rs#L176), [`core/dr-gpu/src/lib.rs:196`](../../core/dr-gpu/src/lib.rs#L196), [`core/dr-gpu/src/lib.rs:74`](../../core/dr-gpu/src/lib.rs#L74), [`core/dr-gpu/src/lib.rs:97`](../../core/dr-gpu/src/lib.rs#L97), [`core/dr-gpu/tests/capture_sharpen.rs:199`](../../core/dr-gpu/tests/capture_sharpen.rs#L199), [`core/dr-gpu/tests/detail_stage.rs:327`](../../core/dr-gpu/tests/detail_stage.rs#L327), [`core/dr-gpu/tests/local_contrast.rs:263`](../../core/dr-gpu/tests/local_contrast.rs#L263), [`core/dr-gpu/tests/noise_reduction.rs:377`](../../core/dr-gpu/tests/noise_reduction.rs#L377), [`core/dr-pipeline/src/detail.rs:142`](../../core/dr-pipeline/src/detail.rs#L142), [`core/dr-pipeline/src/detail.rs:231`](../../core/dr-pipeline/src/detail.rs#L231), [`core/dr-pipeline/src/detail.rs:592`](../../core/dr-pipeline/src/detail.rs#L592), [`core/dr-pipeline/src/detail.rs:980`](../../core/dr-pipeline/src/detail.rs#L980), [`core/dr-pipeline/src/graph.rs:1103`](../../core/dr-pipeline/src/graph.rs#L1103), [`core/dr-pipeline/src/graph.rs:1133`](../../core/dr-pipeline/src/graph.rs#L1133), [`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:628`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L628), [`core/dr-pipeline/src/ops/dehaze.rs:1`](../../core/dr-pipeline/src/ops/dehaze.rs#L1), [`core/dr-pipeline/src/ops/dehaze.rs:564`](../../core/dr-pipeline/src/ops/dehaze.rs#L564), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/local_contrast.rs:970`](../../core/dr-pipeline/src/ops/local_contrast.rs#L970), [`core/dr-pipeline/src/ops/noise_reduction.rs:694`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L694), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`ui/dr-ui/src/develop/framing.rs:640`](../../ui/dr-ui/src/develop/framing.rs#L640), [`ui/dr-ui/src/develop/mod.rs:58`](../../ui/dr-ui/src/develop/mod.rs#L58), [`ui/dr-ui/src/develop/render.rs:1172`](../../ui/dr-ui/src/develop/render.rs#L1172), [`ui/dr-ui/src/develop/render.rs:1206`](../../ui/dr-ui/src/develop/render.rs#L1206), [`ui/dr-ui/src/develop/render.rs:1344`](../../ui/dr-ui/src/develop/render.rs#L1344), [`ui/dr-ui/src/develop/render.rs:315`](../../ui/dr-ui/src/develop/render.rs#L315), [`ui/dr-ui/src/develop/render.rs:97`](../../ui/dr-ui/src/develop/render.rs#L97), [`ui/dr-ui/src/lib.rs:1137`](../../ui/dr-ui/src/lib.rs#L1137), [`ui/dr-ui/src/lib.rs:118`](../../ui/dr-ui/src/lib.rs#L118) | | FR-DSP-2 | [`core/dr-gpu/src/adjust.rs:1419`](../../core/dr-gpu/src/adjust.rs#L1419), [`core/dr-gpu/src/demosaic.rs:122`](../../core/dr-gpu/src/demosaic.rs#L122), [`core/dr-gpu/src/demosaic.rs:169`](../../core/dr-gpu/src/demosaic.rs#L169), [`core/dr-gpu/src/demosaic.rs:451`](../../core/dr-gpu/src/demosaic.rs#L451), [`core/dr-gpu/tests/source_window.rs:1`](../../core/dr-gpu/tests/source_window.rs#L1), [`core/dr-pipeline/src/detail.rs:231`](../../core/dr-pipeline/src/detail.rs#L231), [`core/dr-pipeline/src/detail.rs:571`](../../core/dr-pipeline/src/detail.rs#L571), [`core/dr-pipeline/src/detail.rs:980`](../../core/dr-pipeline/src/detail.rs#L980), [`core/dr-pipeline/src/graph.rs:317`](../../core/dr-pipeline/src/graph.rs#L317), [`core/dr-pipeline/src/graph.rs:86`](../../core/dr-pipeline/src/graph.rs#L86), [`core/dr-pipeline/src/operation.rs:1794`](../../core/dr-pipeline/src/operation.rs#L1794), [`core/dr-pipeline/src/operation.rs:2522`](../../core/dr-pipeline/src/operation.rs#L2522), [`core/dr-pipeline/src/operation.rs:615`](../../core/dr-pipeline/src/operation.rs#L615), [`core/dr-pipeline/src/tiles.rs:1`](../../core/dr-pipeline/src/tiles.rs#L1), [`ui/dr-ui/src/develop/render.rs:1894`](../../ui/dr-ui/src/develop/render.rs#L1894), [`ui/dr-ui/src/develop/render.rs:1973`](../../ui/dr-ui/src/develop/render.rs#L1973), [`ui/dr-ui/src/develop/render.rs:216`](../../ui/dr-ui/src/develop/render.rs#L216), [`ui/dr-ui/src/develop/render.rs:23`](../../ui/dr-ui/src/develop/render.rs#L23), [`ui/dr-ui/src/develop/render.rs:770`](../../ui/dr-ui/src/develop/render.rs#L770), [`ui/dr-ui/src/develop/session.rs:130`](../../ui/dr-ui/src/develop/session.rs#L130), [`ui/dr-ui/src/develop/session.rs:343`](../../ui/dr-ui/src/develop/session.rs#L343), [`ui/dr-ui/src/develop/session.rs:370`](../../ui/dr-ui/src/develop/session.rs#L370) | | FR-DSP-3 | [`core/dr-gpu/tests/frame_budget.rs:101`](../../core/dr-gpu/tests/frame_budget.rs#L101), [`core/dr-gpu/tests/local_contrast.rs:328`](../../core/dr-gpu/tests/local_contrast.rs#L328), [`core/dr-pipeline/src/ops/local_contrast.rs:447`](../../core/dr-pipeline/src/ops/local_contrast.rs#L447) | | FR-DSP-4 | [`ui/dr-ui/src/lib.rs:2360`](../../ui/dr-ui/src/lib.rs#L2360), [`ui/dr-ui/src/lib.rs:2546`](../../ui/dr-ui/src/lib.rs#L2546), [`ui/dr-ui/src/refine.rs:1`](../../ui/dr-ui/src/refine.rs#L1), [`ui/dr-ui/ui/app.slint:112`](../../ui/dr-ui/ui/app.slint#L112), [`ui/dr-ui/ui/app.slint:1863`](../../ui/dr-ui/ui/app.slint#L1863), [`ui/dr-ui/ui/histogram.slint:182`](../../ui/dr-ui/ui/histogram.slint#L182), [`ui/dr-ui/ui/histogram.slint:250`](../../ui/dr-ui/ui/histogram.slint#L250) | @@ -100,7 +100,7 @@ _None._ | FR-DSP-8 | [`platform/dr-plat/src/display.rs:1`](../../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/display/icc.rs:1`](../../platform/dr-plat/src/display/icc.rs#L1), [`platform/dr-plat/src/display/wayland.rs:1`](../../platform/dr-plat/src/display/wayland.rs#L1), [`platform/dr-plat/src/display/x11.rs:1`](../../platform/dr-plat/src/display/x11.rs#L1), [`ui/dr-ui/src/develop/render.rs:1305`](../../ui/dr-ui/src/develop/render.rs#L1305), [`ui/dr-ui/src/develop/render.rs:1752`](../../ui/dr-ui/src/develop/render.rs#L1752), [`ui/dr-ui/src/develop/render.rs:1798`](../../ui/dr-ui/src/develop/render.rs#L1798), [`ui/dr-ui/src/develop/render.rs:1817`](../../ui/dr-ui/src/develop/render.rs#L1817), [`ui/dr-ui/src/develop/render.rs:291`](../../ui/dr-ui/src/develop/render.rs#L291), [`ui/dr-ui/src/develop/render.rs:350`](../../ui/dr-ui/src/develop/render.rs#L350), [`ui/dr-ui/src/develop/render.rs:65`](../../ui/dr-ui/src/develop/render.rs#L65), [`ui/dr-ui/src/develop/session.rs:297`](../../ui/dr-ui/src/develop/session.rs#L297), [`ui/dr-ui/src/display_ui.rs:192`](../../ui/dr-ui/src/display_ui.rs#L192), [`ui/dr-ui/src/display_ui.rs:1`](../../ui/dr-ui/src/display_ui.rs#L1), [`ui/dr-ui/src/display_ui.rs:325`](../../ui/dr-ui/src/display_ui.rs#L325), [`ui/dr-ui/src/display_ui.rs:346`](../../ui/dr-ui/src/display_ui.rs#L346), [`ui/dr-ui/src/display_ui.rs:379`](../../ui/dr-ui/src/display_ui.rs#L379), [`ui/dr-ui/src/lib.rs:1357`](../../ui/dr-ui/src/lib.rs#L1357), [`ui/dr-ui/src/lib.rs:2227`](../../ui/dr-ui/src/lib.rs#L2227), [`ui/dr-ui/src/lib.rs:3092`](../../ui/dr-ui/src/lib.rs#L3092), [`ui/dr-ui/src/lib.rs:3115`](../../ui/dr-ui/src/lib.rs#L3115), [`ui/dr-ui/ui/app.slint:130`](../../ui/dr-ui/ui/app.slint#L130), [`ui/dr-ui/ui/app.slint:1849`](../../ui/dr-ui/ui/app.slint#L1849), [`ui/dr-ui/ui/settings.slint:176`](../../ui/dr-ui/ui/settings.slint#L176), [`ui/dr-ui/ui/settings.slint:864`](../../ui/dr-ui/ui/settings.slint#L864) | | FR-EXP-1 | [`core/dr-export/src/encode.rs:1`](../../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-10 | [`core/dr-catalog/src/albums.rs:1`](../../core/dr-catalog/src/albums.rs#L1), [`core/dr-types/src/settings.rs:744`](../../core/dr-types/src/settings.rs#L744), [`ui/dr-ui/src/albums_ui.rs:1`](../../ui/dr-ui/src/albums_ui.rs#L1), [`ui/dr-ui/src/collections_ui/controller.rs:129`](../../ui/dr-ui/src/collections_ui/controller.rs#L129), [`ui/dr-ui/src/collections_ui/controller.rs:432`](../../ui/dr-ui/src/collections_ui/controller.rs#L432), [`ui/dr-ui/src/develop_ui.rs:353`](../../ui/dr-ui/src/develop_ui.rs#L353), [`ui/dr-ui/src/export.rs:100`](../../ui/dr-ui/src/export.rs#L100), [`ui/dr-ui/src/export.rs:240`](../../ui/dr-ui/src/export.rs#L240), [`ui/dr-ui/src/export.rs:679`](../../ui/dr-ui/src/export.rs#L679), [`ui/dr-ui/src/export.rs:949`](../../ui/dr-ui/src/export.rs#L949), [`ui/dr-ui/src/lib.rs:1737`](../../ui/dr-ui/src/lib.rs#L1737), [`ui/dr-ui/src/library_ui/controller.rs:1001`](../../ui/dr-ui/src/library_ui/controller.rs#L1001), [`ui/dr-ui/src/library_ui/controller.rs:224`](../../ui/dr-ui/src/library_ui/controller.rs#L224), [`ui/dr-ui/src/library_ui/controller.rs:961`](../../ui/dr-ui/src/library_ui/controller.rs#L961), [`ui/dr-ui/src/library_ui/window.rs:400`](../../ui/dr-ui/src/library_ui/window.rs#L400), [`ui/dr-ui/src/saf.rs:1`](../../ui/dr-ui/src/saf.rs#L1), [`ui/dr-ui/ui/albums.slint:1`](../../ui/dr-ui/ui/albums.slint#L1), [`ui/dr-ui/ui/app.slint:3610`](../../ui/dr-ui/ui/app.slint#L3610), [`ui/dr-ui/ui/collections.slint:789`](../../ui/dr-ui/ui/collections.slint#L789), [`ui/dr-ui/ui/export.slint:204`](../../ui/dr-ui/ui/export.slint#L204) | -| FR-EXP-2 | [`core/dr-export/src/encode.rs:1`](../../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/error.rs:26`](../../core/dr-export/src/error.rs#L26), [`core/dr-export/src/icc.rs:1`](../../core/dr-export/src/icc.rs#L1), [`core/dr-export/src/lib.rs:157`](../../core/dr-export/src/lib.rs#L157), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/lib.rs:57`](../../core/dr-export/src/lib.rs#L57), [`core/dr-gpu/src/adjust.rs:3318`](../../core/dr-gpu/src/adjust.rs#L3318), [`core/dr-pipeline/src/graph.rs:997`](../../core/dr-pipeline/src/graph.rs#L997), [`core/dr-pipeline/src/operation.rs:676`](../../core/dr-pipeline/src/operation.rs#L676), [`core/dr-types/src/colour.rs:1`](../../core/dr-types/src/colour.rs#L1), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`core/dr-types/src/settings.rs:989`](../../core/dr-types/src/settings.rs#L989), [`ui/dr-ui/src/develop/render.rs:1817`](../../ui/dr-ui/src/develop/render.rs#L1817), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | +| FR-EXP-2 | [`core/dr-export/src/encode.rs:1`](../../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/error.rs:26`](../../core/dr-export/src/error.rs#L26), [`core/dr-export/src/icc.rs:1`](../../core/dr-export/src/icc.rs#L1), [`core/dr-export/src/lib.rs:157`](../../core/dr-export/src/lib.rs#L157), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/lib.rs:57`](../../core/dr-export/src/lib.rs#L57), [`core/dr-gpu/src/adjust.rs:3318`](../../core/dr-gpu/src/adjust.rs#L3318), [`core/dr-pipeline/src/graph.rs:1016`](../../core/dr-pipeline/src/graph.rs#L1016), [`core/dr-pipeline/src/operation.rs:676`](../../core/dr-pipeline/src/operation.rs#L676), [`core/dr-types/src/colour.rs:1`](../../core/dr-types/src/colour.rs#L1), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`core/dr-types/src/settings.rs:989`](../../core/dr-types/src/settings.rs#L989), [`ui/dr-ui/src/develop/render.rs:1817`](../../ui/dr-ui/src/develop/render.rs#L1817), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-3 | [`core/dr-export/src/lib.rs:186`](../../core/dr-export/src/lib.rs#L186), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/size.rs:136`](../../core/dr-export/src/size.rs#L136), [`core/dr-export/src/size.rs:1`](../../core/dr-export/src/size.rs#L1), [`core/dr-export/src/size.rs:25`](../../core/dr-export/src/size.rs#L25), [`core/dr-export/src/size.rs:84`](../../core/dr-export/src/size.rs#L84), [`core/dr-types/src/settings.rs:1034`](../../core/dr-types/src/settings.rs#L1034), [`core/dr-types/src/settings.rs:1042`](../../core/dr-types/src/settings.rs#L1042), [`core/dr-types/src/settings.rs:1058`](../../core/dr-types/src/settings.rs#L1058), [`core/dr-types/src/settings.rs:1127`](../../core/dr-types/src/settings.rs#L1127), [`core/dr-types/src/settings.rs:1155`](../../core/dr-types/src/settings.rs#L1155), [`core/dr-types/src/settings.rs:1166`](../../core/dr-types/src/settings.rs#L1166), [`core/dr-types/src/settings.rs:1172`](../../core/dr-types/src/settings.rs#L1172), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/src/settings_ui.rs:256`](../../ui/dr-ui/src/settings_ui.rs#L256), [`ui/dr-ui/src/settings_ui.rs:269`](../../ui/dr-ui/src/settings_ui.rs#L269), [`ui/dr-ui/src/settings_ui.rs:288`](../../ui/dr-ui/src/settings_ui.rs#L288), [`ui/dr-ui/src/settings_ui.rs:701`](../../ui/dr-ui/src/settings_ui.rs#L701), [`ui/dr-ui/ui/export.slint:138`](../../ui/dr-ui/ui/export.slint#L138), [`ui/dr-ui/ui/export.slint:148`](../../ui/dr-ui/ui/export.slint#L148) | | FR-EXP-4 | [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/sharpen.rs:1`](../../core/dr-export/src/sharpen.rs#L1), [`core/dr-export/src/size.rs:1`](../../core/dr-export/src/size.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-5 | [`ui/dr-ui/src/settings_store.rs:1`](../../ui/dr-ui/src/settings_store.rs#L1) | @@ -112,7 +112,7 @@ _None._ | FR-MRG-1 | [`core/dr-pano/src/align.rs:1`](../../core/dr-pano/src/align.rs#L1), [`core/dr-pano/src/lib.rs:1`](../../core/dr-pano/src/lib.rs#L1), [`ui/dr-ui/src/lib.rs:2000`](../../ui/dr-ui/src/lib.rs#L2000), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1), [`ui/dr-ui/src/merge_ui.rs:1`](../../ui/dr-ui/src/merge_ui.rs#L1), [`ui/dr-ui/ui/app.slint:1533`](../../ui/dr-ui/ui/app.slint#L1533), [`ui/dr-ui/ui/app.slint:592`](../../ui/dr-ui/ui/app.slint#L592), [`ui/dr-ui/ui/library.slint:2049`](../../ui/dr-ui/ui/library.slint#L2049), [`ui/dr-ui/ui/library.slint:5197`](../../ui/dr-ui/ui/library.slint#L5197), [`ui/dr-ui/ui/merge.slint:1`](../../ui/dr-ui/ui/merge.slint#L1) | | FR-MRG-10 | [`core/dr-gpu/src/merge.rs:1`](../../core/dr-gpu/src/merge.rs#L1), [`core/dr-gpu/src/shaders/merge.wgsl:1`](../../core/dr-gpu/src/shaders/merge.wgsl#L1), [`core/dr-pano/src/lib.rs:1`](../../core/dr-pano/src/lib.rs#L1), [`core/dr-pano/src/seam.rs:1`](../../core/dr-pano/src/seam.rs#L1) | | FR-MRG-11 | [`core/dr-gpu/src/merge.rs:1`](../../core/dr-gpu/src/merge.rs#L1), [`core/dr-gpu/src/shaders/merge.wgsl:1`](../../core/dr-gpu/src/shaders/merge.wgsl#L1) | -| FR-MRG-2 | [`core/dr-gpu/src/adjust.rs:102`](../../core/dr-gpu/src/adjust.rs#L102), [`core/dr-gpu/src/adjust.rs:1580`](../../core/dr-gpu/src/adjust.rs#L1580), [`core/dr-gpu/src/adjust.rs:1711`](../../core/dr-gpu/src/adjust.rs#L1711), [`core/dr-gpu/src/adjust.rs:567`](../../core/dr-gpu/src/adjust.rs#L567), [`core/dr-pipeline/src/graph.rs:1014`](../../core/dr-pipeline/src/graph.rs#L1014), [`core/dr-pipeline/src/operation.rs:1163`](../../core/dr-pipeline/src/operation.rs#L1163), [`core/dr-pipeline/src/operation.rs:2547`](../../core/dr-pipeline/src/operation.rs#L2547), [`core/dr-pipeline/src/operation.rs:2587`](../../core/dr-pipeline/src/operation.rs#L2587), [`core/dr-pipeline/src/operation.rs:529`](../../core/dr-pipeline/src/operation.rs#L529), [`core/dr-pipeline/src/operation.rs:762`](../../core/dr-pipeline/src/operation.rs#L762), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1) | +| FR-MRG-2 | [`core/dr-gpu/src/adjust.rs:102`](../../core/dr-gpu/src/adjust.rs#L102), [`core/dr-gpu/src/adjust.rs:1580`](../../core/dr-gpu/src/adjust.rs#L1580), [`core/dr-gpu/src/adjust.rs:1711`](../../core/dr-gpu/src/adjust.rs#L1711), [`core/dr-gpu/src/adjust.rs:567`](../../core/dr-gpu/src/adjust.rs#L567), [`core/dr-pipeline/src/graph.rs:1033`](../../core/dr-pipeline/src/graph.rs#L1033), [`core/dr-pipeline/src/operation.rs:1163`](../../core/dr-pipeline/src/operation.rs#L1163), [`core/dr-pipeline/src/operation.rs:2547`](../../core/dr-pipeline/src/operation.rs#L2547), [`core/dr-pipeline/src/operation.rs:2587`](../../core/dr-pipeline/src/operation.rs#L2587), [`core/dr-pipeline/src/operation.rs:529`](../../core/dr-pipeline/src/operation.rs#L529), [`core/dr-pipeline/src/operation.rs:762`](../../core/dr-pipeline/src/operation.rs#L762), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1) | | FR-MRG-3 | [`core/dr-decode/examples/linear_dng.rs:1`](../../core/dr-decode/examples/linear_dng.rs#L1), [`core/dr-decode/src/lib.rs:129`](../../core/dr-decode/src/lib.rs#L129), [`core/dr-decode/src/lib.rs:136`](../../core/dr-decode/src/lib.rs#L136), [`core/dr-decode/src/lib.rs:625`](../../core/dr-decode/src/lib.rs#L625), [`core/dr-decode/src/profile.rs:397`](../../core/dr-decode/src/profile.rs#L397), [`core/dr-export/src/dng.rs:1`](../../core/dr-export/src/dng.rs#L1), [`core/dr-gpu/src/demosaic.rs:438`](../../core/dr-gpu/src/demosaic.rs#L438), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1) | | FR-MRG-4 | [`core/dr-export/src/inscribed.rs:1`](../../core/dr-export/src/inscribed.rs#L1), [`core/dr-pano/src/fill.rs:1`](../../core/dr-pano/src/fill.rs#L1), [`core/dr-pano/src/migan.rs:1`](../../core/dr-pano/src/migan.rs#L1), [`core/dr-pano/src/projection.rs:1`](../../core/dr-pano/src/projection.rs#L1), [`ui/dr-ui/src/library/paths.rs:379`](../../ui/dr-ui/src/library/paths.rs#L379), [`ui/dr-ui/src/library/paths.rs:383`](../../ui/dr-ui/src/library/paths.rs#L383), [`ui/dr-ui/src/merge.rs:174`](../../ui/dr-ui/src/merge.rs#L174), [`ui/dr-ui/src/merge_ui.rs:1`](../../ui/dr-ui/src/merge_ui.rs#L1), [`ui/dr-ui/ui/merge.slint:1`](../../ui/dr-ui/ui/merge.slint#L1), [`ui/dr-ui/ui/merge.slint:50`](../../ui/dr-ui/ui/merge.slint#L50) | | FR-MRG-5 | [`core/dr-pano/src/align.rs:1`](../../core/dr-pano/src/align.rs#L1), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1), [`ui/dr-ui/src/merge_ui.rs:1`](../../ui/dr-ui/src/merge_ui.rs#L1), [`ui/dr-ui/ui/merge.slint:1`](../../ui/dr-ui/ui/merge.slint#L1) | @@ -141,7 +141,7 @@ _None._ | FR-PLAT-AND-3 | [`core/dr-catalog/src/jobs.rs:1`](../../core/dr-catalog/src/jobs.rs#L1), [`core/dr-catalog/src/runner.rs:1`](../../core/dr-catalog/src/runner.rs#L1), [`core/dr-catalog/tests/every_queued_kind_has_a_consumer.rs:1`](../../core/dr-catalog/tests/every_queued_kind_has_a_consumer.rs#L1) | | FR-PLAT-AND-4 | [`core/dr-catalog/src/runner.rs:1`](../../core/dr-catalog/src/runner.rs#L1) | | FR-PLAT-AND-5 | [`apps/darkroom-android/src/lib.rs:166`](../../apps/darkroom-android/src/lib.rs#L166), [`core/dr-gpu/src/adjust.rs:1472`](../../core/dr-gpu/src/adjust.rs#L1472), [`core/dr-gpu/src/detail.rs:161`](../../core/dr-gpu/src/detail.rs#L161), [`core/dr-gpu/src/detail.rs:533`](../../core/dr-gpu/src/detail.rs#L533), [`core/dr-gpu/tests/detail_stage.rs:415`](../../core/dr-gpu/tests/detail_stage.rs#L415), [`ui/dr-ui/src/develop/render.rs:654`](../../ui/dr-ui/src/develop/render.rs#L654), [`ui/dr-ui/src/identity_ui.rs:125`](../../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:1309`](../../ui/dr-ui/src/lib.rs#L1309), [`ui/dr-ui/src/lib.rs:1745`](../../ui/dr-ui/src/lib.rs#L1745), [`ui/dr-ui/src/memory.rs:163`](../../ui/dr-ui/src/memory.rs#L163), [`ui/dr-ui/src/memory.rs:1`](../../ui/dr-ui/src/memory.rs#L1) | -| FR-PLAT-AND-6 | [`apps/darkroom-android/src/lib.rs:457`](../../apps/darkroom-android/src/lib.rs#L457) | +| FR-PLAT-AND-6 | [`apps/darkroom-android/src/lib.rs:472`](../../apps/darkroom-android/src/lib.rs#L472) | | FR-PLAT-LIN-1 | [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`platform/dr-plat/src/dirs.rs:1`](../../platform/dr-plat/src/dirs.rs#L1), [`platform/dr-plat/src/storage.rs:344`](../../platform/dr-plat/src/storage.rs#L344), [`ui/dr-ui/src/lib.rs:1486`](../../ui/dr-ui/src/lib.rs#L1486), [`ui/dr-ui/src/preset_store.rs:1`](../../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/settings_store.rs:1`](../../ui/dr-ui/src/settings_store.rs#L1) | | FR-PLAT-LIN-2 | [`platform/dr-plat/src/display.rs:1`](../../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/display/wayland.rs:1`](../../platform/dr-plat/src/display/wayland.rs#L1), [`platform/dr-plat/src/display/x11.rs:1`](../../platform/dr-plat/src/display/x11.rs#L1) | | FR-PLAT-WIN-1 | [`platform/dr-plat/src/dirs.rs:1`](../../platform/dr-plat/src/dirs.rs#L1) | diff --git a/models/LICENCE.md b/models/LICENCE.md index 2f376c1..bef223b 100644 --- a/models/LICENCE.md +++ b/models/LICENCE.md @@ -134,11 +134,16 @@ declined, and the InsightFace grant of D13). | File | Source | Trained on | Used by | |---|---|---|---| -| `denoise/mosaic-1408.onnx` | trained from scratch in the `darkroom-denoise` repository (2026-10-03, run `m2`, 60 000 steps) | 427 of the maintainer's own base-ISO Canon EOS 6D raws, with the 6D's measured noise added | the learned demosaic and denoise (FR-DEV-3g) | +| `denoise/mosaic-best-1408.onnx` | trained in the `darkroom-denoise` repository (2026-10-04, run `final`, 30 000 steps, from the experts of runs `m2` and `edges-100`) | 1,701 of the maintainer's own base-ISO raws and 6,000 synthetic scenes the repository draws itself, with the Canon EOS 6D's measured noise added | the learned demosaic and denoise, Best (FR-DEV-3g) | +| `denoise/mosaic-medium-1408.onnx` | distilled from `final` in the same repository (2026-10-04, run `student-m`, 20 000 steps, from `m2`) | the same | Medium | +| `denoise/mosaic-fast-1408.onnx` | distilled from `final` (2026-10-04, run `student-s`, 30 000 steps, from scratch) | the same | Fast | -A U-Net of plain 3×3 convolutions, ReLU, strided and transposed +U-Nets of plain 3×3 convolutions, ReLU, strided and transposed convolutions and additive skips — no third-party architecture code or -weights — at a fixed `1×1×1408×1408` for `mosaic` and `sigma`, exported by -`python -m denoise.export` in `darkroom-denoise`. Trained only on +weights — and, for Best, two of them blended per photosite by a small gate +network of the same parts. Each at a fixed `1×1×1408×1408` for `mosaic` +and `sigma`, exported by `python -m denoise.export` in `darkroom-denoise`; +the `.a16w16.onnx` siblings are the same networks quantised for the +Hexagon by `tools/quantise-models.sh`. Trained only on photographs the maintainer owns, so the weights carry no grant but the project's own: GPL-3.0-or-later, like the code (denoise.md §10). diff --git a/models/denoise/mosaic-1408.a16w16.onnx b/models/denoise/mosaic-1408.a16w16.onnx deleted file mode 100644 index a4241f5..0000000 --- a/models/denoise/mosaic-1408.a16w16.onnx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b4de28646546279e8c4e70fc3707d089aee846a504ba163e4bf2a33724d5db3 -size 6412449 diff --git a/models/denoise/mosaic-1408.onnx b/models/denoise/mosaic-1408.onnx deleted file mode 100644 index eb8a22a..0000000 --- a/models/denoise/mosaic-1408.onnx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:02c9b0efdc5fbbf69d947a8e345ef340f51c2d899c2d3d87f9c4efd3c2c77277 -size 12624295 diff --git a/models/denoise/mosaic-best-1408.a16w16.onnx b/models/denoise/mosaic-best-1408.a16w16.onnx new file mode 100644 index 0000000..100c407 --- /dev/null +++ b/models/denoise/mosaic-best-1408.a16w16.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7297ded63857a13490e522d4ea4eef50409a3e881a646795be89f78628319d22 +size 13136074 diff --git a/models/denoise/mosaic-best-1408.onnx b/models/denoise/mosaic-best-1408.onnx new file mode 100644 index 0000000..b8996bd --- /dev/null +++ b/models/denoise/mosaic-best-1408.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa7fc9666d08fa0232a9f1e9893eb1c1ab0b0cb0ffa57eb5d08c8e32eb6b8f06 +size 25767168 diff --git a/models/denoise/mosaic-fast-1408.a16w16.onnx b/models/denoise/mosaic-fast-1408.a16w16.onnx new file mode 100644 index 0000000..a8fc725 --- /dev/null +++ b/models/denoise/mosaic-fast-1408.a16w16.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44e06f2a74bb2ce176dbf6ac4035eaddab6c6b52cfe23e31f7061955de1bba82 +size 1930121 diff --git a/models/denoise/mosaic-fast-1408.onnx b/models/denoise/mosaic-fast-1408.onnx new file mode 100644 index 0000000..9114c2b --- /dev/null +++ b/models/denoise/mosaic-fast-1408.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8880b379b02fce9da9c554322bc90e5653e656f6cc7e19caa6d4d07e51d4bea0 +size 3721734 diff --git a/models/denoise/mosaic-medium-1408.a16w16.onnx b/models/denoise/mosaic-medium-1408.a16w16.onnx new file mode 100644 index 0000000..9407dfa --- /dev/null +++ b/models/denoise/mosaic-medium-1408.a16w16.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2bec3e762cd04f9c2f33fe06f6f39e6543b4121c642c869ce3216c93d675243f +size 6410772 diff --git a/models/denoise/mosaic-medium-1408.onnx b/models/denoise/mosaic-medium-1408.onnx new file mode 100644 index 0000000..0d189a7 --- /dev/null +++ b/models/denoise/mosaic-medium-1408.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e261f8fcac84854641532b9b70a6ed43b17b5ec2c96c3c6eea223d662dbd0974 +size 12623048 diff --git a/packaging/PKGBUILD b/packaging/PKGBUILD index 2aa57b6..be87c8b 100644 --- a/packaging/PKGBUILD +++ b/packaging/PKGBUILD @@ -124,12 +124,15 @@ package() { fi install -Dm644 "${_src}" "${pkgdir}/usr/share/darkroom/models/migan-512.onnx" - # The learned demosaic and denoise (the project's own weights, GPL — - # models/LICENCE.md). Same pointer check, same directory. - _src="models/denoise/mosaic-1408.onnx" - if [[ "$(stat -c%s "${_src}")" -lt 100000 ]]; then - echo "error: the denoise model is an LFS pointer — run: git lfs pull" >&2 - return 1 - fi - install -Dm644 "${_src}" "${pkgdir}/usr/share/darkroom/models/mosaic-1408.onnx" + # The learned demosaic and denoise, one network per method (the project's + # own weights, GPL — models/LICENCE.md). Same pointer check, same + # directory. + for _net in fast medium best; do + _src="models/denoise/mosaic-${_net}-1408.onnx" + if [[ "$(stat -c%s "${_src}")" -lt 100000 ]]; then + echo "error: the ${_net} denoise model is an LFS pointer — run: git lfs pull" >&2 + return 1 + fi + install -Dm644 "${_src}" "${pkgdir}/usr/share/darkroom/models/mosaic-${_net}-1408.onnx" + done } diff --git a/tools/quantise-models.py b/tools/quantise-models.py index 9ccd165..f33cf9a 100644 --- a/tools/quantise-models.py +++ b/tools/quantise-models.py @@ -41,7 +41,11 @@ TABLE = { "migan-512": dict(dir="inpaint", form="a16w16", feed="migan"), "xfeat-1024": dict(dir="keypoints", form="int8", feed="xfeat", rewrites=["unfold", "resize"]), "xfeat-768": dict(dir="keypoints", form="int8", feed="xfeat", rewrites=["unfold", "resize"]), - "mosaic-1408": dict(dir="denoise", form="a16w16", feed=None, rewrites=["bayer"]), + "mosaic-fast-1408": dict(dir="denoise", form="a16w16", feed=None, rewrites=["bayer"]), + "mosaic-medium-1408": dict(dir="denoise", form="a16w16", feed=None, rewrites=["bayer"]), + # Exported with its packs as SpaceToDepth already; the rewrite finds + # nothing to do. + "mosaic-best-1408": dict(dir="denoise", form="a16w16", feed=None, rewrites=["bayer"]), } diff --git a/tools/quantise-models.sh b/tools/quantise-models.sh index 48abe22..f5e2c68 100755 --- a/tools/quantise-models.sh +++ b/tools/quantise-models.sh @@ -2,7 +2,7 @@ # Produce the Hexagon's form of each model (docs/dev/inference.md §1.5, §5). # # ./tools/quantise-models.sh PHOTO_DIR [MODEL ...] -# ./tools/quantise-models.sh --ranges RANGES.json mosaic-1408 +# ./tools/quantise-models.sh --ranges RANGES.json mosaic-medium-1408 # # Writes `.
.onnx` beside each canonical file under models/: a QDQ # graph from QNN's own quantisation config, per-channel weights, in the form diff --git a/ui/dr-ui/src/develop/denoise.rs b/ui/dr-ui/src/develop/denoise.rs index e66f7d3..51b7583 100644 --- a/ui/dr-ui/src/develop/denoise.rs +++ b/ui/dr-ui/src/develop/denoise.rs @@ -18,6 +18,7 @@ use std::sync::Arc; use dr_decode::RawImage; use dr_gpu::{DemosaicedImage, GrainBlend}; +use dr_pipeline::learned_denoise::Method; use super::session::DevelopSession; @@ -41,9 +42,12 @@ pub(crate) struct DenoiseState { failed: Option, /// Where the noise figures came from, for the panel. source: Option, - /// The result's key in the on-disk cache: the file's bytes and the model - /// (`denoise_cache::key`). `None` where there is no model to key on. - cache_key: Option, + /// The file's bytes, hashed for the on-disk cache, which keys each + /// network's result on them and the model (`denoise_cache::FileHash`). + file_hash: Option, + /// The method the result, the job and the failure above are for. A + /// different one asked for discards them. + method: Option, } struct Job { @@ -93,10 +97,10 @@ impl DevelopSession { self.denoise.profile = dr_decode::noise_profile(bytes); self.denoise.iso = meta.iso; // TRACES: FR-DEV-3g - // The bytes are only here now, so the cache key is made now: a - // reopened or exported photograph finds its result on disk. - self.denoise.cache_key = crate::library::denoise_model() - .map(|model| super::denoise_cache::key(bytes, &model)); + // The bytes are only here now, so they are hashed now: a + // reopened or exported photograph finds its result on disk, + // under whichever method it asks for. + self.denoise.file_hash = Some(super::denoise_cache::FileHash::of(bytes)); } } @@ -105,6 +109,7 @@ impl DevelopSession { /// Cheap when nothing changed; the develop view calls it after every /// change to the edit, whatever made it — a slider, undo, a version. pub fn reconcile_denoise(&mut self) { + self.forget_other_method(); let wanted = self.graph.denoise_applied() && self.denoise.mosaic.is_some(); if !wanted { if let Some(job) = self.denoise.job.take() { @@ -120,21 +125,11 @@ impl DevelopSession { { return; } - let Some(model) = crate::library::denoise_model() else { - self.denoise.failed = Some("the denoise model is not installed".into()); + let Some(work) = self.work(Arc::new(AtomicBool::new(false))) else { return; }; + let cancel = work.cancel.clone(); let (tx, rx) = mpsc::channel(); - let cancel = Arc::new(AtomicBool::new(false)); - let work = Work { - ctx: self.ctx.clone(), - raw: self.denoise.mosaic.clone().expect("checked above"), - profile: self.denoise.profile.clone(), - iso: self.denoise.iso, - model, - cancel: cancel.clone(), - cache_key: self.denoise.cache_key.clone(), - }; crate::executors::spawn(crate::executors::Executor::Decode, "denoise", move || { let result = work.run(&mut |done, total| { let _ = tx.send(Msg::Progress(done, total)); @@ -144,6 +139,51 @@ impl DevelopSession { self.denoise.job = Some(Job { rx, cancel }); } + /// Drop what was computed, or is being computed, for a network the edit + /// no longer asks for — a choice in the panel, an undo, a version. + /// Each network's result stays in the on-disk cache, so going back to + /// one is a read, not a run. The classical demosaic asks for no network + /// and drops nothing: the result is kept for the way back. + fn forget_other_method(&mut self) { + let asked = self.graph.denoise_method(); + if !asked.learned() || self.denoise.method == Some(asked) { + return; + } + if self.denoise.method.is_none() { + // The first network asked for: nothing computed is another's. + self.denoise.method = Some(asked); + return; + } + if let Some(job) = self.denoise.job.take() { + job.cancel.store(true, Ordering::Relaxed); + } + self.denoise.result = None; + self.denoise.blended = None; + self.denoise.failed = None; + self.denoise.source = None; + self.denoise.method = Some(asked); + } + + /// The job for the method the edit asks for, or `None` — with the reason + /// kept as the failure — where its network is not installed. + fn work(&mut self, cancel: Arc) -> Option { + let raw = self.denoise.mosaic.clone()?; + let Some((model, net)) = crate::library::denoise_model(self.graph.denoise_method()) else { + self.denoise.failed = Some("the denoise model is not installed".into()); + return None; + }; + Some(Work { + ctx: self.ctx.clone(), + raw, + profile: self.denoise.profile.clone(), + iso: self.denoise.iso, + cache_key: self.denoise.file_hash.as_ref().map(|h| h.key(&model)), + model, + halo: net.halo, + cancel, + }) + } + /// Collect what the job sent since the last poll. pub fn poll_denoise(&mut self) -> DenoiseStatus { let Some(job) = &self.denoise.job else { @@ -182,9 +222,10 @@ impl DevelopSession { if !self.graph.denoise_applied() || self.denoise.result.is_some() { return Ok(()); } - let Some(raw) = self.denoise.mosaic.clone() else { + self.forget_other_method(); + if self.denoise.mosaic.is_none() { return Ok(()); - }; + } // Already under way: wait for it rather than start again. if let Some(job) = self.denoise.job.take() { for msg in job.rx.iter() { @@ -193,15 +234,8 @@ impl DevelopSession { } } } - let model = crate::library::denoise_model().ok_or("the denoise model is not installed")?; - let work = Work { - ctx: self.ctx.clone(), - raw, - profile: self.denoise.profile.clone(), - iso: self.denoise.iso, - model, - cancel: Arc::new(AtomicBool::new(false)), - cache_key: self.denoise.cache_key.clone(), + let Some(work) = self.work(Arc::new(AtomicBool::new(false))) else { + return Err(self.denoise.failed.clone().unwrap_or_default()); }; let finished = work.run(&mut |_, _| {})?; self.land(finished) @@ -282,6 +316,8 @@ struct Work { profile: Option>, iso: Option, model: std::path::PathBuf, + /// The context `model` needs past a tile's kept centre. + halo: usize, cancel: Arc, cache_key: Option, } @@ -315,8 +351,8 @@ impl Work { .map_err(|e| e.to_string())?; let noise = dr_denoise::noise::for_frame_with(&raw, self.profile.as_deref(), self.iso) .ok_or("this photograph gives no way to measure its noise")?; - let mut net = - dr_denoise::onnx::OnnxNet::from_path(&self.model).map_err(|e| e.to_string())?; + let mut net = dr_denoise::onnx::OnnxNet::from_path(&self.model, self.halo) + .map_err(|e| e.to_string())?; let rung = net .rung() .map(|r| r.label().to_string()) @@ -426,12 +462,18 @@ mod tests { // On by default, at full strength: the network's result as it is. assert!(same(&s.developed_source(), &result)); - // Off: the classical demosaic, result or no result. - s.graph - .set_param(learned_denoise::ID, learned_denoise::APPLY, 0.0); + // Bilinear: the classical demosaic, result or no result. + s.graph.set_param( + learned_denoise::ID, + learned_denoise::METHOD, + Method::Bilinear.index(), + ); assert!(same(&s.developed_source(), &classical)); - s.graph - .set_param(learned_denoise::ID, learned_denoise::APPLY, 1.0); + s.graph.set_param( + learned_denoise::ID, + learned_denoise::METHOD, + Method::DEFAULT.index(), + ); // Less strength: a blend, made once per value and reused until it // moves. s.graph @@ -455,19 +497,41 @@ mod tests { let mut s = DevelopSession::open_owned(&ctx, bayer(64, 64), dr_types::Orientation::NORMAL).unwrap(); s.denoise.failed = Some("no model".into()); - s.graph - .set_param(learned_denoise::ID, learned_denoise::APPLY, 1.0); s.reconcile_denoise(); assert!( s.denoise.job.is_none(), - "a failure is not retried while the switch stays on" + "a failure is not retried while the method stays" + ); + s.graph.set_param( + learned_denoise::ID, + learned_denoise::METHOD, + Method::Bilinear.index(), ); - s.graph - .set_param(learned_denoise::ID, learned_denoise::APPLY, 0.0); s.reconcile_denoise(); assert!( s.denoise.failed.is_none(), - "toggling off is how a failure is retried" + "choosing bilinear is how a failure is retried" ); } + + #[test] + fn another_network_discards_the_result_and_bilinear_keeps_it() { + let Some(ctx) = headless() else { return }; + let mut s = + DevelopSession::open_owned(&ctx, bayer(64, 64), dr_types::Orientation::NORMAL).unwrap(); + s.denoise.method = Some(Method::DEFAULT); + landed(&mut s); + let to = |s: &mut DevelopSession, m: Method| { + s.graph + .set_param(learned_denoise::ID, learned_denoise::METHOD, m.index()); + s.forget_other_method(); + }; + to(&mut s, Method::Bilinear); + assert!(s.denoise.result.is_some(), "kept for the way back"); + to(&mut s, Method::DEFAULT); + assert!(s.denoise.result.is_some()); + to(&mut s, Method::Fast); + assert!(s.denoise.result.is_none(), "another network's picture"); + assert_eq!(s.denoise.method, Some(Method::Fast)); + } } diff --git a/ui/dr-ui/src/develop/denoise_cache.rs b/ui/dr-ui/src/develop/denoise_cache.rs index 0aad99b..5ec8526 100644 --- a/ui/dr-ui/src/develop/denoise_cache.rs +++ b/ui/dr-ui/src/develop/denoise_cache.rs @@ -47,17 +47,29 @@ pub fn dir() -> PathBuf { .unwrap_or_else(|| PathBuf::from("denoise-cache")) } -/// The key for a file's bytes under a model. -pub fn key(bytes: &[u8], model: &Path) -> String { - let mut h = Sha256::new(); - h.update(bytes); - if let Some(name) = model.file_name() { - h.update(name.to_string_lossy().as_bytes()); +/// A file's bytes, hashed once at open: each method's network keys its +/// result from this, so changing the method does not read the file again. +#[derive(Clone)] +pub struct FileHash(Sha256); + +impl FileHash { + pub fn of(bytes: &[u8]) -> Self { + let mut h = Sha256::new(); + h.update(bytes); + FileHash(h) + } + + /// The key for these bytes under a model. + pub fn key(&self, model: &Path) -> String { + let mut h = self.0.clone(); + if let Some(name) = model.file_name() { + h.update(name.to_string_lossy().as_bytes()); + } + let size = std::fs::metadata(model).map(|m| m.len()).unwrap_or(0); + h.update(size.to_le_bytes()); + let digest = h.finalize(); + digest.iter().map(|b| format!("{b:02x}")).collect() } - let size = std::fs::metadata(model).map(|m| m.len()).unwrap_or(0); - h.update(size.to_le_bytes()); - let digest = h.finalize(); - digest.iter().map(|b| format!("{b:02x}")).collect() } fn path_in(dir: &Path, key: &str) -> PathBuf { @@ -204,11 +216,11 @@ mod tests { std::fs::create_dir_all(&dir).unwrap(); let model = dir.join("m.onnx"); std::fs::write(&model, b"weights").unwrap(); - let a = key(b"photo", &model); - assert_eq!(a, key(b"photo", &model)); - assert_ne!(a, key(b"photo2", &model)); + let a = FileHash::of(b"photo").key(&model); + assert_eq!(a, FileHash::of(b"photo").key(&model)); + assert_ne!(a, FileHash::of(b"photo2").key(&model)); std::fs::write(&model, b"other weights").unwrap(); - assert_ne!(a, key(b"photo", &model)); + assert_ne!(a, FileHash::of(b"photo").key(&model)); let _ = std::fs::remove_dir_all(&dir); } diff --git a/ui/dr-ui/src/inference.rs b/ui/dr-ui/src/inference.rs index 3a99725..88f253a 100644 --- a/ui/dr-ui/src/inference.rs +++ b/ui/dr-ui/src/inference.rs @@ -34,8 +34,10 @@ pub fn init(runtime_dirs: Vec) { (Role::EyeClassifier, crate::library::EYE_MODEL), (Role::EyeClassifier, crate::library::SUNGLASSES_MODEL), (Role::Inpainter, crate::library::INPAINT_MODEL), - (Role::Denoiser, crate::library::DENOISE_MODEL), ]); + wanted.extend( + [dr_denoise::FAST, dr_denoise::MEDIUM, dr_denoise::BEST].map(|n| (Role::Denoiser, n.file)), + ); let models: Vec<(Role, PathBuf)> = wanted .into_iter() .filter_map(|(role, name)| Some((role, crate::library::shared_model(name)?))) diff --git a/ui/dr-ui/src/labels.rs b/ui/dr-ui/src/labels.rs index b658a16..174c186 100644 --- a/ui/dr-ui/src/labels.rs +++ b/ui/dr-ui/src/labels.rs @@ -223,6 +223,12 @@ fn catalogued(key: &str) -> Option<&'static str> { // panel under its own name — see `rows_filtered`. "param.lens_profile.apply" => "Apply", "param.learned_denoise.apply" => "Apply", + // Which demosaic: the classical one, or a network by how long it takes. + "param.learned_denoise.method" => "Method", + "param.learned_denoise.method.bilinear" => "Bilinear", + "param.learned_denoise.method.fast" => "Fast", + "param.learned_denoise.method.medium" => "Medium", + "param.learned_denoise.method.best" => "Best", // How strongly: 100 % is the network's result, and less puts the // removed noise's brightness back as grain. "param.learned_denoise.strength" => "Strength", diff --git a/ui/dr-ui/src/library/paths.rs b/ui/dr-ui/src/library/paths.rs index eac4f53..ba1ddc3 100644 --- a/ui/dr-ui/src/library/paths.rs +++ b/ui/dr-ui/src/library/paths.rs @@ -390,13 +390,28 @@ pub fn inpaint_model() -> Option { } /// TRACES: FR-DEV-3g -/// The learned demosaic and denoise, as shipped in `models/denoise/`. -pub const DENOISE_MODEL: &str = "mosaic-1408.onnx"; +/// The network a denoise method runs, as shipped in `models/denoise/`; +/// `None` for the classical demosaic, which runs none. +pub fn denoise_network( + method: dr_pipeline::learned_denoise::Method, +) -> Option { + use dr_pipeline::learned_denoise::Method; + match method { + Method::Bilinear => None, + Method::Fast => Some(dr_denoise::FAST), + Method::Medium => Some(dr_denoise::MEDIUM), + Method::Best => Some(dr_denoise::BEST), + } +} /// TRACES: FR-DEV-3g -/// Where the denoise model is, by the border filler's search. -pub fn denoise_model() -> Option { - shared_model(DENOISE_MODEL) +/// Where a method's network is, by the border filler's search, and the +/// context it needs. +pub fn denoise_model( + method: dr_pipeline::learned_denoise::Method, +) -> Option<(PathBuf, dr_denoise::Shipped)> { + let net = denoise_network(method)?; + Some((shared_model(net.file)?, net)) } #[cfg(test)]