mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-24 10:09:01 -06:00
LR-IMP-FORMATS: decode Canon EOS R5 Mark II C-RAW (CRX QP-map first literal and escape)
The CRX 0x200 QP map opens with its first symbol as a 32-bit literal; every
later symbol is Rice coded with a limited-length escape: 23 zeros, the
terminating 1 and the symbol in 8 bits (the ITU-T T.87 layout for a 32-bit
limit and 8-bit symbols, without its minus-one offset). The old rule (an
escape after 16 zeros with a 16-bit literal) matched only the first symbol,
which is all the R8 and R7 maps need. R5 Mark II maps (QP 150-162) jump by up
to 12 where the Rice parameter is 0, giving 18- to 22-zero prefixes that
misparsed ("Canon CRX adaptive QP value -21087"): 174 of 306 sampled files
from a private R5 Mark II library opened as previews. Every QP map of its
33,665 C-RAW files now decodes to the exact end of its entropy stream; the six
oracle fixtures are unchanged. Established by black-box analysis of the
bitstream; no third-party decoder source consulted.
Adds the four CC0 R5 Mark II samples (raw.pixls.us 7881-7884) to the corpus
with pinned sensor hashes (the crop-mode framing is left to #754), bumps
RENDER_CACHE_VERSION to 43, and updates cr3.md, raw-parity (235 verified
models), coverage, gaps, the checklist rows, ROADMAP, target-app-parity and
What's New.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0ba118de92
commit
4700c8a74e
+9
-4
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
**Stage: alpha** · next: beta, ~14 points and ~340–600 h away
|
**Stage: alpha** · next: beta, ~14 points and ~340–600 h away
|
||||||
|
|
||||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (full re-measure against Lightroom Classic 15.5 and the installed Lightroom 9.6; restructured to the progress-docs standard) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (EOS R5 Mark II CR3 verified; RAW decoding 77%) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||||
|
|
||||||
One-page summary of how close LightCraft is to Adobe Lightroom. Agents: read this, then pick work
|
One-page summary of how close LightCraft is to Adobe Lightroom. Agents: read this, then pick work
|
||||||
from [docs/gaps.md](docs/gaps.md). The full assessment, method and evidence are in
|
from [docs/gaps.md](docs/gaps.md). The full assessment, method and evidence are in
|
||||||
@@ -29,11 +29,11 @@ Each audience with its own hours (Opus 5.5 agent wall-clock hours to ~95%):
|
|||||||
| Essentials user | **~64%** | **160–300 h** (~50% parallelizes) | default raw look for popular cameras; launch stability; basic-slider feel; opening CR3 / HEIC files people send |
|
| Essentials user | **~64%** | **160–300 h** (~50% parallelizes) | default raw look for popular cameras; launch stability; basic-slider feel; opening CR3 / HEIC files people send |
|
||||||
|
|
||||||
The gap between breadth and readiness is quality and coverage, not missing buttons: camera colour is
|
The gap between breadth and readiness is quality and coverage, not missing buttons: camera colour is
|
||||||
estimated rather than measured, CR3 decodes on three verified Canon bodies, compressed ORF and HE NEF
|
estimated rather than measured, CR3 decodes on four verified Canon bodies, compressed ORF and HE NEF
|
||||||
open as previews, rendering is tuned by eye, AI masks are heuristics, there is no lens database, and
|
open as previews, rendering is tuned by eye, AI masks are heuristics, there is no lens database, and
|
||||||
tests run in CI on FreeBSD only. **Why alpha:** core workflows run end to end, but readiness is below
|
tests run in CI on FreeBSD only. **Why alpha:** core workflows run end to end, but readiness is below
|
||||||
the ~75% beta bar (it is above the ~40% alpha bar) and Lightroom's main inputs, raw files, still have blocking gaps (Canon, ~30% of
|
the ~75% beta bar (it is above the ~40% alpha bar) and Lightroom's main inputs, raw files, still have blocking gaps (Canon, ~30% of
|
||||||
raw users, decodes CR3 on three verified bodies). It passes the alpha gate: all six core workflows
|
raw users, decodes CR3 on four verified bodies). It passes the alpha gate: all six core workflows
|
||||||
(import, cull, develop, save and reopen, batch looks, export) work end to end on macOS
|
(import, cull, develop, save and reopen, batch looks, export) work end to end on macOS
|
||||||
([docs/roadmap.md](docs/roadmap.md#alpha-gate)). The three readiness numbers and their weights and discounts are in
|
([docs/roadmap.md](docs/roadmap.md#alpha-gate)). The three readiness numbers and their weights and discounts are in
|
||||||
[target-app-parity.md](docs/target-app-parity.md#ready-for-real-work-mainstream-practitioner-and-essentials-user).
|
[target-app-parity.md](docs/target-app-parity.md#ready-for-real-work-mainstream-practitioner-and-essentials-user).
|
||||||
@@ -61,7 +61,7 @@ Hours are calibrated on this repo's PR history; see
|
|||||||
| Area | Ready | Breadth | Remaining |
|
| Area | Ready | Breadth | Remaining |
|
||||||
|---|---:|---:|---:|
|
|---|---:|---:|---:|
|
||||||
| Import and library | 80% | 90% | 25–45 h |
|
| Import and library | 80% | 90% | 25–45 h |
|
||||||
| RAW decoding and camera coverage | 76% | 81% | 120–220 h |
|
| RAW decoding and camera coverage | 77% | 81% | 120–220 h |
|
||||||
| Colour, camera profiles, render fidelity | 35% | 65% | 80–150 h |
|
| Colour, camera profiles, render fidelity | 35% | 65% | 80–150 h |
|
||||||
| Global develop adjustments | 70% | 93% | 30–60 h |
|
| Global develop adjustments | 70% | 93% | 30–60 h |
|
||||||
| Optics, lens profiles, crop and geometry | 50% | 80% | 40–80 h |
|
| Optics, lens profiles, crop and geometry | 50% | 80% | 40–80 h |
|
||||||
@@ -114,6 +114,10 @@ Ranked toward beta; detail in [docs/roadmap.md](docs/roadmap.md), gaps in [docs/
|
|||||||
|
|
||||||
## Progress log
|
## Progress log
|
||||||
|
|
||||||
|
- 2026-10-11: Canon EOS R5 Mark II C-RAW decodes from sensor data (57% of its files opened as a
|
||||||
|
preview): the CRX QP map's first-symbol literal and limited-length escape; four CC0 R5 Mark II files
|
||||||
|
pinned, the QP maps of 33,665 private C-RAW files decode exactly ([cr3.md](docs/cr3.md)). 235 models
|
||||||
|
verified; RAW decoding 76% → 77%; headline numbers unchanged.
|
||||||
- **2026-10-10 (UI docking):** Library, Tools, and Presets panels can be regrouped, split, floated within the app window, closed, and reopened. Tools keeps the current Edit/Crop/Masking mode; the photo view and filmstrip stay together. Panel moves and reset are available as UI commands, and saved UI preferences retain arrangements. Widget state styling uses the shared `craft-ui` theme helper, retaining the dark palette, typography, spacing and per-state borders. No readiness percentage change.
|
- **2026-10-10 (UI docking):** Library, Tools, and Presets panels can be regrouped, split, floated within the app window, closed, and reopened. Tools keeps the current Edit/Crop/Masking mode; the photo view and filmstrip stay together. Panel moves and reset are available as UI commands, and saved UI preferences retain arrangements. Widget state styling uses the shared `craft-ui` theme helper, retaining the dark palette, typography, spacing and per-state borders. No readiness percentage change.
|
||||||
- 2026-10-10 (RAW): RAW measured model by model against Adobe's 1,446-model list (234 verified, 943
|
- 2026-10-10 (RAW): RAW measured model by model against Adobe's 1,446-model list (234 verified, 943
|
||||||
unverified, 233 preview-only, 36 unsupported; ~84% of photographers' cameras decode, ~40% on a
|
unverified, 233 preview-only, 36 unsupported; ~84% of photographers' cameras decode, ~40% on a
|
||||||
@@ -157,6 +161,7 @@ Ranked toward beta; detail in [docs/roadmap.md](docs/roadmap.md), gaps in [docs/
|
|||||||
|
|
||||||
| Date | Change | Summary |
|
| Date | Change | Summary |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| 2026-10-11 | minor | EOS R5 Mark II CR3 verified: CR3 on four verified bodies, RAW decoding 76% → 77%; headline numbers unchanged |
|
||||||
| 2026-10-10 | minor | RAW measured model by model; RAW decode and colour as explicit rows: full 59% → 61%, mainstream 51% → 49%, essentials 63% → 64%; beta ~14 points |
|
| 2026-10-10 | minor | RAW measured model by model; RAW decode and colour as explicit rows: full 59% → 61%, mainstream 51% → 49%, essentials 63% → 64%; beta ~14 points |
|
||||||
| 2026-10-10 | minor | Full ready restored to the additive weighted sum (~59%; method aligned with the standard, no new evidence); hours per audience; beta ~16 points away |
|
| 2026-10-10 | minor | Full ready restored to the additive weighted sum (~59%; method aligned with the standard, no new evidence); hours per audience; beta ~16 points away |
|
||||||
| 2026-10-10 | minor | Mainstream practitioner and essentials user numbers; full ready 55% → 46% (method written down); beta 340–600 h |
|
| 2026-10-10 | minor | Mainstream practitioner and essentials user numbers; full ready 55% → 46% (method written down); beta 340–600 h |
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ impl SettingsHashes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Bump when the pipeline's output changes, to invalidate cached thumbnails.
|
/// Bump when the pipeline's output changes, to invalidate cached thumbnails.
|
||||||
pub const RENDER_CACHE_VERSION: u64 = 42;
|
pub const RENDER_CACHE_VERSION: u64 = 43;
|
||||||
|
|
||||||
/// Thumbnails render at one of these long edges (so window/cell size changes reuse the cache).
|
/// Thumbnails render at one of these long edges (so window/cell size changes reuse the cache).
|
||||||
pub const THUMB_SIZES: [usize; 4] = [128, 256, 384, 512];
|
pub const THUMB_SIZES: [usize; 4] = [128, 256, 384, 512];
|
||||||
|
|||||||
Vendored
+36
-8
@@ -10,9 +10,12 @@
|
|||||||
//!
|
//!
|
||||||
//! Current support: version 0x100 lossless Bayer RAW and horizontal-tile C-RAW,
|
//! Current support: version 0x100 lossless Bayer RAW and horizontal-tile C-RAW,
|
||||||
//! plus version 0x200 single-tile 14-bit C-RAW with adaptive QP quantization
|
//! plus version 0x200 single-tile 14-bit C-RAW with adaptive QP quantization
|
||||||
//! (including odd-height QP maps, as on the EOS R7).
|
//! (including odd-height QP maps, as on the EOS R7, and odd-height Bayer planes, as on the EOS R5 Mark II).
|
||||||
//! Both ff01/ff02/ff03 and ff11/ff12/ff13 marker families are supported.
|
//! Both ff01/ff02/ff03 and ff11/ff12/ff13 marker families are supported.
|
||||||
//! Six full M50/R100/R8 sensor fixtures match an external decoder sample for sample.
|
//! Six full M50/R100/R8 sensor fixtures match an external decoder sample for sample.
|
||||||
|
//! The QP map's first-symbol literal and its escape (the T.87 limited-length layout) were found
|
||||||
|
//! on EOS R5 Mark II maps, whose larger QP steps need them; every map of 33,665 R5 Mark II files
|
||||||
|
//! decodes to the exact end of its entropy stream with them.
|
||||||
//! Unverified coding variants return explicit unsupported errors.
|
//! Unverified coding variants return explicit unsupported errors.
|
||||||
|
|
||||||
use super::crx_wavelet::{self, Band as WaveletBand, TileEdges};
|
use super::crx_wavelet::{self, Band as WaveletBand, TileEdges};
|
||||||
@@ -25,6 +28,8 @@ const MAX_TILES: usize = 1024;
|
|||||||
const MAX_HEADER_BYTES: usize = 1 << 20;
|
const MAX_HEADER_BYTES: usize = 1 << 20;
|
||||||
const MAX_CRX_SAMPLES: usize = 200_000_000;
|
const MAX_CRX_SAMPLES: usize = 200_000_000;
|
||||||
const MAX_CRX_EDGE: u32 = 65_536;
|
const MAX_CRX_EDGE: u32 = 65_536;
|
||||||
|
/// Unary QP-map prefix length that announces an 8-bit escaped symbol.
|
||||||
|
const QP_ESCAPE_ZEROS: u32 = 23;
|
||||||
const RUN_EXPONENT: [u8; 32] = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
const RUN_EXPONENT: [u8; 32] = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
||||||
|
|
||||||
fn corrupt(reason: &str) -> RawError {
|
fn corrupt(reason: &str) -> RawError {
|
||||||
@@ -528,13 +533,17 @@ impl Bits<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn qp_rice(&mut self, k: u32) -> Result<u32> {
|
fn qp_rice(&mut self, k: u32) -> Result<u32> {
|
||||||
|
// Limited-length code (the ITU-T T.87 layout for a 32-bit limit and 8-bit symbols):
|
||||||
|
// a quotient of 23 or more is sent as 23 zeros, the terminating 1 and the symbol in 8 bits.
|
||||||
let mut zeros = 0;
|
let mut zeros = 0;
|
||||||
while zeros < 16 && self.take(1)? == 0 {
|
while self.take(1)? == 0 {
|
||||||
zeros += 1;
|
zeros += 1;
|
||||||
|
if zeros > QP_ESCAPE_ZEROS {
|
||||||
|
return Err(corrupt("QP Rice escape prefix exceeds 23 bits"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if zeros == 16 {
|
if zeros == QP_ESCAPE_ZEROS {
|
||||||
// QP escape has no unary terminating 1 before the 16-bit literal.
|
self.take(8)
|
||||||
self.take(16)
|
|
||||||
} else if k <= 20 {
|
} else if k <= 20 {
|
||||||
Ok((zeros << k) | self.take(k)?)
|
Ok((zeros << k) | self.take(k)?)
|
||||||
} else {
|
} else {
|
||||||
@@ -752,7 +761,8 @@ fn qp_map(src: &[u8], width: usize, height: usize) -> Result<QpMap> {
|
|||||||
let above = *previous.get(x).ok_or_else(|| corrupt("above QP outside row"))?;
|
let above = *previous.get(x).ok_or_else(|| corrupt("above QP outside row"))?;
|
||||||
let corner = if x == 0 { above } else { *previous.get(x - 1).ok_or_else(|| corrupt("corner QP outside row"))? };
|
let corner = if x == 0 { above } else { *previous.get(x - 1).ok_or_else(|| corrupt("corner QP outside row"))? };
|
||||||
let right = previous.get(x + 1).copied().unwrap_or(above);
|
let right = previous.get(x + 1).copied().unwrap_or(above);
|
||||||
let symbol = bits.qp_rice(k)?;
|
// The map opens with its first symbol as a 32-bit literal; every later one is Rice coded.
|
||||||
|
let symbol = if x == 0 && y == 0 { (bits.take(16)? << 16) | bits.take(16)? } else { bits.qp_rice(k)? };
|
||||||
let value = median(left, above, corner).checked_add(signed(symbol)).ok_or_else(|| corrupt("QP prediction overflow"))?;
|
let value = median(left, above, corner).checked_add(signed(symbol)).ok_or_else(|| corrupt("QP prediction overflow"))?;
|
||||||
if !(131..=167).contains(&value) {
|
if !(131..=167).contains(&value) {
|
||||||
return Err(RawError::Unsupported(format!("Canon CRX adaptive QP value {value}")));
|
return Err(RawError::Unsupported(format!("Canon CRX adaptive QP value {value}")));
|
||||||
@@ -984,9 +994,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn qp_escape_and_average_precede_the_quantization_table() {
|
fn qp_escape_and_average_precede_the_quantization_table() {
|
||||||
let mut bits = Bits { src: &[0, 0, 1, 0x2c], at: 0 };
|
// 23 zeros, the terminating 1, then the symbol in 8 bits.
|
||||||
assert_eq!(bits.qp_rice(0).unwrap(), 300);
|
let mut bits = Bits { src: &[0, 0, 1, 0x18], at: 0 };
|
||||||
|
assert_eq!(bits.qp_rice(0).unwrap(), 24);
|
||||||
assert_eq!(bits.at, 32);
|
assert_eq!(bits.at, 32);
|
||||||
|
// 22 zeros are an ordinary Rice prefix.
|
||||||
|
let mut bits = Bits { src: &[0, 0, 2, 0], at: 0 };
|
||||||
|
assert_eq!(bits.qp_rice(0).unwrap(), 22);
|
||||||
|
assert_eq!(bits.at, 23);
|
||||||
|
assert!(Bits { src: &[0, 0, 0, 0x80, 0], at: 0 }.qp_rice(0).is_err());
|
||||||
|
// The map's first symbol is a 32-bit literal (300 = QP 150 from prediction 0).
|
||||||
let map = qp_map(&[0, 0, 1, 0x2c, 0x94], 1, 4).unwrap();
|
let map = qp_map(&[0, 0, 1, 0x2c, 0x94], 1, 4).unwrap();
|
||||||
assert_eq!(map.data, [150; 4]);
|
assert_eq!(map.data, [150; 4]);
|
||||||
assert!(qp_map(&[0, 0, 1, 0x2c, 0x95], 1, 4).is_err());
|
assert!(qp_map(&[0, 0, 1, 0x2c, 0x95], 1, 4).is_err());
|
||||||
@@ -1003,6 +1020,17 @@ mod tests {
|
|||||||
assert!(matches!(qp_map(&[0, 0, 1, 4, 0x94], 1, 4), Err(RawError::Unsupported(_))));
|
assert!(matches!(qp_map(&[0, 0, 1, 4, 0x94], 1, 4), Err(RawError::Unsupported(_))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn long_qp_prefixes_and_escapes_as_on_the_eos_r5_mark_ii() {
|
||||||
|
// EOS R5 Mark II maps (QP 150–162) jump by up to 12 where k is 0: an 18-zero prefix that an
|
||||||
|
// escape after 16 zeros misread, then a real escape (23 zeros, 1, symbol 23 = −12).
|
||||||
|
let src = [0x00, 0x00, 0x01, 0x2c, 0x90, 0x00, 0x01, 0x90, 0x00, 0x00, 0x08, 0xb8];
|
||||||
|
assert_eq!(qp_map(&src, 7, 1).unwrap().data, [150, 150, 150, 159, 159, 159, 147]);
|
||||||
|
for end in 0..src.len() {
|
||||||
|
assert!(qp_map(&src[..end], 7, 1).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn odd_height_qp_map_uses_its_last_row_alone() {
|
fn odd_height_qp_map_uses_its_last_row_alone() {
|
||||||
// EOS R7 C-RAW: 4732 sensor rows give a 1183-row QP map, so the last
|
// EOS R7 C-RAW: 4732 sensor rows give a 1183-row QP map, so the last
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ fn corpus() -> PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check(name: &str, hash: u64, sensor: (usize, usize), developed: (usize, usize)) {
|
fn check(name: &str, hash: u64, sensor: (usize, usize), developed: (usize, usize)) {
|
||||||
|
check_against(name, hash, sensor, Some(developed), "the independent reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_against(name: &str, hash: u64, sensor: (usize, usize), developed: Option<(usize, usize)>, reference: &str) {
|
||||||
let path = corpus().join("raw").join(name);
|
let path = corpus().join("raw").join(name);
|
||||||
let Ok(bytes) = std::fs::read(&path) else {
|
let Ok(bytes) = std::fs::read(&path) else {
|
||||||
eprintln!("skip: {} absent", path.display());
|
eprintln!("skip: {} absent", path.display());
|
||||||
@@ -25,12 +29,14 @@ fn check(name: &str, hash: u64, sensor: (usize, usize), developed: (usize, usize
|
|||||||
assert_eq!(raw.format, RawFormat::Cr3);
|
assert_eq!(raw.format, RawFormat::Cr3);
|
||||||
raw.validate().unwrap();
|
raw.validate().unwrap();
|
||||||
assert_eq!((raw.width, raw.height, raw.cpp), (sensor.0, sensor.1, 1));
|
assert_eq!((raw.width, raw.height, raw.cpp), (sensor.0, sensor.1, 1));
|
||||||
assert_eq!(raw.info().developed_size(), developed);
|
if let Some(developed) = developed {
|
||||||
|
assert_eq!(raw.info().developed_size(), developed);
|
||||||
|
}
|
||||||
assert_eq!(raw.info(), probe_info(&bytes).unwrap());
|
assert_eq!(raw.info(), probe_info(&bytes).unwrap());
|
||||||
let RawData::U16(samples) = &raw.data else { panic!("{name}: integer sensor data expected") };
|
let RawData::U16(samples) = &raw.data else { panic!("{name}: integer sensor data expected") };
|
||||||
let actual =
|
let actual =
|
||||||
samples.iter().flat_map(|v| v.to_le_bytes()).fold(0xcbf2_9ce4_8422_2325u64, |h, byte| (h ^ u64::from(byte)).wrapping_mul(0x100_0000_01b3));
|
samples.iter().flat_map(|v| v.to_le_bytes()).fold(0xcbf2_9ce4_8422_2325u64, |h, byte| (h ^ u64::from(byte)).wrapping_mul(0x100_0000_01b3));
|
||||||
assert_eq!(actual, hash, "{name}: sensor pixels differ from the independent reference");
|
assert_eq!(actual, hash, "{name}: sensor pixels differ from {reference}");
|
||||||
assert!(raw.wb_multipliers.is_some(), "{name}: as-shot white balance missing");
|
assert!(raw.wb_multipliers.is_some(), "{name}: as-shot white balance missing");
|
||||||
assert!(raw.white_at(0) > raw.black.mean(), "{name}: invalid black/white levels");
|
assert!(raw.white_at(0) > raw.black.mean(), "{name}: invalid black/white levels");
|
||||||
}
|
}
|
||||||
@@ -79,6 +85,33 @@ fn canon_r8_craw_sensor_is_exact() {
|
|||||||
check("cr3-canon-r8-craw.cr3", 0xf836_a663_a795_a375, (6188, 4120), (6000, 4000));
|
check("cr3-canon-r8-craw.cr3", 0xf836_a663_a795_a375, (6188, 4120), (6000, 4000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// EOS R5 Mark II (raw.pixls.us 7881–7884, CC0). No external decoder was run on these: the hashes pin
|
||||||
|
/// LightCraft's own decode. Lossless RAW is CRX 0x100, as in the oracle-checked fixtures above, with
|
||||||
|
/// odd-height (2825- and 1787-row) Bayer planes; every entropy stream decodes to its exact end. These
|
||||||
|
/// low-ISO C-RAW files need no QP-map escape (most of the camera's files do; that is covered by the unit
|
||||||
|
/// tests in `crx.rs`, see docs/cr3.md). The developed images match the camera's own previews.
|
||||||
|
fn check_r5m2(name: &str, hash: u64, sensor: (usize, usize), developed: Option<(usize, usize)>) {
|
||||||
|
check_against(name, hash, sensor, developed, "the pinned LightCraft decode");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn canon_r5m2_sensor_is_pinned() {
|
||||||
|
// raw.pixls.us/getfile.php/7881; SHA256 d6e6aa3b493ea8936dff0efb0cc17c87471437e7317bce37c8c82ba08b9cab7b
|
||||||
|
check_r5m2("cr3-canon-r5m2-raw.cr3", 0xff71_6fb3_0248_496f, (8480, 5650), Some((8192, 5464)));
|
||||||
|
// raw.pixls.us/getfile.php/7882; SHA256 b3c08a5c7a97299dfd58896a12b939e7b43ec78682761812524825e6e5d087be
|
||||||
|
check_r5m2("cr3-canon-r5m2-craw.cr3", 0xaf32_b453_57b5_34e5, (8480, 5650), Some((8192, 5464)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crop mode (1.6×): the sensor samples only. Its developed framing depends on how the file's misplaced valid
|
||||||
|
/// area is read, which is not part of the CRX decode.
|
||||||
|
#[test]
|
||||||
|
fn canon_r5m2_crop_mode_sensor_is_pinned() {
|
||||||
|
// raw.pixls.us/getfile.php/7883; SHA256 9f88c0ff012924193b7f4497559d133dfe626766d600b5d67689156721739ead
|
||||||
|
check_r5m2("cr3-canon-r5m2-apsc-raw.cr3", 0x31cf_630a_fe86_8958, (5376, 3574), None);
|
||||||
|
// raw.pixls.us/getfile.php/7884; SHA256 6a597497776a6abbfab8fcf12d0086ac7a3f8afea2879d61accf6bbf48d357d7
|
||||||
|
check_r5m2("cr3-canon-r5m2-apsc-craw.cr3", 0x4721_605b_2033_9332, (5376, 3574), None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn canon_m50_craw_crop_is_the_shot_aspect() {
|
fn canon_m50_craw_crop_is_the_shot_aspect() {
|
||||||
// raw.pixls.us/getfile.php/2663: the 1:1 square starts 1000 px right of the recommended crop's origin,
|
// raw.pixls.us/getfile.php/2663: the 1:1 square starts 1000 px right of the recommended crop's origin,
|
||||||
|
|||||||
@@ -2039,5 +2039,8 @@
|
|||||||
"Downloading model": "Modell wird heruntergeladen",
|
"Downloading model": "Modell wird heruntergeladen",
|
||||||
"Finding faces": "Gesichter werden gesucht",
|
"Finding faces": "Gesichter werden gesucht",
|
||||||
"Synchronizing folder": "Ordner wird synchronisiert",
|
"Synchronizing folder": "Ordner wird synchronisiert",
|
||||||
"Looking for changes": "Änderungen werden gesucht"
|
"Looking for changes": "Änderungen werden gesucht",
|
||||||
|
"imported earlier switch over with Photo ▸ Reload from Disk.": "Bereits importierte Fotos wechseln mit Foto → Vom Datenträger neu laden zur RAW-Bearbeitung.",
|
||||||
|
"Canon EOS R5 Mark II C-RAW files that opened as \"preview only\" (more than half of them, depending on the": "C-RAW-Dateien der Canon EOS R5 Mark II, die als „Nur Vorschau“ geöffnet wurden (je nach Motiv mehr als die Hälfte),",
|
||||||
|
"scene) now develop from their sensor data with every editing tool, like the camera's other raws. Photos": "werden jetzt wie die übrigen RAW-Dateien der Kamera aus ihren Sensordaten mit allen Werkzeugen bearbeitet."
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-1
@@ -18,7 +18,7 @@ are the public prose descriptions and patents cited in
|
|||||||
embedded-JPEG fallback and its visible warning when a JPEG is present. So does
|
embedded-JPEG fallback and its visible warning when a JPEG is present. So does
|
||||||
any other CR3 decode error (a corrupt file, or a body whose CRX stream the
|
any other CR3 decode error (a corrupt file, or a body whose CRX stream the
|
||||||
decoder misreads): every CR3 opened from its embedded JPEG before this decoder,
|
decoder misreads): every CR3 opened from its embedded JPEG before this decoder,
|
||||||
and only three bodies are verified, so a CR3 never fails to import or load
|
and only four bodies are verified, so a CR3 never fails to import or load
|
||||||
where a preview exists. HEVC-only preview tracks are recognized but are not
|
where a preview exists. HEVC-only preview tracks are recognized but are not
|
||||||
decoded.
|
decoded.
|
||||||
|
|
||||||
@@ -49,6 +49,16 @@ control. The exact inputs and reference hashes are:
|
|||||||
| Canon R8 RAW, raw.pixls.us 6585 | `7d5c6dbb11ff7e6ee58715d90a20f5d801e8b103f4711ff6ea329ceafcef254c` | `63c1c6d8d1eb2312` |
|
| Canon R8 RAW, raw.pixls.us 6585 | `7d5c6dbb11ff7e6ee58715d90a20f5d801e8b103f4711ff6ea329ceafcef254c` | `63c1c6d8d1eb2312` |
|
||||||
| Canon R8 C-RAW, raw.pixls.us 6587 | `df33cf394573645ce03dea1b2e9f0b5cc2b7734e9e3391ee7114151414cf2812` | `f836a663a795a375` |
|
| Canon R8 C-RAW, raw.pixls.us 6587 | `df33cf394573645ce03dea1b2e9f0b5cc2b7734e9e3391ee7114151414cf2812` | `f836a663a795a375` |
|
||||||
|
|
||||||
|
The EOS R5 Mark II files (raw.pixls.us 7881–7884, CC0) are pinned to LightCraft's own decode; no external
|
||||||
|
decoder was run on them:
|
||||||
|
|
||||||
|
| File | Input SHA-256 | Sensor FNV-1a (u16 little-endian) |
|
||||||
|
|---|---|---|
|
||||||
|
| Canon R5 Mark II RAW, raw.pixls.us 7881 | `d6e6aa3b493ea8936dff0efb0cc17c87471437e7317bce37c8c82ba08b9cab7b` | `ff716fb30248496f` |
|
||||||
|
| Canon R5 Mark II C-RAW, raw.pixls.us 7882 | `b3c08a5c7a97299dfd58896a12b939e7b43ec78682761812524825e6e5d087be` | `af32b45357b534e5` |
|
||||||
|
| Canon R5 Mark II crop-mode RAW, raw.pixls.us 7883 | `9f88c0ff012924193b7f4497559d133dfe626766d600b5d67689156721739ead` | `31cf630afe868958` |
|
||||||
|
| Canon R5 Mark II crop-mode C-RAW, raw.pixls.us 7884 | `6a597497776a6abbfab8fcf12d0086ac7a3f8afea2879d61accf6bbf48d357d7` | `4721605b20339332` |
|
||||||
|
|
||||||
Reference pixels were observed from the DNGLab 0.8.0 macOS arm64 release
|
Reference pixels were observed from the DNGLab 0.8.0 macOS arm64 release
|
||||||
binary; no decoder source was read or copied, and it is not shipped or linked.
|
binary; no decoder source was read or copied, and it is not shipped or linked.
|
||||||
The release ZIP SHA-256 was
|
The release ZIP SHA-256 was
|
||||||
@@ -63,6 +73,34 @@ the nonlinear integer table, then multiplication, division by eight, addition
|
|||||||
of the subband base and a minimum step of one. QP values 131–167 are verified;
|
of the subband base and a minimum step of one. QP values 131–167 are verified;
|
||||||
unmeasured values are rejected.
|
unmeasured values are rejected.
|
||||||
|
|
||||||
|
The QP map is coded as follows (established on the EOS R5 Mark II). Its first symbol is a 32-bit
|
||||||
|
big-endian literal, mapped like every other symbol and added to a prediction of zero. Every later
|
||||||
|
symbol is Rice coded with a limited-length escape: a quotient of 23 or more is written as 23 zeros,
|
||||||
|
the terminating 1 and the symbol in 8 bits. This is the escape layout of ITU-T T.87 for a 32-bit
|
||||||
|
code-length limit and 8-bit symbols, without that standard's minus-one offset. In the R8 maps only
|
||||||
|
the first symbol needs more than 15 leading zeros, and its bits read the same whether taken as a
|
||||||
|
32-bit literal or as an escape after 16 zeros with a 16-bit literal (the rule LightCraft used before).
|
||||||
|
The R7 maps decoded to their exact ends under that rule, which a later long prefix would have broken;
|
||||||
|
no R7 file was at hand to recheck them. R5 Mark II maps (QP 150–162) also jump by up to 12 where the Rice parameter is 0. That
|
||||||
|
gives 18- to 22-zero prefixes, which the 16-zero rule misread as escapes ("Canon CRX adaptive QP value
|
||||||
|
−21087" and other out-of-range values; the file then opened as a preview). It also gives real escapes,
|
||||||
|
symbols 23 and 24. Escapes were seen only where the Rice parameter is 0 (in 100 of 612 maps; all 351 inspected, up to 10 per map); at a larger
|
||||||
|
parameter they would use the same layout, which is unobserved. With this coding the QP maps of all
|
||||||
|
33,665 R5 Mark II C-RAW files in a private library (version `0x200`, 8480 × 5650) decode to the exact
|
||||||
|
end of their entropy streams, with values 150–162. So do the reduced-size tracks of 306 of those
|
||||||
|
files, the two CC0 R5 Mark II C-RAW files above and the R8 C-RAW fixture; all six fixture hashes are
|
||||||
|
unchanged. Under the 16-zero rule, 174 of those 306 files (57%) failed and opened as previews, all
|
||||||
|
with out-of-range values (none at QP 168). The two CC0 C-RAW files are low-ISO shots whose maps need no
|
||||||
|
long prefix: they decoded under the old rule too, so the escape is covered by synthetic unit tests in
|
||||||
|
`crx.rs` rather than by a public file. Render cache version 43 redraws thumbnails of files whose decode
|
||||||
|
changed; photos imported as preview-only switch over with Photo ▸ Reload from Disk.
|
||||||
|
|
||||||
|
The R5 Mark II sensor has 5650 rows (3574 in crop mode), so its Bayer planes have odd heights (2825,
|
||||||
|
1787). Lossless planes decode as before. In C-RAW every wavelet level has an odd height (2825 → 1413 →
|
||||||
|
707), and each subband's entropy stream ends exactly where the subband geometry says. The synthesis
|
||||||
|
uses the same boundary rules that are verified on the R8's odd lengths. Decoded rows show no step
|
||||||
|
down to the last sensor row, and the developed images match the camera's embedded JPEGs at 100 %.
|
||||||
|
|
||||||
An odd QP-map height (EOS R7: 4732 sensor rows give 1183 QP rows) leaves the
|
An odd QP-map height (EOS R7: 4732 sensor rows give 1183 QP rows) leaves the
|
||||||
last row of the second-level high-frequency bands without a partner row; that
|
last row of the second-level high-frequency bands without a partner row; that
|
||||||
row's QP is used on its own. The odd-height map decodes to the exact end of its
|
row's QP is used on its own. The odd-height map decodes to the exact end of its
|
||||||
|
|||||||
+4
-3
@@ -1,6 +1,6 @@
|
|||||||
# Gaps: where LightCraft falls short of Lightroom
|
# Gaps: where LightCraft falls short of Lightroom
|
||||||
|
|
||||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created; absorbs the checklist's Top gaps and the ROADMAP's honest assessment, re-ranked after a full re-measure) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (gaps 2 and 10: EOS R5 Mark II CR3 verified) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||||
|
|
||||||
Every known shortfall, one entry each, ranked by user impact (how many Lightroom users hit it, and
|
Every known shortfall, one entry each, ranked by user impact (how many Lightroom users hit it, and
|
||||||
how hard it blocks them), then by effort. **Agents pick work from the top** (the first entry nobody is
|
how hard it blocks them), then by effort. **Agents pick work from the top** (the first entry nobody is
|
||||||
@@ -16,7 +16,7 @@ Hours are Opus 5.5 agent wall-clock hours (see [target-app-parity.md](target-app
|
|||||||
| # | Gap | Evidence | User impact | Hours | Doc |
|
| # | Gap | Evidence | User impact | Hours | Doc |
|
||||||
|---:|---|---|---|---:|---|
|
|---:|---|---|---|---:|---|
|
||||||
| 1 B | **Camera colour is estimated, not measured** (LR-PROF-CAMERACOLOR). Raws start from a per-file fit to the camera JPEG, 4 bundled profiles or 52 spectral matrices; others use a neutral matrix | ΔE vs camera JPEG 2.9–10 after fitting (raw-parity.md); 0 chart-calibrated models vs 1,500 Adobe Standard profiles | every raw shooter sees colour that is close but not Lightroom's; some get neutral-matrix colour | 50–90 | [raw-parity](raw-parity.md#colour) |
|
| 1 B | **Camera colour is estimated, not measured** (LR-PROF-CAMERACOLOR). Raws start from a per-file fit to the camera JPEG, 4 bundled profiles or 52 spectral matrices; others use a neutral matrix | ΔE vs camera JPEG 2.9–10 after fitting (raw-parity.md); 0 chart-calibrated models vs 1,500 Adobe Standard profiles | every raw shooter sees colour that is close but not Lightroom's; some get neutral-matrix colour | 50–90 | [raw-parity](raw-parity.md#colour) |
|
||||||
| 2 B | **CR3 beyond three verified bodies** (LR-IMP-FORMATS): CRX variants other than those verified on M50 / R100 / R8 fall back to the preview; CR3 sRAW / mRAW and HEIF CR3 too | measured: Canon is the largest bucket (33% of photographers) and its share whose camera fully works is the lowest of the big four, 72%; 17 of 22 popular Canon bodies write CR3, 2 verified (raw-parity.md) | +6.5 points of photographers whose camera works, the biggest single raw gain | 25–45 | [raw-parity](raw-parity.md#remaining-work-ranked-by-photographers-unlocked-per-hour) |
|
| 2 B | **CR3 beyond four verified bodies** (LR-IMP-FORMATS): CRX variants other than those verified on M50 / R100 / R8 / R5 Mark II fall back to the preview; CR3 sRAW / mRAW and HEIF CR3 too | measured: Canon is the largest bucket (33% of photographers) and its share whose camera fully works is the lowest of the big four, 73%; 18 of 22 popular Canon bodies write CR3, 4 verified (raw-parity.md) | +6.2 points of photographers whose camera works, the biggest single raw gain | 25–45 | [raw-parity](raw-parity.md#remaining-work-ranked-by-photographers-unlocked-per-hour) |
|
||||||
| 3 B | **Render fidelity unmeasured** (LR-BEHAV-RENDER-FIDELITY): tone, highlights, texture / clarity / dehaze, NR and sharpening are tuned by eye | no side-by-side suite; a retune needs a new process version (only V1 exists) | edits imported from Lightroom look different; the look "isn't Lightroom's" | 30–60 | [raw-parity](raw-parity.md), [process-versions](process-versions.md) |
|
| 3 B | **Render fidelity unmeasured** (LR-BEHAV-RENDER-FIDELITY): tone, highlights, texture / clarity / dehaze, NR and sharpening are tuned by eye | no side-by-side suite; a retune needs a new process version (only V1 exists) | edits imported from Lightroom look different; the look "isn't Lightroom's" | 30–60 | [raw-parity](raw-parity.md), [process-versions](process-versions.md) |
|
||||||
| 4 B | **Original-pixel detail at 100%** (LR-VIEW-ZOOM, P0): the whole-image preview is capped (2,560 px default); compare, overlays and soft proofing lack sharp zoom windows (#323) | checklist row 🟡 | checking focus, the first thing culling needs, isn't reliable on large files | 8–15 | [ui-parity](ui-parity.md) |
|
| 4 B | **Original-pixel detail at 100%** (LR-VIEW-ZOOM, P0): the whole-image preview is capped (2,560 px default); compare, overlays and soft proofing lack sharp zoom windows (#323) | checklist row 🟡 | checking focus, the first thing culling needs, isn't reliable on large files | 8–15 | [ui-parity](ui-parity.md) |
|
||||||
| 5 B | **AI masks: Subject, Sky, People, Background, Landscape** are heuristics; Object / Describe run SAM 3 but its download has no mirror configured | `crates/segment`; ai-masks.md; MASK rows 67% | masking is how most Lightroom users edit today | 40–70 + model decision | [target-app-parity](target-app-parity.md#ai) |
|
| 5 B | **AI masks: Subject, Sky, People, Background, Landscape** are heuristics; Object / Describe run SAM 3 but its download has no mirror configured | `crates/segment`; ai-masks.md; MASK rows 67% | masking is how most Lightroom users edit today | 40–70 + model decision | [target-app-parity](target-app-parity.md#ai) |
|
||||||
@@ -24,7 +24,7 @@ Hours are Opus 5.5 agent wall-clock hours (see [target-app-parity.md](target-app
|
|||||||
| 7 | **Nikon High Efficiency NEF** (HE / HE★ on Z 8, Z 9, Z 6III, Z f, Z50II, Z5II when set to HE) | named and preview only (#193); needs a pure-Rust JPEG XS decoder | +1.1 points (only shots taken in HE; lossless works on the same bodies); low gain per hour (~0.04), so not a beta blocker | 20–40 | [raw-parity](raw-parity.md) |
|
| 7 | **Nikon High Efficiency NEF** (HE / HE★ on Z 8, Z 9, Z 6III, Z f, Z50II, Z5II when set to HE) | named and preview only (#193); needs a pure-Rust JPEG XS decoder | +1.1 points (only shots taken in HE; lossless works on the same bodies); low gain per hour (~0.04), so not a beta blocker | 20–40 | [raw-parity](raw-parity.md) |
|
||||||
| 8 B | **No lens profile database** (LR-EDIT-OPTICS-PROFILE): only DNG opcodes, RW2 in-file distortion and Sony ILCE-7RM4A distortion | Adobe ships 3,635 lens profiles; we never use them | distortion / vignetting correction is a default step for many | 40–80 + calibration shots | [raw-parity](raw-parity.md#lens-profiles) |
|
| 8 B | **No lens profile database** (LR-EDIT-OPTICS-PROFILE): only DNG opcodes, RW2 in-file distortion and Sony ILCE-7RM4A distortion | Adobe ships 3,635 lens profiles; we never use them | distortion / vignetting correction is a default step for many | 40–80 + calibration shots | [raw-parity](raw-parity.md#lens-profiles) |
|
||||||
| 9 B | **Tests don't run in CI on macOS, Windows or Linux x64**: only FreeBSD runs `cargo test`; the others build packages | `.github/workflows/` (freebsd, packaging-lint, release, windows-arm64) | regressions reach users on the main platforms; `cargo xtask ci` runs only locally | 6–12 | [target-app-parity](target-app-parity.md#by-dimension) |
|
| 9 B | **Tests don't run in CI on macOS, Windows or Linux x64**: only FreeBSD runs `cargo test`; the others build packages | `.github/workflows/` (freebsd, packaging-lint, release, windows-arm64) | regressions reach users on the main platforms; `cargo xtask ci` runs only locally | 6–12 | [target-app-parity](target-app-parity.md#by-dimension) |
|
||||||
| 10 B | **Per-model verification thin, plus cheap per-body decode fixes**: 234 of 1,446 Adobe models verified (16%), ~40% of photographers on a verified body; Nikon 5 bodies verified, Canon 11. Cheap fixes: Z 6II packed 14-bit NEF (#769, PR #671), Sony A100 / F828 regression (#702), DSLR-A200…A390 / A850 12-bit ARW (#535) | measured: [raw/coverage.tsv](raw/coverage.tsv) | per-body bugs (levels, crops, WB) surface only from users | 25–45 | [raw-parity](raw-parity.md#by-maker-measured) |
|
| 10 B | **Per-model verification thin, plus cheap per-body decode fixes**: 235 of 1,446 Adobe models verified (16%), ~42% of photographers on a verified body; Nikon 5 bodies verified, Canon 12. Cheap fixes: Z 6II packed 14-bit NEF (#769, PR #671), Sony A100 / F828 regression (#702), DSLR-A200…A390 / A850 12-bit ARW (#535) | measured: [raw/coverage.tsv](raw/coverage.tsv) | per-body bugs (levels, crops, WB) surface only from users | 25–45 | [raw-parity](raw-parity.md#by-maker-measured) |
|
||||||
| 11 | **Enhance: Raw Details, Super Resolution; AI denoise without shippable weights or X-Trans** | ENH rows 0%; denoise Bayer only, RawNIND weights GPL and opt-in | Fujifilm users get no AI denoise; nobody gets it out of the box | 30–60 + model decision | [raw-parity](raw-parity.md#demosaic-levels-crops-and-lens-metadata) |
|
| 11 | **Enhance: Raw Details, Super Resolution; AI denoise without shippable weights or X-Trans** | ENH rows 0%; denoise Bayer only, RawNIND weights GPL and opt-in | Fujifilm users get no AI denoise; nobody gets it out of the box | 30–60 + model decision | [raw-parity](raw-parity.md#demosaic-levels-crops-and-lens-metadata) |
|
||||||
| 12 | **Content-aware / generative remove, detect distractions, reflections removal** | REM rows 75%; patch synthesis missing | cleanup work goes back to Photoshop | 25–45 (+ generative model) | [target-app-parity](target-app-parity.md#ai) |
|
| 12 | **Content-aware / generative remove, detect distractions, reflections removal** | REM rows 75%; patch synthesis missing | cleanup work goes back to Photoshop | 25–45 (+ generative model) | [target-app-parity](target-app-parity.md#ai) |
|
||||||
| 13 | **Lightroom catalog migration is one-way and approximate**: unsupported Adobe profiles / AI settings archived, history kept as data | lightroom-catalog-import.md | switching users lose some looks | 8–12 | [file-format-parity](file-format-parity.md) |
|
| 13 | **Lightroom catalog migration is one-way and approximate**: unsupported Adobe profiles / AI settings archived, history kept as data | lightroom-catalog-import.md | switching users lose some looks | 8–12 | [file-format-parity](file-format-parity.md) |
|
||||||
@@ -72,6 +72,7 @@ Beta-blocking gaps (B) total **~230–430 h**; with the stability and platform w
|
|||||||
|
|
||||||
| Date | Change | Summary |
|
| Date | Change | Summary |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| 2026-10-11 | minor | Gaps 2 and 10 shrink: EOS R5 Mark II CR3 decodes and is verified (fourth CR3 body, Canon 12 verified, 235 models, ~42% on a verified body); CR3 gain +6.5 → +6.2 points |
|
||||||
| 2026-10-10 | minor | RAW gaps re-measured model by model (raw-parity.md): CR3, compressed ORF and verification entries carry measured shares; HE NEF no longer a beta blocker (+1.1 points for 20–40 h); verification entry absorbs the cheap per-body fixes (#769, #702, A200 series) |
|
| 2026-10-10 | minor | RAW gaps re-measured model by model (raw-parity.md): CR3, compressed ORF and verification entries carry measured shares; HE NEF no longer a beta blocker (+1.1 points for 20–40 h); verification entry absorbs the cheap per-body fixes (#769, #702, A200 series) |
|
||||||
| 2026-10-10 | minor | Beta total raised to 340–600 h to include the ~92 open core-path user issues |
|
| 2026-10-10 | minor | Beta total raised to 340–600 h to include the ~92 open core-path user issues |
|
||||||
| 2026-10-10 | major | Created from the checklist's Top gaps (whose items 1–2 had been duplicated by a merge) and ROADMAP's Where we stand; re-ranked; added evidence, impact, hours and beta flags; added platform-CI, lens-database, HE NEF and localization gaps |
|
| 2026-10-10 | major | Created from the checklist's Top gaps (whose items 1–2 had been duplicated by a merge) and ROADMAP's Where we stand; re-ranked; added evidence, impact, hours and beta flags; added platform-CI, lens-database, HE NEF and localization gaps |
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+19
-17
@@ -1,6 +1,6 @@
|
|||||||
# RAW parity: cameras, formats, demosaic, colour and lens profiles
|
# RAW parity: cameras, formats, demosaic, colour and lens profiles
|
||||||
|
|
||||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (model-by-model measurement against Adobe's published camera list; use-weighted coverage; variant matrix; colour and lens sections; ranked next cameras) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6 (Camera Raw 18.7)
|
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (EOS R5 Mark II decoded and verified: CRX QP-map escape, odd-height planes) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6 (Camera Raw 18.7)
|
||||||
|
|
||||||
Raw processing is the deepest single dimension of Lightroom parity: a photographer whose camera
|
Raw processing is the deepest single dimension of Lightroom parity: a photographer whose camera
|
||||||
does not decode, or decodes with the wrong colour, cannot switch. This document measures it model by
|
does not decode, or decodes with the wrong colour, cannot switch. This document measures it model by
|
||||||
@@ -14,13 +14,13 @@ ranked in [gaps.md](gaps.md). Details per format: [cr3.md](cr3.md),
|
|||||||
| Measure | Value | Kind |
|
| Measure | Value | Kind |
|
||||||
|---|---:|---|
|
|---|---:|---|
|
||||||
| Adobe-listed camera models | **1,446** | measured: [raw/adobe-cameras.tsv](raw/adobe-cameras.tsv) |
|
| Adobe-listed camera models | **1,446** | measured: [raw/adobe-cameras.tsv](raw/adobe-cameras.tsv) |
|
||||||
| Decoded from sensor data and **verified** on a real file | **234** (16%) | measured: [raw/evidence.tsv](raw/evidence.tsv) |
|
| Decoded from sensor data and **verified** on a real file | **235** (16%) | measured: [raw/evidence.tsv](raw/evidence.tsv) |
|
||||||
| Decoder path should handle it, **unverified** | **943** (65%) | measured from the format rules (632 of them DNG, mostly phones) |
|
| Decoder path should handle it, **unverified** | **942** (65%) | measured from the format rules (632 of them DNG, mostly phones) |
|
||||||
| **Preview-only** (embedded JPEG) | **233** (16%) | measured |
|
| **Preview-only** (embedded JPEG) | **233** (16%) | measured |
|
||||||
| **Unsupported** (not imported, refused or decodes wrongly) | **36** (2%) | measured |
|
| **Unsupported** (not imported, refused or decodes wrongly) | **36** (2%) | measured |
|
||||||
| Models added since 2017 (Camera Raw 10+): verified / unverified / preview / unsupported | 81 / 641 / 24 / 8 of 754 | measured |
|
| Models added since 2017 (Camera Raw 10+): verified / unverified / preview / unsupported | 82 / 640 / 24 / 8 of 754 | measured |
|
||||||
| **Share of photographers whose camera fully works** (decodes from sensor data), use-weighted | **~84%** | estimated: measured classes × written usage weights × per-format confidence |
|
| **Share of photographers whose camera fully works** (decodes from sensor data), use-weighted | **~85%** | estimated: measured classes × written usage weights × per-format confidence |
|
||||||
| …of which on a body we have verified | **~40%** | estimated, same weights |
|
| …of which on a body we have verified | **~42%** | estimated, same weights |
|
||||||
| Camera colour: Adobe profiles vs ours | 1,500 Adobe Standard profiles, 481 models with Camera Matching profiles vs **4 bundled profiles** + per-file fits + 52 spectral matrices | measured (bundle listing, Adobe list, `assets/camera-profiles`) |
|
| Camera colour: Adobe profiles vs ours | 1,500 Adobe Standard profiles, 481 models with Camera Matching profiles vs **4 bundled profiles** + per-file fits + 52 spectral matrices | measured (bundle listing, Adobe list, `assets/camera-profiles`) |
|
||||||
| Lens profiles: Adobe vs ours | **3,635 vs 0** (in-file corrections only) | measured |
|
| Lens profiles: Adobe vs ours | **3,635 vs 0** (in-file corrections only) | measured |
|
||||||
| **RAW readiness** (decoding 60%, colour 25%, lens 15%) | **~56%** (range 50–60%) | estimated, see [Scores](#scores) |
|
| **RAW readiness** (decoding 60%, colour 25%, lens 15%) | **~56%** (range 50–60%) | estimated, see [Scores](#scores) |
|
||||||
@@ -42,7 +42,8 @@ committed table is stale.
|
|||||||
claims were not used.
|
claims were not used.
|
||||||
- **Verified** means a real file from that body decoded from sensor data in: the corpus test over the
|
- **Verified** means a real file from that body decoded from sensor data in: the corpus test over the
|
||||||
`RAW_SAMPLES` manifest (`xtask/src/main.rs`, 101 CC0 files; bodies whose sample is in
|
`RAW_SAMPLES` manifest (`xtask/src/main.rs`, 101 CC0 files; bodies whose sample is in
|
||||||
`KNOWN_UNSUPPORTED` excluded), `crates/raw/tests/cr3_corpus.rs` (3 bodies, exact), the RAF reference
|
`KNOWN_UNSUPPORTED` excluded), `crates/raw/tests/cr3_corpus.rs` (3 bodies exact against an external decoder;
|
||||||
|
the EOS R5 Mark II pinned, with a QP-map check of 33,665 private files), the RAF reference
|
||||||
check ([raf-compression.md](raf-compression.md)), and the raw.pixls.us bulk checks recorded in issue
|
check ([raf-compression.md](raf-compression.md)), and the raw.pixls.us bulk checks recorded in issue
|
||||||
#535 (all 100 Sony bodies there; 87 decode) and PR #215 (every Panasonic / Leica RW2 / RWL / RAW body
|
#535 (all 100 Sony bodies there; 87 decode) and PR #215 (every Panasonic / Leica RW2 / RWL / RAW body
|
||||||
there, 178 files from 118 bodies). Bulk-check body lists were matched to Adobe names through the
|
there, 178 files from 118 bodies). Bulk-check body lists were matched to Adobe names through the
|
||||||
@@ -56,14 +57,14 @@ committed table is stale.
|
|||||||
~8 years (listed in the file), 20% to the bucket's other Adobe models.
|
~8 years (listed in the file), 20% to the bucket's other Adobe models.
|
||||||
- **Per-format confidence** for unverified bodies (the chance their files decode correctly): DNG, CR2,
|
- **Per-format confidence** for unverified bodies (the chance their files decode correctly): DNG, CR2,
|
||||||
RAF, RW2 0.95; NEF, ARW, PEF 0.9; ORF, SRW, SR2 0.8; **CR3 0.6** (the CRX decoder refuses several
|
RAF, RW2 0.95; NEF, ARW, PEF 0.9; ORF, SRW, SR2 0.8; **CR3 0.6** (the CRX decoder refuses several
|
||||||
coding variants and only three bodies are verified; maintainers report the R7 working).
|
coding variants and only four bodies are verified; maintainers report the R7 working).
|
||||||
|
|
||||||
## By maker (measured)
|
## By maker (measured)
|
||||||
|
|
||||||
| Maker | Adobe models | verified | unverified | preview | unsupported | Main reason for preview / unsupported |
|
| Maker | Adobe models | verified | unverified | preview | unsupported | Main reason for preview / unsupported |
|
||||||
|---|---:|---:|---:|---:|---:|---|
|
|---|---:|---:|---:|---:|---:|---|
|
||||||
| Sony | 149 | 86 | 51 | 9 | 3 | DSLR-A200…A390 and A850 12-bit compressed ARW (preview, #535); A100 and DSC-F828 refused (regression #702); SRF not imported |
|
| Sony | 149 | 86 | 51 | 9 | 3 | DSLR-A200…A390 and A850 12-bit compressed ARW (preview, #535); A100 and DSC-F828 refused (regression #702); SRF not imported |
|
||||||
| Canon | 134 | 11 | 100 | 21 | 2 | CRW (2000–2004 bodies) preview; EOS-1D / 1Ds TIFF raws not imported |
|
| Canon | 134 | 12 | 99 | 21 | 2 | CRW (2000–2004 bodies) preview; EOS-1D / 1Ds TIFF raws not imported |
|
||||||
| Samsung | 128 | 1 | 118 | 9 | 0 | compressed SRW (NX1, NX30, NX300, NX500, NX2000, NX3000, NX3300, NX mini, Galaxy NX) |
|
| Samsung | 128 | 1 | 118 | 9 | 0 | compressed SRW (NX1, NX30, NX300, NX500, NX2000, NX3000, NX3300, NX mini, Galaxy NX) |
|
||||||
| Apple | 113 | 1 | 112 | 0 | 0 | — (DNG / ProRAW) |
|
| Apple | 113 | 1 | 112 | 0 | 0 | — (DNG / ProRAW) |
|
||||||
| Panasonic | 104 | 93 | 11 | 0 | 0 | — |
|
| Panasonic | 104 | 93 | 11 | 0 | 0 | — |
|
||||||
@@ -80,13 +81,13 @@ committed table is stale.
|
|||||||
| DJI | 21 | 0 | 21 | 0 | 0 | — (DNG) |
|
| DJI | 21 | 0 | 21 | 0 | 0 | — (DNG) |
|
||||||
| OM Digital Solutions | 7 | 0 | 0 | 7 | 0 | **compressed ORF** |
|
| OM Digital Solutions | 7 | 0 | 0 | 7 | 0 | **compressed ORF** |
|
||||||
| Kodak, Konica Minolta, Epson, Sigma, GoPro, Contax, others | 56 | 0 | 14 | 27 | 15 | DCR, GPR not imported; KDC, MRW, ERF, X3F preview |
|
| Kodak, Konica Minolta, Epson, Sigma, GoPro, Contax, others | 56 | 0 | 14 | 27 | 15 | DCR, GPR not imported; KDC, MRW, ERF, X3F preview |
|
||||||
| **All** | **1,446** | **234 (16%)** | **943 (65%)** | **233 (16%)** | **36 (2%)** | |
|
| **All** | **1,446** | **235 (16%)** | **942 (65%)** | **233 (16%)** | **36 (2%)** | |
|
||||||
|
|
||||||
## By use (estimated)
|
## By use (estimated)
|
||||||
|
|
||||||
| Bucket | Weight | Camera fully works | On a verified body | Why |
|
| Bucket | Weight | Camera fully works | On a verified body | Why |
|
||||||
|---|---:|---:|---:|---|
|
|---|---:|---:|---:|---|
|
||||||
| Canon | 33% | 72% | 16% | 17 of the 22 popular bodies write CR3; 2 of them verified, the rest at 0.6 |
|
| Canon | 33% | 73% | 19% | 18 of the 22 popular bodies write CR3; 4 of them verified (M50, R8, R100, R5 Mark II), the rest at 0.6 |
|
||||||
| Sony | 27% | 98% | 91% | bulk-checked |
|
| Sony | 27% | 98% | 91% | bulk-checked |
|
||||||
| Nikon | 16% | 91% | 12% | decoders cover every NEF coding but HE; few bodies verified |
|
| Nikon | 16% | 91% | 12% | decoders cover every NEF coding but HE; few bodies verified |
|
||||||
| Fujifilm | 10% | 91% | 45% | |
|
| Fujifilm | 10% | 91% | 45% | |
|
||||||
@@ -97,7 +98,7 @@ committed table is stale.
|
|||||||
| Leica | 1% | 95% | 5% | |
|
| Leica | 1% | 95% | 5% | |
|
||||||
| DJI | 1% | 95% | 0% | |
|
| DJI | 1% | 95% | 0% | |
|
||||||
| Medium format and others | 0.5% | 23% | 0% | IIQ, 3FR, X3F |
|
| Medium format and others | 0.5% | 23% | 0% | IIQ, 3FR, X3F |
|
||||||
| **Weighted** | 100% | **84%** | **40%** | |
|
| **Weighted** | 100% | **85%** | **42%** | |
|
||||||
|
|
||||||
About 5 in 6 raw photographers' cameras decode, but only about 2 in 5 use a body we have actually
|
About 5 in 6 raw photographers' cameras decode, but only about 2 in 5 use a body we have actually
|
||||||
checked, and Canon, the largest bucket, is the weakest of the big four.
|
checked, and Canon, the largest bucket, is the weakest of the big four.
|
||||||
@@ -110,8 +111,8 @@ checked, and Canon, the largest bucket, is the weakest of the big four.
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| CR2 | lossless JPEG slices | ✅ | 8 corpus bodies; CFA phase from `CR2CFAPattern` (#85, 35 bodies); masked-column black level |
|
| CR2 | lossless JPEG slices | ✅ | 8 corpus bodies; CFA phase from `CR2CFAPattern` (#85, 35 bodies); masked-column black level |
|
||||||
| CR2 | sRAW / mRAW (YCbCr) | ✅ | `vendor/cr2/sraw.rs`, 31 samples from 16 models |
|
| CR2 | sRAW / mRAW (YCbCr) | ✅ | `vendor/cr2/sraw.rs`, 31 samples from 16 models |
|
||||||
| CR3 | CRX lossless, version 0x100 | ✅ | M50, R100, R8 exact against a reference |
|
| CR3 | CRX lossless, version 0x100 | ✅ | M50, R100, R8 exact against a reference; R5 Mark II (odd-height planes) pinned |
|
||||||
| CR3 | C-RAW 0x100 (horizontal tiles), 0x200 (single 14-bit tile, adaptive QP) | ✅ | same 3 bodies exact |
|
| CR3 | C-RAW 0x100 (horizontal tiles), 0x200 (single 14-bit tile, adaptive QP incl. the QP-map escape) | ✅ | same 3 bodies exact; R5 Mark II pinned, QP maps of 33,665 files decode exactly, matches the camera JPEG |
|
||||||
| CR3 | other CRX variants (vertical tiles, partial subbands, other plane flags, 0x200 multi-tile) | ⬜ | refused in `crx.rs`, falls back to the preview; which bodies write them is unmeasured |
|
| CR3 | other CRX variants (vertical tiles, partial subbands, other plane flags, 0x200 multi-tile) | ⬜ | refused in `crx.rs`, falls back to the preview; which bodies write them is unmeasured |
|
||||||
| CR3 | sRAW / mRAW | ⬜ | 4-plane Bayer only |
|
| CR3 | sRAW / mRAW | ⬜ | 4-plane Bayer only |
|
||||||
| CR3 | HEIF / HDR PQ | ⬜ | HEVC tracks recognised, not decoded |
|
| CR3 | HEIF / HDR PQ | ⬜ | HEVC tracks recognised, not decoded |
|
||||||
@@ -207,10 +208,10 @@ drone DNG users (~9% of photographers by the weights above); Adobe reaches nearl
|
|||||||
|
|
||||||
| Part | Weight | Score | Basis |
|
| Part | Weight | Score | Basis |
|
||||||
|---|---:|---:|---|
|
|---|---:|---:|---|
|
||||||
| Decoding | 60% | **76%** | use-weighted 84% × 0.9 for per-body decode bugs still surfacing (levels, crops, WB: #535, #455, #461, #702) |
|
| Decoding | 60% | **77%** | use-weighted 85% × 0.9 (76.5%) for per-body decode bugs still surfacing (levels, crops, WB: #535, #455, #461, #702) |
|
||||||
| Colour | 25% | **35%** | see [Colour](#colour) |
|
| Colour | 25% | **35%** | see [Colour](#colour) |
|
||||||
| Lens profiles | 15% | **10%** | see [Lens profiles](#lens-profiles) |
|
| Lens profiles | 15% | **10%** | see [Lens profiles](#lens-profiles) |
|
||||||
| **RAW readiness** | 100% | **~56%** (range 50–60%) | 45.6 + 8.75 + 1.5; demosaic and highlight quality unmeasured |
|
| **RAW readiness** | 100% | **~56%** (range 50–60%) | 45.9 + 8.75 + 1.5; demosaic and highlight quality unmeasured |
|
||||||
|
|
||||||
The previous estimate (earlier on 2026-10-10) was ~50%, with decoding at ~78% weighted by maker
|
The previous estimate (earlier on 2026-10-10) was ~50%, with decoding at ~78% weighted by maker
|
||||||
from the format list alone. Measured model by model, decoding comes out about the same; the change is
|
from the format list alone. Measured model by model, decoding comes out about the same; the change is
|
||||||
@@ -226,7 +227,7 @@ works, from [raw/usage-weights.tsv](raw/usage-weights.tsv).
|
|||||||
| # | Camera / variant | Gain (points of photographers) | Hours | Gain per hour | Needs |
|
| # | Camera / variant | Gain (points of photographers) | Hours | Gain per hour | Needs |
|
||||||
|---:|---|---:|---:|---:|---|
|
|---:|---|---:|---:|---:|---|
|
||||||
| 1 | Compressed ORF (every Olympus / OM body since ~2008) | +2.6 | 8–15 | ~0.20 | CC0 samples (have 2) |
|
| 1 | Compressed ORF (every Olympus / OM body since ~2008) | +2.6 | 8–15 | ~0.20 | CC0 samples (have 2) |
|
||||||
| 2 | CR3: remaining CRX variants, then verify the 17 popular CR3 bodies | +6.5 | 25–45 | ~0.19 | samples per body (raw.pixls.us has most) |
|
| 2 | CR3: remaining CRX variants, then verify the other 14 popular CR3 bodies | +6.2 | 25–45 | ~0.19 | samples per body (raw.pixls.us has most) |
|
||||||
| 3 | Verify popular Nikon, Fujifilm, Canon CR2 and Pentax bodies (one CC0 file each, fix what breaks) | +2.0 | 8–15 | ~0.17 | public samples |
|
| 3 | Verify popular Nikon, Fujifilm, Canon CR2 and Pentax bodies (one CC0 file each, fix what breaks) | +2.0 | 8–15 | ~0.17 | public samples |
|
||||||
| 4 | Nikon packed 14-bit under a compressed tag (Z 6II uncompressed, #769) | +0.2 | 1–2 | ~0.13 | PR #671 exists |
|
| 4 | Nikon packed 14-bit under a compressed tag (Z 6II uncompressed, #769) | +0.2 | 1–2 | ~0.13 | PR #671 exists |
|
||||||
| 5 | Sony DSLR-A200…A390 / A850 12-bit compressed ARW | +0.4 | 3–6 | ~0.08 | samples on raw.pixls.us |
|
| 5 | Sony DSLR-A200…A390 / A850 12-bit compressed ARW | +0.4 | 3–6 | ~0.08 | samples on raw.pixls.us |
|
||||||
@@ -249,5 +250,6 @@ Beyond decoding:
|
|||||||
|
|
||||||
| Date | Change | Summary |
|
| Date | Change | Summary |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| 2026-10-11 | minor | EOS R5 Mark II verified (CRX QP-map first literal and limited-length escape, odd-height Bayer planes; 4 CC0 files pinned, QP maps of 33,665 private files): 235 verified, 942 unverified; use-weighted 85% (42% on verified bodies); decoding 77%, RAW readiness unchanged at ~56% |
|
||||||
| 2026-10-10 (later) | major | Model-by-model measurement against Adobe's published list (1,446 models: 234 verified, 943 unverified, 233 preview, 36 unsupported); `docs/raw/` data and re-measure script; use-weighted share 84% (40% on verified bodies); variant matrix; colour and lens sections with scores; ranked next cameras; RAW readiness ~56% from written parts |
|
| 2026-10-10 (later) | major | Model-by-model measurement against Adobe's published list (1,446 models: 234 verified, 943 unverified, 233 preview, 36 unsupported); `docs/raw/` data and re-measure script; use-weighted share 84% (40% on verified bodies); variant matrix; colour and lens sections with scores; ranked next cameras; RAW readiness ~56% from written parts |
|
||||||
| 2026-10-10 | major | Created: formats, makers, demosaic, colour and lens checklists; target counts from the installed Lightroom 9.6 bundle listing |
|
| 2026-10-10 | major | Created: formats, makers, demosaic, colour and lens checklists; target counts from the installed Lightroom 9.6 bundle listing |
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ Canon EOS R1 CR3 2023 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 s
|
|||||||
Canon EOS R3 CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
Canon EOS R3 CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||||
Canon EOS R5 CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
Canon EOS R5 CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||||
Canon EOS R5 C CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
Canon EOS R5 C CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||||
Canon EOS R5 Mark II CR3 2023 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
Canon EOS R5 Mark II CR3 2023 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hashes, docs/cr3.md); bulk: QP maps of 33,665 C-RAW files
|
||||||
Canon EOS R6 CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
Canon EOS R6 CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||||
Canon EOS R6 V CR3 2025 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
Canon EOS R6 V CR3 2025 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||||
Canon EOS R6 Mark II CR3 2022 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
Canon EOS R6 Mark II CR3 2022 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 86 and column 19.
|
@@ -11,6 +11,7 @@ Canon EOS 7D verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
|||||||
Canon EOS 80D verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
Canon EOS 80D verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||||
Canon EOS M50 (EOS Kiss M) verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
Canon EOS M50 (EOS Kiss M) verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||||
Canon EOS R100 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
Canon EOS R100 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||||
|
Canon EOS R5 Mark II verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hashes, docs/cr3.md); bulk: QP maps of 33,665 C-RAW files
|
||||||
Canon EOS R8 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
Canon EOS R8 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||||
Canon EOS-5D Mark III verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
Canon EOS-5D Mark III verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||||
Fujifilm GFX 100 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
Fujifilm GFX 100 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 2 and column 3.
|
+11
-10
@@ -1,6 +1,6 @@
|
|||||||
# Target-app parity: LightCraft vs Adobe Lightroom
|
# Target-app parity: LightCraft vs Adobe Lightroom
|
||||||
|
|
||||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (full re-measure against Lightroom Classic 15.5 and the installed Lightroom 9.6; merged ROADMAP's parity estimate and honest assessment into this file) · **Target:** Adobe Lightroom Classic 15.5 (August 2026) and Lightroom 9.6 (desktop)
|
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (EOS R5 Mark II CR3 verified: RAW decoding 76% → 77%; headline numbers unchanged) · **Target:** Adobe Lightroom Classic 15.5 (August 2026) and Lightroom 9.6 (desktop)
|
||||||
|
|
||||||
The authoritative assessment of how close LightCraft is to Lightroom. The row-by-row checklist is
|
The authoritative assessment of how close LightCraft is to Lightroom. The row-by-row checklist is
|
||||||
[parity-checklist.md](parity-checklist.md); the ranked work list is [gaps.md](gaps.md); deep areas
|
[parity-checklist.md](parity-checklist.md); the ranked work list is [gaps.md](gaps.md); deep areas
|
||||||
@@ -67,7 +67,7 @@ from the checklist sections and the deep-dive documents.
|
|||||||
| Area | Weight | Breadth | Ready | Remaining | Notes |
|
| Area | Weight | Breadth | Ready | Remaining | Notes |
|
||||||
|---|---:|---:|---:|---:|---|
|
|---|---:|---:|---:|---:|---|
|
||||||
| Import and library (import, folders, albums, smart albums, keywords, metadata, search, faces) | 15% | 90% | 80% | 25–45 h | checklist A–E 83–92%; robust journal; 85k-photo libraries |
|
| Import and library (import, folders, albums, smart albums, keywords, metadata, search, faces) | 15% | 90% | 80% | 25–45 h | checklist A–E 83–92%; robust journal; 85k-photo libraries |
|
||||||
| RAW decoding and camera coverage | 15% | 81% | 76% | 120–220 h | [raw-parity.md](raw-parity.md), measured model by model: 84% of photographers' cameras decode (use-weighted), × 0.9 for per-body bugs; CR3 variants, compressed ORF, HE NEF |
|
| RAW decoding and camera coverage | 15% | 81% | 77% | 120–220 h | [raw-parity.md](raw-parity.md), measured model by model: 85% of photographers' cameras decode (use-weighted), × 0.9 for per-body bugs; CR3 variants, compressed ORF, HE NEF |
|
||||||
| Colour, camera profiles, render fidelity | 10% | 65% | 35% | 80–150 h | 4 bundled profiles vs Adobe's 1,500; per-file fits median ΔE ~5 vs the camera JPEG, ~10% far off; no fidelity suite ([raw-parity.md](raw-parity.md#colour)) |
|
| Colour, camera profiles, render fidelity | 10% | 65% | 35% | 80–150 h | 4 bundled profiles vs Adobe's 1,500; per-file fits median ΔE ~5 vs the camera JPEG, ~10% far off; no fidelity suite ([raw-parity.md](raw-parity.md#colour)) |
|
||||||
| Global develop adjustments (light, colour, curves, grading, effects, detail) | 15% | 93% | 70% | 30–60 h | checklist F 91.7%; character tuned by eye |
|
| Global develop adjustments (light, colour, curves, grading, effects, detail) | 15% | 93% | 70% | 30–60 h | checklist F 91.7%; character tuned by eye |
|
||||||
| Optics, lens profiles, crop and geometry | 6% | 80% | 50% | 40–80 h | no lens database; crop / Upright complete |
|
| Optics, lens profiles, crop and geometry | 6% | 80% | 50% | 40–80 h | no lens database; crop / Upright complete |
|
||||||
@@ -129,7 +129,7 @@ valued from the model-by-model measurement in [raw-parity.md](raw-parity.md):
|
|||||||
| Dimension | Weight | Ready |
|
| Dimension | Weight | Ready |
|
||||||
|---|---:|---:|
|
|---|---:|---:|
|
||||||
| Features: the other 11 areas, weighted depth from [Features](#features) | 45% | 60.9% |
|
| Features: the other 11 areas, weighted depth from [Features](#features) | 45% | 60.9% |
|
||||||
| RAW decoding and camera coverage | 9% | 76% (84% use-weighted × 0.9) |
|
| RAW decoding and camera coverage | 9% | 77% (85% use-weighted × 0.9) |
|
||||||
| Camera colour and default rendering | 6% | 35% |
|
| Camera colour and default rendering | 6% | 35% |
|
||||||
| UI/UX fidelity | 8% | 70% |
|
| UI/UX fidelity | 8% | 70% |
|
||||||
| File formats (non-raw) | 6% | 70% |
|
| File formats (non-raw) | 6% | 70% |
|
||||||
@@ -139,7 +139,7 @@ valued from the model-by-model measurement in [raw-parity.md](raw-parity.md):
|
|||||||
| Stability | 8% | 60% |
|
| Stability | 8% | 60% |
|
||||||
| Platforms | 4% | 60% |
|
| Platforms | 4% | 60% |
|
||||||
| Ecosystem / plug-ins | 2% | 15% |
|
| Ecosystem / plug-ins | 2% | 15% |
|
||||||
| **Weighted sum** | 100% | **60.6% ≈ 61%** (range 56–66%) |
|
| **Weighted sum** | 100% | **60.7% ≈ 61%** (range 56–66%) |
|
||||||
|
|
||||||
Mainstream comes out lower than full: its scope is the raw-develop core, where LightCraft is weakest
|
Mainstream comes out lower than full: its scope is the raw-develop core, where LightCraft is weakest
|
||||||
(camera colour, CR3 coverage), and its discounts are multiplicative, while the full sum is lifted by
|
(camera colour, CR3 coverage), and its discounts are multiplicative, while the full sum is lifted by
|
||||||
@@ -171,18 +171,18 @@ than the user's own.
|
|||||||
|---|---:|---:|
|
|---|---:|---:|
|
||||||
| Import and library | 18% | 80% |
|
| Import and library | 18% | 80% |
|
||||||
| Cull: views, compare, zoom, ratings | 12% | 70% |
|
| Cull: views, compare, zoom, ratings | 12% | 70% |
|
||||||
| Raw decoding for their camera | 27% | 84% (measured use-weighted share whose camera fully works, [raw-parity.md](raw-parity.md#by-use-estimated)) |
|
| Raw decoding for their camera | 27% | 85% (measured use-weighted share whose camera fully works, [raw-parity.md](raw-parity.md#by-use-estimated)) |
|
||||||
| Global develop adjustments | 15% | 70% |
|
| Global develop adjustments | 15% | 70% |
|
||||||
| Crop, geometry, lens corrections | 6% | 50% |
|
| Crop, geometry, lens corrections | 6% | 50% |
|
||||||
| Masking (manual, subject / sky; no generative) | 8% | 45% |
|
| Masking (manual, subject / sky; no generative) | 8% | 45% |
|
||||||
| Heal / remove (no generative), denoise | 5% | 40% |
|
| Heal / remove (no generative), denoise | 5% | 40% |
|
||||||
| Presets, copy / paste / sync | 5% | 85% |
|
| Presets, copy / paste / sync | 5% | 85% |
|
||||||
| Export | 4% | 75% |
|
| Export | 4% | 75% |
|
||||||
| **Weighted depth** | 100% | **71.8%** |
|
| **Weighted depth** | 100% | **72.1%** |
|
||||||
|
|
||||||
Colour fidelity is a written discount, **×0.85**: most raws start near the camera's own look (median
|
Colour fidelity is a written discount, **×0.85**: most raws start near the camera's own look (median
|
||||||
ΔE ~5), about 10% far off (ΔE ~18), none calibrated to Adobe Standard, so a working photographer
|
ΔE ~5), about 10% far off (ΔE ~18), none calibrated to Adobe Standard, so a working photographer
|
||||||
corrects colour by hand (33 open colour issues). 71.8% × 0.804 × 0.85 = **~49%** (range 44–54%).
|
corrects colour by hand (33 open colour issues). 72.1% × 0.804 × 0.85 = **~49%** (range 44–54%).
|
||||||
|
|
||||||
### Essentials user: ~64%
|
### Essentials user: ~64%
|
||||||
|
|
||||||
@@ -199,11 +199,11 @@ basic sliders, crop, apply a preset, undo, export JPEGs.
|
|||||||
| Crop and straighten | 10% | 80% |
|
| Crop and straighten | 10% | 80% |
|
||||||
| Presets and profiles | 8% | 80% |
|
| Presets and profiles | 8% | 80% |
|
||||||
| Undo and history | 5% | 90% |
|
| Undo and history | 5% | 90% |
|
||||||
| Their camera's raws: decode × default look | 10% | 63% (84% whose camera fully works × colour factor 0.75) |
|
| Their camera's raws: decode × default look | 10% | 64% (85% whose camera fully works × colour factor 0.75) |
|
||||||
| Export JPEG | 10% | 85% |
|
| Export JPEG | 10% | 85% |
|
||||||
| **Weighted depth** | 100% | **77.4%** |
|
| **Weighted depth** | 100% | **77.5%** |
|
||||||
|
|
||||||
77.4% × 0.830 = **~64%** (range 59–69%).
|
77.5% × 0.830 = **~64%** (range 59–69%).
|
||||||
|
|
||||||
### User evidence (GitHub issues, excluding the four maintainers)
|
### User evidence (GitHub issues, excluding the four maintainers)
|
||||||
|
|
||||||
@@ -297,6 +297,7 @@ P2 items 12–25 h; look tuning, performance, packaging, hardening 25–45 h.
|
|||||||
|
|
||||||
| Date | Change | Summary |
|
| Date | Change | Summary |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| 2026-10-11 | minor | EOS R5 Mark II CR3 verified (raw-parity.md): use-weighted share whose camera decodes 84% → 85%, RAW decoding 76% → 77%; full 60.6% → 60.7%, mainstream depth 71.8% → 72.1%, essentials depth 77.4% → 77.5%; the rounded numbers (~61%, ~49%, ~64%) are unchanged |
|
||||||
| 2026-10-10 | minor | RAW measured model by model (raw-parity.md): RAW decoding (76%) and colour (35%) are explicit rows of the full sum (59% → 61%); mainstream uses the use-weighted 84% plus a ×0.85 colour discount (51% → 49%); essentials uses 84% × colour 0.75 (63% → 64%); beta ~14 points |
|
| 2026-10-10 | minor | RAW measured model by model (raw-parity.md): RAW decoding (76%) and colour (35%) are explicit rows of the full sum (59% → 61%); mainstream uses the use-weighted 84% plus a ×0.85 colour discount (51% → 49%); essentials uses 84% × colour 0.75 (63% → 64%); beta ~14 points |
|
||||||
| 2026-10-10 | minor | Full number restored to an additive weighted sum over the dimensions (~59%; method aligned with the standard, no new evidence); hours to ~95% for each of the three audiences; beta distance ~16 points |
|
| 2026-10-10 | minor | Full number restored to an additive weighted sum over the dimensions (~59%; method aligned with the standard, no new evidence); hours to ~95% for each of the three audiences; beta distance ~16 points |
|
||||||
| 2026-10-10 | minor | Added mainstream practitioner (~51%) and essentials user (~63%) numbers; full ready re-derived from written weights × discounts (55% → 46%); user-issue evidence; beta hours 340–600 |
|
| 2026-10-10 | minor | Added mainstream practitioner (~51%) and essentials user (~63%) numbers; full ready re-derived from written weights × discounts (55% → 46%); user-issue evidence; beta hours 340–600 |
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# What's new in LightCraft
|
# What's new in LightCraft
|
||||||
|
|
||||||
|
## 2026-10-11
|
||||||
|
|
||||||
|
### Canon EOS R5 Mark II
|
||||||
|
- Canon EOS R5 Mark II C-RAW files that opened as "preview only" (more than half of them, depending on the
|
||||||
|
scene) now develop from their sensor data with every editing tool, like the camera's other raws. Photos
|
||||||
|
imported earlier switch over with Photo ▸ Reload from Disk.
|
||||||
|
|
||||||
## 2026-10-10
|
## 2026-10-10
|
||||||
|
|
||||||
### Activity stack
|
### Activity stack
|
||||||
|
|||||||
@@ -512,6 +512,27 @@ const RAW_SAMPLES: &[(&str, &str, &str)] = &[
|
|||||||
"https://raw.pixls.us/getfile.php/6587/nice/Canon%20-%20EOS%20R8%20-%203:2.CR3",
|
"https://raw.pixls.us/getfile.php/6587/nice/Canon%20-%20EOS%20R8%20-%203:2.CR3",
|
||||||
"df33cf394573645ce03dea1b2e9f0b5cc2b7734e9e3391ee7114151414cf2812",
|
"df33cf394573645ce03dea1b2e9f0b5cc2b7734e9e3391ee7114151414cf2812",
|
||||||
),
|
),
|
||||||
|
// EOS R5 Mark II, full frame and 1.6x crop mode: odd-height (2825- / 1787-row) Bayer planes.
|
||||||
|
(
|
||||||
|
"cr3-canon-r5m2-raw.cr3",
|
||||||
|
"https://raw.pixls.us/getfile.php/7881/nice/Canon%20-%20EOS%20R5%20Mark%20II%20-%20RAW%20%283:2%29.CR3",
|
||||||
|
"d6e6aa3b493ea8936dff0efb0cc17c87471437e7317bce37c8c82ba08b9cab7b",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"cr3-canon-r5m2-craw.cr3",
|
||||||
|
"https://raw.pixls.us/getfile.php/7882/nice/Canon%20-%20EOS%20R5%20Mark%20II%20-%20CRAW%20%283:2%29.CR3",
|
||||||
|
"b3c08a5c7a97299dfd58896a12b939e7b43ec78682761812524825e6e5d087be",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"cr3-canon-r5m2-apsc-raw.cr3",
|
||||||
|
"https://raw.pixls.us/getfile.php/7883/nice/Canon%20-%20EOS%20R5%20Mark%20II%20-%20RAW%20%283:2%29.CR3",
|
||||||
|
"9f88c0ff012924193b7f4497559d133dfe626766d600b5d67689156721739ead",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"cr3-canon-r5m2-apsc-craw.cr3",
|
||||||
|
"https://raw.pixls.us/getfile.php/7884/nice/Canon%20-%20EOS%20R5%20Mark%20II%20-%20CRAW%20%283:2%29.CR3",
|
||||||
|
"6a597497776a6abbfab8fcf12d0086ac7a3f8afea2879d61accf6bbf48d357d7",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"dng-adobe-canon-5d3-linear-lj92.dng",
|
"dng-adobe-canon-5d3-linear-lj92.dng",
|
||||||
"https://raw.pixls.us/getfile.php/1032/nice/Adobe%20DNG%20Converter%20-%20Canon%20EOS%205D%20Mark%20III%20-%20Lossless%20JPEG%20compression%2C%20rgb%20%283:2%29.DNG",
|
"https://raw.pixls.us/getfile.php/1032/nice/Adobe%20DNG%20Converter%20-%20Canon%20EOS%205D%20Mark%20III%20-%20Lossless%20JPEG%20compression%2C%20rgb%20%283:2%29.DNG",
|
||||||
|
|||||||
Reference in New Issue
Block a user