Keep the sigmoid as the default curve; Camera Raw's tone is a choice
The Camera Raw default rested on comparing against Lightroom previews of photographs that carry the user's Lightroom edits — HSL saturation Blue +58, Aqua +50 and more, Highlights -40, Blacks -20, in every DNG's XMP — so it measured the house look, not Camera Raw's base rendering. Under the ACR3 curve _MG_9080 renders brighter than its Lightroom preview (mean 0.39 against 0.31). So the curve choice's first variant, the default, is the sigmoid again and every raw renders as in 0.20.0 apart from baseline exposure. D21 and camera-profiles.md §12 now say the default is open, to be decided by measuring against Lightroom exports of unedited photographs. Tests that are about Camera Raw's tone choose it explicitly.
This commit is contained in:
@@ -3420,10 +3420,8 @@ mod tests {
|
||||
read_centre(&ctx, t)
|
||||
};
|
||||
|
||||
// The default rendering of a raw is Camera Raw's tone (D21): a grey
|
||||
// goes through the ACR3 curve unchanged in hue.
|
||||
let scene = 3537.0 / 16383.0;
|
||||
let viewed = dr_types::tone::evaluate(&dr_types::tone::ACR3_DEFAULT, scene);
|
||||
let viewed = dr_pipeline::view::Sigmoid::default_curve().channel(scene);
|
||||
let expected = (dr_types::Transfer::Srgb.encode(viewed) * 255.0).round() as i32;
|
||||
let delta = (i32::from(from_sensor[0]) - expected).abs();
|
||||
assert!(
|
||||
|
||||
@@ -206,7 +206,12 @@ fn camera_raw_tone_agrees_with_its_cpu_reference() {
|
||||
.expect("demosaicer")
|
||||
.run(&frame(None))
|
||||
.expect("upload");
|
||||
let ops: Vec<Box<dyn Operation>> = vec![Box::new(dr_pipeline::ops::ViewTransform::new())];
|
||||
let mut view = dr_pipeline::ops::ViewTransform::new();
|
||||
view.set_param(
|
||||
dr_pipeline::ops::view_transform::CURVE,
|
||||
dr_pipeline::ops::view_transform::CAMERA_RAW,
|
||||
);
|
||||
let ops: Vec<Box<dyn Operation>> = vec![Box::new(view)];
|
||||
let shader = dr_pipeline::compose(&ops);
|
||||
let mut adjust = AdjustPass::new(&ctx);
|
||||
adjust.render(&source, &shader, SIZE, SIZE).expect("render");
|
||||
|
||||
@@ -46,8 +46,8 @@ fn flat_raw(level: u16) -> RawImage {
|
||||
}
|
||||
}
|
||||
|
||||
/// The default chain with D19's sigmoid chosen: Camera Raw's tone is the
|
||||
/// default since D21, and these tests are about the sigmoid.
|
||||
/// The default chain with D19's sigmoid chosen explicitly, so these tests
|
||||
/// stay about the sigmoid whichever curve is the default (D21).
|
||||
fn sigmoid_chain() -> EditGraph {
|
||||
let mut g = EditGraph::default_chain();
|
||||
g.set_param(
|
||||
@@ -59,15 +59,21 @@ fn sigmoid_chain() -> EditGraph {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn camera_raw_tone_is_the_default_and_agrees_with_the_acr3_curve() {
|
||||
fn camera_raw_tone_agrees_with_the_acr3_curve() {
|
||||
// TRACES: FR-DEV-3j
|
||||
// D21: a raw with no profile renders a grey through Camera Raw's default
|
||||
// curve, which the profile buffer's placeholder carries.
|
||||
// D21: a raw with no profile, Camera Raw's curve chosen, renders a grey
|
||||
// through the ACR3 default curve, which the profile buffer's placeholder
|
||||
// carries.
|
||||
let Some(ctx) = ctx() else {
|
||||
eprintln!("skipping: no GPU adapter");
|
||||
return;
|
||||
};
|
||||
let graph = EditGraph::default_chain();
|
||||
let mut graph = EditGraph::default_chain();
|
||||
graph.set_param(
|
||||
dr_pipeline::ops::view_transform::ID,
|
||||
dr_pipeline::ops::view_transform::CURVE,
|
||||
dr_pipeline::ops::view_transform::CAMERA_RAW,
|
||||
);
|
||||
for level in [500u16, 4_000, 8_520, 20_000, 40_000] {
|
||||
let scene = f32::from(level) / f32::from(u16::MAX);
|
||||
let display = dr_types::tone::evaluate(&dr_types::tone::ACR3_DEFAULT, scene);
|
||||
|
||||
@@ -34,13 +34,15 @@ pub const ID: OpId = OpId("view_transform");
|
||||
pub const CONTRAST: ParamId = ParamId("contrast");
|
||||
pub const WHITE: ParamId = ParamId("white");
|
||||
/// TRACES: FR-DEV-3j
|
||||
/// Which curve renders: Camera Raw's (index 0, the default — D21) or D19's
|
||||
/// sigmoid.
|
||||
/// Which curve renders: D19's sigmoid (index 0, the default) or Camera
|
||||
/// Raw's (D21). Which of the two should be the default is open — the
|
||||
/// Lightroom-matching work decides it — so the default is what 0.20.0
|
||||
/// rendered.
|
||||
pub const CURVE: ParamId = ParamId("curve");
|
||||
|
||||
/// [`CURVE`]'s values, in the order of its variants.
|
||||
pub const CAMERA_RAW: f32 = 0.0;
|
||||
pub const SIGMOID: f32 = 1.0;
|
||||
pub const SIGMOID: f32 = 0.0;
|
||||
pub const CAMERA_RAW: f32 = 1.0;
|
||||
|
||||
static HELPERS: LazyLock<[Helper; 3]> = LazyLock::new(|| {
|
||||
[
|
||||
@@ -88,8 +90,8 @@ static DESCRIPTOR: LazyLock<Arc<OpDescriptor>> = LazyLock::new(|| {
|
||||
"curve",
|
||||
"param.view_transform.curve",
|
||||
vec![
|
||||
LocalizedKey("param.view_transform.curve.camera_raw"),
|
||||
LocalizedKey("param.view_transform.curve.sigmoid"),
|
||||
LocalizedKey("param.view_transform.curve.camera_raw"),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -108,7 +110,7 @@ impl Default for ViewTransform {
|
||||
Self {
|
||||
contrast: DEFAULT_CONTRAST,
|
||||
white: DEFAULT_WHITE,
|
||||
curve: CAMERA_RAW,
|
||||
curve: SIGMOID,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,7 +150,7 @@ impl Operation for ViewTransform {
|
||||
}
|
||||
|
||||
fn is_active(&self) -> bool {
|
||||
self.contrast != DEFAULT_CONTRAST || self.white != DEFAULT_WHITE || self.curve != CAMERA_RAW
|
||||
self.contrast != DEFAULT_CONTRAST || self.white != DEFAULT_WHITE || self.curve != SIGMOID
|
||||
}
|
||||
|
||||
fn stage(&self) -> Stage {
|
||||
@@ -159,9 +161,9 @@ impl Operation for ViewTransform {
|
||||
"\
|
||||
// Skipped for an already-rendered source: a JPEG is a display rendering
|
||||
// already, and rendering it again would compress it twice.
|
||||
// Camera Raw's tone by default (D21), D19's sigmoid by choice.
|
||||
// D19's sigmoid by default, Camera Raw's tone by choice (D21).
|
||||
if (!non_linear) {
|
||||
if (mode < 0.5) {
|
||||
if (mode > 0.5) {
|
||||
c = camera_raw_tone(c, cr_scale, cr_power, cr_grey);
|
||||
} else {
|
||||
c = view_sigmoid(c, slope, inv_k, peak);
|
||||
|
||||
@@ -295,8 +295,12 @@ that rendering, chosen by a new parameter on `view_transform`:
|
||||
|
||||
| `curve` | What it is | Default for |
|
||||
|---|---|---|
|
||||
| Camera Raw | the profile's curve, else ACR3, via RGBTone in ProPhoto | every raw (D21) |
|
||||
| Sigmoid | D19's log-logistic curve | — |
|
||||
| Sigmoid | D19's log-logistic curve | every raw, for now |
|
||||
| Camera Raw | the profile's curve, else ACR3, via RGBTone in ProPhoto | — (D21: the default is open) |
|
||||
|
||||
*Amended 2026-10-03:* Camera Raw was the default in the first draft. The measurement it rested on
|
||||
compared against Lightroom renders of *edited* photographs; see D21. The default is decided by
|
||||
measuring against Lightroom exports of unedited ones.
|
||||
|
||||
A JPEG is still not rendered again (FR-DEV-3j). Film simulation still replaces the view transform
|
||||
when a stock is chosen.
|
||||
|
||||
@@ -2437,7 +2437,7 @@ Rationale, evidence, and the eliminated alternatives are recorded in
|
||||
| D12 | Scope versus pace | **DECIDED 2026-09-19** — settled by events; full scope stands, no v1 date |
|
||||
| D18 | Derived images | **DECIDED 2026-09-19** — a merge writes a new source file; no multi-source Version |
|
||||
| D19 | Scene-referred pipeline | **DECIDED 2026-09-27** — edits on unbounded scene-linear colour; one view transform, last; per-body base curves retired |
|
||||
| D21 | Camera Raw tone for raws | **DECIDED 2026-10-03** — the view transform gains a Camera Raw curve (profile's, else ACR3 default, via RGBTone in ProPhoto), the default for every raw; Sigmoid stays a choice |
|
||||
| D21 | Camera Raw tone for raws | **PARTLY DECIDED 2026-10-03** — the view transform gains a Camera Raw curve (profile's, else ACR3 default, via RGBTone in ProPhoto) as a choice; which curve is the default is open, pending measurement against Lightroom exports |
|
||||
| D20 | DCP camera profiles | **DECIDED 2026-10-02** — HueSatMap and LookTable as a scene operation after exposure; embedded profile first, then a matched `.dcp`; tone curve not applied; none shipped |
|
||||
|
||||
### D11 — product positioning
|
||||
@@ -2773,7 +2773,15 @@ matrix does.
|
||||
*What it costs.* Every DNG with an embedded profile renders differently; previews refresh only when
|
||||
rendered again; tablet and desktop release together. The profiles directory does not sync yet.
|
||||
|
||||
### D21 — Camera Raw tone for raws · **DECIDED 2026-10-03**
|
||||
### D21 — Camera Raw tone for raws · **PARTLY DECIDED 2026-10-03**
|
||||
|
||||
*Amended the same day:* the default is **not** decided. The measurement below was against
|
||||
Lightroom previews of photographs carrying the user's Lightroom edits — a house look of HSL
|
||||
saturation (Blue +58, Aqua +50, …), Highlights −40 and Blacks −20 in every DNG's XMP — so it said
|
||||
nothing about Camera Raw's base rendering. Under Camera Raw's curve `_MG_9080` renders brighter
|
||||
than its Lightroom preview (mean 0.39 against 0.31). The sigmoid stays the default; the curve
|
||||
below is a choice; the default is decided by measurement against Lightroom exports of unedited
|
||||
photographs (the `lr-fit` work). What follows is the original text.
|
||||
|
||||
**The view transform has two curves, and Camera Raw's is the default for every raw.** It is the
|
||||
profile's `ProfileToneCurve`, or the ACR3 default curve where the profile has none or there is no
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user