Merge PR #915
# Conflicts: # crates/engine/src/media.rs # crates/raw/src/vendor/crx.rs # crates/ui-egui/locales/de.json # docs/gaps.md # docs/parity-checklist.md # docs/raw-parity.md # docs/whats-new.md
This commit is contained in:
commit
7ecb0b0191
13
ROADMAP.md
13
ROADMAP.md
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
**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
|
||||
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 |
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
([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).
|
||||
|
|
@ -61,7 +61,7 @@ Hours are calibrated on this repo's PR history; see
|
|||
| Area | Ready | Breadth | Remaining |
|
||||
|---|---:|---:|---:|
|
||||
| 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 |
|
||||
| Global develop adjustments | 70% | 93% | 30–60 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
|
||||
|
||||
- 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 (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
|
||||
|
|
@ -157,6 +161,7 @@ Ranked toward beta; detail in [docs/roadmap.md](docs/roadmap.md), gaps in [docs/
|
|||
|
||||
| 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 | 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 |
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ impl SettingsHashes {
|
|||
}
|
||||
|
||||
/// Bump when the pipeline's output changes, to invalidate cached thumbnails.
|
||||
pub const RENDER_CACHE_VERSION: u64 = 55;
|
||||
pub const RENDER_CACHE_VERSION: u64 = 56;
|
||||
|
||||
/// 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];
|
||||
|
|
|
|||
|
|
@ -10,9 +10,12 @@
|
|||
//!
|
||||
//! 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
|
||||
//! (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.
|
||||
//! 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.
|
||||
|
||||
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_CRX_SAMPLES: usize = 200_000_000;
|
||||
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];
|
||||
|
||||
fn corrupt(reason: &str) -> RawError {
|
||||
|
|
@ -539,13 +544,17 @@ impl Bits<'_> {
|
|||
}
|
||||
|
||||
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;
|
||||
while zeros < 16 && self.take(1)? == 0 {
|
||||
while self.take(1)? == 0 {
|
||||
zeros += 1;
|
||||
if zeros > QP_ESCAPE_ZEROS {
|
||||
return Err(corrupt("QP Rice escape prefix exceeds 23 bits"));
|
||||
}
|
||||
}
|
||||
if zeros == 16 {
|
||||
// QP escape has no unary terminating 1 before the 16-bit literal.
|
||||
self.take(16)
|
||||
if zeros == QP_ESCAPE_ZEROS {
|
||||
self.take(8)
|
||||
} else if k <= 20 {
|
||||
Ok((zeros << k) | self.take(k)?)
|
||||
} else {
|
||||
|
|
@ -763,7 +772,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 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 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"))?;
|
||||
if !(131..=168).contains(&value) {
|
||||
return Err(RawError::Unsupported(format!("Canon CRX adaptive QP value {value}")));
|
||||
|
|
@ -995,9 +1005,16 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn qp_escape_and_average_precede_the_quantization_table() {
|
||||
let mut bits = Bits { src: &[0, 0, 1, 0x2c], at: 0 };
|
||||
assert_eq!(bits.qp_rice(0).unwrap(), 300);
|
||||
// 23 zeros, the terminating 1, then the symbol in 8 bits.
|
||||
let mut bits = Bits { src: &[0, 0, 1, 0x18], at: 0 };
|
||||
assert_eq!(bits.qp_rice(0).unwrap(), 24);
|
||||
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();
|
||||
assert_eq!(map.data, [150; 4]);
|
||||
assert!(qp_map(&[0, 0, 1, 0x2c, 0x95], 1, 4).is_err());
|
||||
|
|
@ -1020,6 +1037,16 @@ mod tests {
|
|||
assert!(matches!(qp_map(&[0, 0, 1, 0x52, 0x94], 1, 4), Err(RawError::Unsupported(_))));
|
||||
}
|
||||
|
||||
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]
|
||||
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
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ fn corpus() -> PathBuf {
|
|||
}
|
||||
|
||||
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 Ok(bytes) = std::fs::read(&path) else {
|
||||
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);
|
||||
raw.validate().unwrap();
|
||||
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());
|
||||
let RawData::U16(samples) = &raw.data else { panic!("{name}: integer sensor data expected") };
|
||||
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));
|
||||
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.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));
|
||||
}
|
||||
|
||||
/// 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]
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -2063,5 +2063,8 @@
|
|||
"Perceptual": "Perzeptiv",
|
||||
"Relative": "Relativ",
|
||||
"Simulate Paper & Ink": "Papier und Druckfarbe simulieren",
|
||||
"Content-Aware": "Inhaltsbasiert"
|
||||
"Content-Aware": "Inhaltsbasiert",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
40
docs/cr3.md
40
docs/cr3.md
|
|
@ -24,7 +24,7 @@ are the public prose descriptions and patents cited in
|
|||
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
|
||||
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
|
||||
decoded.
|
||||
|
||||
|
|
@ -55,6 +55,16 @@ control. The exact inputs and reference hashes are:
|
|||
| Canon R8 RAW, raw.pixls.us 6585 | `7d5c6dbb11ff7e6ee58715d90a20f5d801e8b103f4711ff6ea329ceafcef254c` | `63c1c6d8d1eb2312` |
|
||||
| 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
|
||||
binary; no decoder source was read or copied, and it is not shipped or linked.
|
||||
The release ZIP SHA-256 was
|
||||
|
|
@ -69,6 +79,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;
|
||||
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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Gaps: where LightCraft falls short of Lightroom
|
||||
|
||||
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (CR3 entry names the EOS R7 C-RAW fix and the refused CRX variants; CI and Windows / Linux entries note the 0.6.0 riscv64 build; camera colour: tone curve from black-and-white camera JPEGs; Compare and Reference get sharp zoom windows; gap 4 shrinks; gap 14: the HDR switch is read from crs XMP) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (CR3 entry names the EOS R7 C-RAW fix and the refused CRX variants; CI and Windows / Linux entries note the 0.6.0 riscv64 build; camera colour: tone curve from black-and-white camera JPEGs; Compare and Reference get sharp zoom windows; gap 4 shrinks; gap 14: the HDR switch is read from crs XMP; 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
|
||||
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 |
|
||||
|---:|---|---|---|---:|---|
|
||||
| 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 (a black-and-white camera JPEG gives its tone curve only, #577) | Δ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.rs` refuses vertical-tile C-RAW, partial-subband and other plane coding, multi-tile 0x200 and adaptive low-frequency gains, and those files fall back to the preview; CR3 sRAW / mRAW and HEIF CR3 too. EOS R7 C-RAW (odd-height QP map) decodes since a45c2b66 and R6 Mark II C-RAW is reported working on 0.6.0, but neither is verified yet (no corpus test or recorded check) | 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); R7 rule checked only on paired RAW / C-RAW captures ([cr3.md](cr3.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.rs` refuses vertical-tile C-RAW, partial-subband and other plane coding, multi-tile 0x200 and adaptive low-frequency gains, and those files fall back to the preview; CR3 sRAW / mRAW and HEIF CR3 too. Verified: M50 / R100 / R8 / R5 Mark II. EOS R7 C-RAW (odd-height QP map) decodes since a45c2b66 and R6 Mark II C-RAW is reported working on 0.6.0, but neither is verified yet (no corpus test or recorded check) | 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); R7 rule checked only on paired RAW / C-RAW captures ([cr3.md](cr3.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) |
|
||||
| 4 B | **Original-pixel detail at 100%** (LR-VIEW-ZOOM, P0): Detail, Before/After, Compare and Reference are sharp at 1:1–8:1 (zoom windows, #323). Mask overlays and soft proofing still render the whole frame at the drawn size instead of a window: sharp up to the GPU texture side, but a full-size render per edit at 1:1 | checklist row 🟡 | editing with a mask overlay or soft proof on at 1:1 is slow on large files, and blurry past the texture side | 4–8 | [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) |
|
||||
|
|
@ -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) |
|
||||
| 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); the linux-riscv64 release job added in 0.6.0 (#844) runs only `lightcraft-cli --version` under QEMU | 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) |
|
||||
| 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) |
|
||||
|
|
@ -77,6 +77,7 @@ Beta-blocking gaps (B) total **~230–430 h**; with the stability and platform w
|
|||
| 2026-10-11 | minor | Gap 4: Compare and Reference views get zoom windows per pane (1:1 was a 2,560 px render magnified); overlays and soft proofing remain, 8–15 h → 4–8 h |
|
||||
| 2026-10-10 | minor | Compressed ORF entry links the two Olympus patents that describe the method |
|
||||
| 2026-10-11 | minor | Gap 14: `crs:HDREditMode` is read from XMP (#663); the headroom limit and SDR rendition still aren't |
|
||||
| 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 | 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 |
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,6 @@
|
|||
# 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
|
||||
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 |
|
||||
|---|---:|---|
|
||||
| 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) |
|
||||
| Decoder path should handle it, **unverified** | **943** (65%) | measured from the format rules (632 of them DNG, mostly phones) |
|
||||
| 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** | **942** (65%) | measured from the format rules (632 of them DNG, mostly phones) |
|
||||
| **Preview-only** (embedded JPEG) | **233** (16%) | 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 |
|
||||
| **Share of photographers whose camera fully works** (decodes from sensor data), use-weighted | **~84%** | estimated: measured classes × written usage weights × per-format confidence |
|
||||
| …of which on a body we have verified | **~40%** | estimated, same weights |
|
||||
| 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 | **~85%** | estimated: measured classes × written usage weights × per-format confidence |
|
||||
| …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`) |
|
||||
| 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) |
|
||||
|
|
@ -42,7 +42,8 @@ committed table is stale.
|
|||
claims were not used.
|
||||
- **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
|
||||
`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
|
||||
#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
|
||||
|
|
@ -56,14 +57,14 @@ committed table is stale.
|
|||
~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,
|
||||
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)
|
||||
|
||||
| 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 |
|
||||
| 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) |
|
||||
| Apple | 113 | 1 | 112 | 0 | 0 | — (DNG / ProRAW) |
|
||||
| Panasonic | 104 | 93 | 11 | 0 | 0 | — |
|
||||
|
|
@ -80,13 +81,13 @@ committed table is stale.
|
|||
| DJI | 21 | 0 | 21 | 0 | 0 | — (DNG) |
|
||||
| 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 |
|
||||
| **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)
|
||||
|
||||
| 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 |
|
||||
| Nikon | 16% | 91% | 12% | decoders cover every NEF coding but HE; few bodies verified |
|
||||
| Fujifilm | 10% | 91% | 45% | |
|
||||
|
|
@ -97,7 +98,7 @@ committed table is stale.
|
|||
| Leica | 1% | 95% | 5% | |
|
||||
| DJI | 1% | 95% | 0% | |
|
||||
| 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
|
||||
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 | 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 | C-RAW 0x100 (horizontal tiles), 0x200 (single 14-bit tile, adaptive QP) | ✅ | same 3 bodies exact |
|
||||
| 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 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 | sRAW / mRAW | ⬜ | 4-plane Bayer only |
|
||||
| CR3 | HEIF / HDR PQ | ⬜ | HEVC tracks recognised, not decoded |
|
||||
|
|
@ -222,10 +223,10 @@ drone DNG users (~9% of photographers by the weights above); Adobe reaches nearl
|
|||
|
||||
| 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) |
|
||||
| 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
|
||||
from the format list alone. Measured model by model, decoding comes out about the same; the change is
|
||||
|
|
@ -241,7 +242,7 @@ works, from [raw/usage-weights.tsv](raw/usage-weights.tsv).
|
|||
| # | 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) |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
|
@ -265,5 +266,6 @@ Beyond decoding:
|
|||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | minor | Compressed ORF: pointer to the two Olympus patents that describe the method, as a clean-room starting point |
|
||||
| 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 | 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 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 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 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
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
|
@ -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 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 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-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)
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 3.
|
|
|
@ -1,6 +1,6 @@
|
|||
# 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
|
||||
[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 |
|
||||
|---|---:|---:|---:|---:|---|
|
||||
| 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)) |
|
||||
| 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 |
|
||||
|
|
@ -129,7 +129,7 @@ valued from the model-by-model measurement in [raw-parity.md](raw-parity.md):
|
|||
| Dimension | Weight | Ready |
|
||||
|---|---:|---:|
|
||||
| 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% |
|
||||
| UI/UX fidelity | 8% | 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% |
|
||||
| Platforms | 4% | 60% |
|
||||
| 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
|
||||
(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% |
|
||||
| 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% |
|
||||
| Crop, geometry, lens corrections | 6% | 50% |
|
||||
| Masking (manual, subject / sky; no generative) | 8% | 45% |
|
||||
| Heal / remove (no generative), denoise | 5% | 40% |
|
||||
| Presets, copy / paste / sync | 5% | 85% |
|
||||
| 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
|
||||
Δ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%
|
||||
|
||||
|
|
@ -199,11 +199,11 @@ basic sliders, crop, apply a preset, undo, export JPEGs.
|
|||
| Crop and straighten | 10% | 80% |
|
||||
| Presets and profiles | 8% | 80% |
|
||||
| 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% |
|
||||
| **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)
|
||||
|
||||
|
|
@ -297,6 +297,7 @@ P2 items 12–25 h; look tuning, performance, packaging, hardening 25–45 h.
|
|||
|
||||
| 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 | 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 |
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@
|
|||
library open now stays, and LightCraft says "This is a Lightroom catalog, not a LightCraft library" and offers
|
||||
**Import Lightroom Catalog…** with that catalog, or Cancel. `lightcraft-cli --library` refuses those folders too.
|
||||
|
||||
### 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
|
||||
|
||||
### Dialogs fit the window
|
||||
|
|
|
|||
|
|
@ -524,6 +524,27 @@ const RAW_SAMPLES: &[(&str, &str, &str)] = &[
|
|||
"https://raw.pixls.us/getfile.php/6587/nice/Canon%20-%20EOS%20R8%20-%203:2.CR3",
|
||||
"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",
|
||||
"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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue