Files
DarkRoom/core/dr-pipeline/src/learned_denoise.rs
T
dtourolle 2e7f14dafe Develop every raw through the AI denoise by default, with a strength, cached
The learned demosaic was an option under Detail, off by default. It is
now how a Bayer raw is developed: on by default at full strength on
every device — which hardware runs it is the inference engine's choice
— and first in the Adjust panel, since it decides what every control
below is applied to.

Strength (0-100, default 100) replaces Keep grain: grain = 100 -
strength, the same luminance-only blend, so moving it is one GPU pass
and never a re-run. 0.21.0's sidecars stored grain; it is still read,
as the inverse, and never written.

With it on for every photograph, the result is now kept on disk
(denoise.md §7.1, §12): the network's output as half floats, keyed on
a SHA-256 of the file's bytes and the model, oldest first past a 5 GB
budget, beside the inference engine's cache. A reopened photograph and
an export of one already developed read it back instead of running the
network again; a damaged entry is a miss.
2026-10-03 22:16:36 -04:00

61 lines
2.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! TRACES: FR-DEV-3g
//! The learned denoise's settings: whether to use it, 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
//! (docs/dev/denoise.md §2, §7), and the grain is a blend of its result with
//! the classical one, done where the source is chosen. But what a
//! photographer sets travels the one road every setting travels — the
//! capability list feeds the panel, [`crate::Preset`] captures it, the
//! sidecar stores it, the undo stack replays it (FR-DEV-3c) — so it is
//! published as a capability, like the lens profile switch.
use std::sync::{Arc, LazyLock};
use crate::descriptor::{Attribute, LocalizedKey, OpDescriptor, ParamDescriptor, Scale, Unit};
use crate::{OpId, ParamId};
pub const ID: OpId = OpId("learned_denoise");
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
/// lower puts the removed noise's brightness back as grain.
pub const STRENGTH: ParamId = ParamId("strength");
/// What 0.21.0 stored instead of [`STRENGTH`]: the grain kept, its inverse.
/// Still read, so an edit saved by that release keeps its look; never
/// 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
/// 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<Arc<OpDescriptor>> = LazyLock::new(|| {
Arc::new(OpDescriptor {
id: ID,
label: LocalizedKey("op.learned_denoise"),
params: vec![
ParamDescriptor::switch_on("apply", "param.learned_denoise.apply"),
ParamDescriptor::scalar(
"strength",
"param.learned_denoise.strength",
0.0,
100.0,
100.0,
Unit::Percent,
Scale::Linear,
0,
),
],
// With the classical noise reduction, which is what a photographer
// looks for it beside.
attributes: vec![Attribute::Detail],
})
});
pub fn descriptor() -> Arc<OpDescriptor> {
DESCRIPTOR.clone()
}