mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-14 11:17:05 -04:00
Progress docs: target-app parity, RAW coverage vs Adobe, gaps, alpha gate, readiness by audience (#788)
Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, model-by-model RAW coverage against Adobe's camera list (docs/raw/), and format, hardware, UI and localization parity docs. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
b70ae1741e
commit
964d9338ba
27 files changed
+4837
-396
No files matched your search
@@ -5,12 +5,18 @@ LightCraft is a clean-room, open-source, pure-Rust photo library + non-destructi
|
||||
## Start every session here
|
||||
1. Read `plan/STATUS.md` (current milestone, next unchecked task, blockers).
|
||||
2. Read the task in `plan/execution-plan.md` §3, the relevant section of `plan/architecture.md`, and the README/docs of the crate you touch. Behaviour/visual reference: `plan/lightroom/` (incl. `10-observed-ui.md` + screenshots).
|
||||
3. **Know where we stand:** read [`ROADMAP.md`](ROADMAP.md) → *Where we stand* (honest assessment by dimension and
|
||||
by kind of user) and *Where we're going* (ordered priorities). The checklist counts features that *exist*; the real
|
||||
gaps are quality and coverage: camera colour calibration, CR3 / compressed raws, per-model verification, render
|
||||
fidelity against Lightroom, AI models, HDR / video / Classic modules. A ✅ row is not proof of parity — if you find a
|
||||
✅ feature that is wrong or incomplete, downgrade it to 🟡 with a note.
|
||||
4. **Pick work** from [`docs/parity.md`](docs/parity.md) → *Top gaps* (ordered by user impact; the tracker has one row per feature, menu item and shortcut). When you land a feature, update its row(s) and the gap list in the same commit, and the *Where we stand* / *Where we're going* sections of `ROADMAP.md` when a listed gap closes; `cargo xtask parity` (part of `ci`) checks that every `cmd:`/`ctl:` id and path the tracker cites still exists, and `cargo xtask parity --write` refreshes its summary.
|
||||
3. **Know where we stand:** read [`ROADMAP.md`](ROADMAP.md) (stage, headline numbers, every dimension) and, for
|
||||
method and evidence, [`docs/target-app-parity.md`](docs/target-app-parity.md). The checklist counts features that
|
||||
*exist*; the real gaps are quality and coverage: camera colour calibration, CR3 / compressed raws, per-model
|
||||
verification, render fidelity against Lightroom, AI models, HDR / video / Classic modules (raw detail:
|
||||
[`docs/raw-parity.md`](docs/raw-parity.md)). A ✅ row is not proof of parity — if you find a ✅ feature that is
|
||||
wrong or incomplete, downgrade it to 🟡 with a note.
|
||||
4. **Pick work** from [`docs/gaps.md`](docs/gaps.md) (ranked by user impact; `B` marks beta blockers). The row-by-row
|
||||
tracker is [`docs/parity-checklist.md`](docs/parity-checklist.md) (one row per feature, menu item and shortcut).
|
||||
When you land a feature, update its row(s) and the gap entry in the same commit, and the numbers in `ROADMAP.md` /
|
||||
`docs/target-app-parity.md` when a listed gap closes (bump each doc's *Last updated* line and revision history, per
|
||||
craftrules `standards/progress-docs.md`); `cargo xtask parity` (part of `ci`) checks that every `cmd:`/`ctl:` id and
|
||||
path the tracker cites still exists, and `cargo xtask parity --write` refreshes its summary.
|
||||
5. Follow the autonomous operation protocol (`plan/execution-plan.md` §7). Don't stop to ask unless §7 lists the decision as the user's.
|
||||
|
||||
`plan/` is gitignored (local-only).
|
||||
|
||||
@@ -5,12 +5,18 @@ LightCraft is a clean-room, open-source, pure-Rust photo library + non-destructi
|
||||
## Start every session here
|
||||
1. Read `plan/STATUS.md` (current milestone, next unchecked task, blockers).
|
||||
2. Read the task in `plan/execution-plan.md` §3, the relevant section of `plan/architecture.md`, and the README/docs of the crate you touch. Behaviour/visual reference: `plan/lightroom/` (incl. `10-observed-ui.md` + screenshots).
|
||||
3. **Know where we stand:** read [`ROADMAP.md`](ROADMAP.md) → *Where we stand* (honest assessment by dimension and
|
||||
by kind of user) and *Where we're going* (ordered priorities). The checklist counts features that *exist*; the real
|
||||
gaps are quality and coverage: camera colour calibration, CR3 / compressed raws, per-model verification, render
|
||||
fidelity against Lightroom, AI models, HDR / video / Classic modules. A ✅ row is not proof of parity — if you find a
|
||||
✅ feature that is wrong or incomplete, downgrade it to 🟡 with a note.
|
||||
4. **Pick work** from [`docs/parity.md`](docs/parity.md) → *Top gaps* (ordered by user impact; the tracker has one row per feature, menu item and shortcut). When you land a feature, update its row(s) and the gap list in the same commit, and the *Where we stand* / *Where we're going* sections of `ROADMAP.md` when a listed gap closes; `cargo xtask parity` (part of `ci`) checks that every `cmd:`/`ctl:` id and path the tracker cites still exists, and `cargo xtask parity --write` refreshes its summary.
|
||||
3. **Know where we stand:** read [`ROADMAP.md`](ROADMAP.md) (stage, headline numbers, every dimension) and, for
|
||||
method and evidence, [`docs/target-app-parity.md`](docs/target-app-parity.md). The checklist counts features that
|
||||
*exist*; the real gaps are quality and coverage: camera colour calibration, CR3 / compressed raws, per-model
|
||||
verification, render fidelity against Lightroom, AI models, HDR / video / Classic modules (raw detail:
|
||||
[`docs/raw-parity.md`](docs/raw-parity.md)). A ✅ row is not proof of parity — if you find a ✅ feature that is
|
||||
wrong or incomplete, downgrade it to 🟡 with a note.
|
||||
4. **Pick work** from [`docs/gaps.md`](docs/gaps.md) (ranked by user impact; `B` marks beta blockers). The row-by-row
|
||||
tracker is [`docs/parity-checklist.md`](docs/parity-checklist.md) (one row per feature, menu item and shortcut).
|
||||
When you land a feature, update its row(s) and the gap entry in the same commit, and the numbers in `ROADMAP.md` /
|
||||
`docs/target-app-parity.md` when a listed gap closes (bump each doc's *Last updated* line and revision history, per
|
||||
craftrules `standards/progress-docs.md`); `cargo xtask parity` (part of `ci`) checks that every `cmd:`/`ctl:` id and
|
||||
path the tracker cites still exists, and `cargo xtask parity --write` refreshes its summary.
|
||||
5. Follow the autonomous operation protocol (`plan/execution-plan.md` §7). Don't stop to ask unless §7 lists the decision as the user's.
|
||||
|
||||
`plan/` is gitignored (local-only).
|
||||
|
||||
@@ -297,18 +297,20 @@ lightcraft --control 7980 ~/Pictures/trip
|
||||
|
||||
## Feature status
|
||||
|
||||
LightCraft is young and moving fast. **Where we honestly stand** (details in the [roadmap](ROADMAP.md#where-we-stand)):
|
||||
LightCraft is young and moving fast: **alpha**. **Where we honestly stand** (details in the [roadmap](ROADMAP.md) and
|
||||
[docs/target-app-parity.md](docs/target-app-parity.md)):
|
||||
|
||||
- **By feature count we're at ~79%** of Lightroom (core features 98%), tracked row by row in
|
||||
[docs/parity.md](docs/parity.md).
|
||||
- **As a day-to-day Lightroom replacement we're nearer 60–70%.** It's great for JPEG/DNG and most Nikon / Sony /
|
||||
older-Canon raws on one machine.
|
||||
- **By feature count we're at ~81%** of Lightroom (core features 98%), tracked row by row in
|
||||
[docs/parity-checklist.md](docs/parity-checklist.md).
|
||||
- **As a day-to-day Lightroom replacement we're nearer 61% for the whole product, ~49% for a typical working photographer and ~64% for
|
||||
casual use.** It's great for JPEG/DNG and most Sony / Panasonic /
|
||||
Fujifilm / Nikon / older-Canon raws on one machine; see [docs/raw-parity.md](docs/raw-parity.md) for your camera.
|
||||
- **The biggest gaps:**
|
||||
- **camera colour calibration:** Sony, Nikon, Panasonic, Fujifilm and Canon CR3 raws have guarded estimates from their camera JPEGs, with built-in ILCE-7CR, ILCE-7M4, X-H2S and X-T4 profiles; measured calibration is missing, and other raws or rejected fits retain a neutral matrix;
|
||||
- **compressed Olympus raws and unsupported CR3 variants:** these use embedded JPEG previews when present. Fujifilm lossless/lossy compressed RAF now decodes sensor data; [verification and existing-library reload instructions](docs/raf-compression.md);
|
||||
- **AI masks and denoise:** subject and sky selection are classical heuristics;
|
||||
- **on-screen HDR display, video and the Classic Print / Book / Map modules.**
|
||||
- **What's next:** see [where we're going](ROADMAP.md#where-were-going).
|
||||
- **What's next:** see [the ranked gaps](docs/gaps.md) and [the roadmap](docs/roadmap.md).
|
||||
|
||||
| Area | Status |
|
||||
|---|---|
|
||||
@@ -318,10 +320,10 @@ LightCraft is young and moving fast. **Where we honestly stand** (details in the
|
||||
| Masking: brush, linear, radial, luminance/colour range, add/subtract/intersect | ✅ (AI subject/sky use classical heuristics for now) |
|
||||
| Crop, straighten tool + auto straighten, flip, rotate, aspect ratios, overlays | ✅ |
|
||||
| Profiles (Color, Neutral, Vivid, Landscape, Portrait, Monochrome: our own looks), presets, versions, history, copy/paste/sync settings | ✅ |
|
||||
| Camera colour: DNG files use their own matrices | ✅ DNG · 🟡 own Sony/Fujifilm profiles; measured calibration database missing |
|
||||
| Camera colour: DNG files use their own matrices | ✅ DNG · 🚧 own Sony/Fujifilm profiles; measured calibration database missing |
|
||||
| Native macOS menu bar (generated from the command registry), control channel + every widget addressable, headless UI snapshots | ✅ |
|
||||
| RAW: DNG, CR2, CR3 (lossless CRX Bayer and version 0x100/0x200 C-RAW), ARW, NEF (uncompressed + lossless/lossy compressed), Fujifilm RAF (uncompressed + lossless/lossy compressed, Bayer + X-Trans), Panasonic RW2 / Leica RWL / Panasonic RAW (every raw format, DMC-LX1 to DC-S1RM2), Pentax PEF, Olympus ORF (uncompressed), Samsung SRW (uncompressed); embedded previews for every format incl. CR3 | 🟡 · CR3, compressed ORF and compressed SRW decode ⬜ |
|
||||
| Detail: sharpening, luminance + colour noise reduction | ✅ · AI Denoise, Super Resolution ⬜ |
|
||||
| RAW: DNG, CR2, CR3 (lossless CRX Bayer and version 0x100/0x200 C-RAW), ARW, NEF (uncompressed + lossless/lossy compressed, incl. lossy after split), Fujifilm RAF (uncompressed + lossless/lossy compressed, Bayer + X-Trans), Panasonic RW2 / Leica RWL / Panasonic RAW (every raw format, DMC-LX1 to DC-S1RM2), Pentax PEF, Olympus ORF (uncompressed, 12.8 bpp), Samsung SRW (uncompressed); embedded previews for every format incl. CR3 | 🚧 · other CR3 variants, compressed ORF / SRW and Nikon HE NEF decode ⬜ ([raw parity](docs/raw-parity.md)) |
|
||||
| Detail: sharpening, luminance + colour noise reduction | ✅ · AI Denoise 🚧 (Bayer, user-installed weights), Super Resolution ⬜ |
|
||||
| Remove / Heal / Clone spots (auto source), Visualize Spots, Red Eye and Pet Eye (auto pupil detection, catchlight) | ✅ · content-aware fill, spot pin editing 🚧 |
|
||||
| Export: JPEG / PNG / TIFF / WebP / AVIF / DNG / original, sizing, file-size limit, output sharpening, naming templates, batch, metadata policy, text or image watermark | ✅ |
|
||||
| HDR: HDR editing with a headroom limit, SDR rendition, Visualize HDR; export as ISO 21496-1 gain map JPEG, PQ AVIF or 32-bit float TIFF | ✅ · HDR display ⬜ |
|
||||
@@ -332,7 +334,7 @@ LightCraft is young and moving fast. **Where we honestly stand** (details in the
|
||||
| Optics (distortion, vignetting, auto + manual CA, defringe, lens corrections embedded in DNG files and Panasonic / Leica RW2 / RWL distortion data), Geometry (transforms, Constrain Crop), Upright (Auto/Level/Vertical/Full/Guided) | ✅ · camera lens profiles (our own) ⬜ |
|
||||
| Photo Merge: HDR (auto-align, deghost), Panorama (spherical/cylindrical/perspective, boundary warp, auto crop), HDR Panorama → DNG | ✅ |
|
||||
| GPU pipeline (wgpu compute, CPU-exact within 1/255), CPU fallback on device limits / errors | ✅ · WebGPU in the browser 🚧 |
|
||||
| AI: segmentation masks, AI denoise, super resolution, faces; video | ⬜ (see [roadmap](ROADMAP.md#where-were-going)) |
|
||||
| AI: segmentation masks, AI denoise, super resolution, faces; video | 🚧 (see [gaps](docs/gaps.md)) |
|
||||
| Web build (same UI in the browser via WASM): persistent library in OPFS/IndexedDB, Web Worker rendering, export downloads | ✅ · WebGPU, Safari/Firefox testing 🚧 |
|
||||
|
||||
<sub>✅ works today · 🚧 in progress · ⬜ not started</sub>
|
||||
|
||||
+138
-214
@@ -1,242 +1,166 @@
|
||||
# LightCraft roadmap
|
||||
|
||||
Milestones toward full Adobe Lightroom parity (cloud Lightroom first, then every Lightroom Classic module), with wall-clock
|
||||
estimates for continuous (24/7) agent-driven development with 4–6 parallel agents. Estimates are calibrated on the sibling
|
||||
projects (DrawCraft reached its first four milestones in ≈ 4½ h) and are revised as milestones land.
|
||||
**Stage: alpha** · next: beta, ~14 points and ~340–600 h away
|
||||
|
||||
## Where we stand
|
||||
> **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
|
||||
|
||||
*Honest assessment, 2026-10-08. Agents: read this before picking work. The checklist in
|
||||
[`docs/parity.md`](docs/parity.md) counts features that **exist**; this section is about whether a photographer can
|
||||
**switch** from Lightroom. Update it when a gap below closes.*
|
||||
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
|
||||
[docs/target-app-parity.md](docs/target-app-parity.md).
|
||||
|
||||
**In one line:** the checklist says **79.7%** (P0 98.2%, P1 95.6%, P2 41.6%), but measured by whether a working
|
||||
photographer could replace Lightroom without noticing, we are at roughly **60–70%**. The remaining gap is mostly
|
||||
**quality of results and camera coverage**, not missing buttons.
|
||||
## Headline numbers
|
||||
|
||||
Caveat on the checklist: ✅ is set by whoever lands a feature, and nobody has systematically checked rows against
|
||||
Lightroom's behaviour or output. Bugs keep turning up in ✅ areas (CR2 colour-filter phase on some Canon models #85,
|
||||
duplicate Local entries #22, black GPU exports on an Intel iGPU #78).
|
||||
|
||||
### By dimension
|
||||
|
||||
| Dimension | Estimate | What's true today | Biggest gaps |
|
||||
|---|---:|---|---|
|
||||
| **Feature checklist** | 79.7% | P0 core and P1 nearly complete: import (Add / Copy / Move, templates, devices), library, grid/loupe/compare/survey, every Edit slider, curves, colour grading, masking tools, crop/Upright, heal/clone, presets/profiles, versions/history, sync, export, menus, shortcuts | P0: full-resolution zoom detail; P1: lens-profile database, content-aware fill (patch synthesis), video playback/trim |
|
||||
| **RAW coverage** (formats people shoot) | ~55% | DNG (all kinds), CR2, CR3 lossless Bayer and version 0x100/0x200 C-RAW (M50/R100/R8 pixel-exact corpus), ARW, NEF (uncompressed + Huffman lossless/lossy), RAF (uncompressed, lossless/lossy compressed Bayer and X-Trans), uncompressed ORF, uncompressed Samsung SRW (NX5 to NX1100, EX1, WB2000), RW2 / RWL / Panasonic RAW (every raw format, checked on 178 files from 118 Panasonic and Leica bodies), PEF; every container's embedded preview (incl. CR3) | **CR3** (every Canon since ~2018), compressed ORF, compressed Samsung SRW (NX1, NX30, NX300, NX500, NX2000, NX3000, NX3300, NX mini), Nikon lossy-after-split, Canon sRAW, HEIC/AVIF. NEFs labelled compressed but stored uncompressed (Z 6 packed 14-bit, D850 12-bit uncompressed). Nikon High Efficiency NEF (HE / HE★: Z 8, Z 9, Z 6III, Z f; JPEG XS-based, preview only, #193). Per-model verification is thin (~55 corpus files vs >1,000 models) |
|
||||
| **Colour & image quality** | ~55–65% | Pipeline is complete and fast; GPU path CPU-exact within 1/255 | **No measured camera calibration database**: ARW, NEF, RW2, RAF, CR3, CR2 and PEF have guarded camera-JPEG colour estimates, with bundled ILCE-7CR, ILCE-7M4, X-H2S and X-T4 profiles (docs/camera-preview-colour.md); 52 models whose JPEG fit is rejected start from matrices fitted to measured spectral sensitivities; other non-DNG raws and rejected estimates use a neutral matrix. Colour fidelity remains incomplete. No lens-profile database. No measured fidelity against Lightroom (tone, highlights, texture/clarity, NR, sharpening are tuned by eye) |
|
||||
| **AI & computational** | ~15–20% | Assisted culling (focus, bursts), auto tone, HDR/panorama merge; subject/sky/background masks as classical heuristics, or the photo's own segmentation mattes when it ships them (DNG semantic masks, e.g. iPhone ProRAW's sky matte); non-destructive Bayer RAW denoise with opt-in weights on pure-Rust CPU/GPU; **faces (MVP, [docs/faces.md](docs/faces.md))**: a pure-Rust detector (a 232 KB opt-in download), opt-in recognition models (one-click download or add a file; they run on the shared pure-Rust CPU interpreter; pinned SFace/AuraFace embeddings agree with an independent reference runtime on 40 public crops; one-thread medians 34–36 / 233–252 ms (AuraFace remains expensive)), a background scan that finds and embeds faces, name suggestions, a person's page with look-alike faces to confirm, an Unnamed faces section (look-alikes together, select a group and name it at once) | Real segmentation masks (subject, sky, people, objects, landscape, depth), denoise model policy / linear RGB / quality verification, super resolution, lens blur, generative remove, natural-language search; for faces: clusters with separators between groups, small faces in large photos (the detector looks at 640 px), thresholds calibrated on live faces, writing face regions back to XMP. **Blocked on a model strategy** (licensable weights or our own training; pure-Rust inference is feasible) |
|
||||
| **Workflow & library** | ~85% (single machine) | Robust catalog (journal + snapshots, background compaction, crash-tested), 85k-photo libraries stay responsive, Local browsing with automatic cleanup, XMP interop, keywords, smart albums, Move import | Opening an 85k library takes 1.7–4.7 s; no cloud sync (out of scope), no tablet companion (#74, roadmap), shared albums, publish services, tethering |
|
||||
| **Classic modules** | ~30% | Geotagging from GPX track logs, soft proofing (partial), slideshow (basic), paginated contact-sheet PDF export (A4/Letter, layout/captions, current edits, 150 dpi sRGB) | **Map view, Book, full Print module, Slideshow module, Web, publish services**: contact sheets work, custom print packages and printer colour management remain missing |
|
||||
| **HDR & video** | ~25% | HDR editing (headroom limit, SDR rendition, Visualize HDR); gain map JPEG, PQ AVIF and float TIFF export | On-screen HDR display, HLG, HDR settings from crs XMP; video play/trim/edit/export |
|
||||
| **Platform & robustness** | ~70% | macOS native; Windows/Linux builds; web via WASM; no-panic lints workspace-wide, `unsafe` confined to `crates/sysmem`; failed saves are reported; GPU errors fall back to CPU | Windows installer UI unverified on Windows (PR #79); GPU path proven only on Apple + user reports; English, Simplified/Traditional Chinese, Japanese, Brazilian Portuguese, Spanish, German, Russian and Ukrainian UI (see docs/localization.md); remaining technical errors; Traditional Chinese uses the Simplified Chinese font until craft-fonts has a TC face; accessibility partial; headless UI tests time out under machine load |
|
||||
|
||||
### By kind of user
|
||||
|
||||
| User | Readiness | What blocks them |
|
||||
| | Value | Kind |
|
||||
|---|---:|---|
|
||||
| JPEG / DNG shooter, single machine | ~85% | Fidelity polish, AI masks |
|
||||
| Nikon / Sony / Panasonic / older-Canon raw shooter | ~65% | Camera colour fidelity and coverage (ARW, NEF and RW2 preview estimates are only a starting point); embedded distortion is supported for Panasonic / Leica RW2 and the Sony ILCE-7RM4A (Bayer ARW, 24–105 / 200–600 tested); other lens metadata needs coverage and validation |
|
||||
| Fujifilm raw shooter | ~65% | Uncompressed and lossless/lossy compressed RAF decoded; camera colour calibration remains missing. Verified on 13 bodies, including 14/16-bit GFX; see `docs/raf-compression.md` |
|
||||
| Canon CR3 / Olympus compressed-raw shooter | ~45% | CR3 lossless Bayer and version 0x100/0x200 C-RAW develop from sensor data (M50, R100, R8 verified pixel for pixel); other CRX variants and compressed ORF open as embedded JPEG previews. Camera colour and broader model verification remain |
|
||||
| Lightroom Classic power user | ~45% | Print, Book, Map, publish, tethering |
|
||||
| Relies on AI (masks, denoise) | ~25% | Object / Describe masks via optional SAM 3 (download not yet hosted); Bayer AI denoise needs separately installed weights; X-Trans/linear RGB, model policy and quality parity remain open |
|
||||
| **Feature breadth** (checklist) | **81.1%** of 517 rows (P0 98.0%, P1 95.1%, P2 46.9%) | measured: [parity-checklist.md](docs/parity-checklist.md) recount |
|
||||
| **Feature breadth** (weighted by use) | **~77%** | estimated |
|
||||
| **Ready for real work** (full target) | **~61%** (56–66%) | estimated: weighted sum over the dimensions |
|
||||
| **Mainstream practitioner** | **~49%** (44–54%) | estimated |
|
||||
| **Essentials user** | **~64%** (59–69%) | estimated |
|
||||
| Remaining to **beta** | **~340–600 h** (Opus 5.5 agent hours, ~60% parallel) | estimated |
|
||||
| Remaining to **full parity** | **~1,000–1,800 h** (~70% parallel) | estimated |
|
||||
|
||||
## Where we're going
|
||||
Each audience with its own hours (Opus 5.5 agent wall-clock hours to ~95%):
|
||||
|
||||
Priorities, in order. Each points at tracker rows in [`docs/parity.md`](docs/parity.md) → *Top gaps*.
|
||||
| Audience | Ready | Opus 5.5 agent wall-clock hours to ~95% | Work that dominates |
|
||||
|---|---:|---:|---|
|
||||
| Full target (ready for real work) | **~61%** | **1,000–1,800 h** (~70% parallelizes) | raw colour, lens and camera data; AI models; Classic output modules; localization; plug-in ecosystem |
|
||||
| Mainstream practitioner | **~49%** | **450–840 h** (~60% parallelizes) | camera colour and render fidelity; CR3 / ORF / HE NEF; lens database; subject / sky masks; Lightroom XMP exchange; stability |
|
||||
| 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 |
|
||||
|
||||
1. **Camera colour calibration of our own** (LR-PROF-CAMERACOLOR, P0): fit each camera to its own embedded JPEG, use
|
||||
matrices the files carry themselves, then chart shots. Sony ARW, Nikon NEF, Panasonic RW2, Fujifilm RAF, Canon CR3/CR2,
|
||||
Pentax PEF, Samsung SRW and Olympus ORF have the file-local fit (matrix + tone curve from their own JPEG; CR2 and PEF
|
||||
since issue #310, not yet checked on the corpus); 52 models whose fit is rejected fall back to matrices fitted to
|
||||
measured spectral sensitivities (rawtoaces-data); then validate fidelity.
|
||||
2. **Raw formats, clean-room** (LR-IMP-FORMATS, P0): Remaining **unverified CR3 CRX** variants, compressed ORF, NEF
|
||||
lossy-after-split, sRAW. Decided 2026-10-05: write our own decoders from prose descriptions (never decoder source,
|
||||
no LGPL dependency); compressed NEF (#86) is the template.
|
||||
3. **Verified camera coverage** (LR-IMP-CAMERA-COVERAGE, P0): a CC0 sample per model in the corpus, each decoded and
|
||||
checked for plausible colour; fix per-model bugs (#85).
|
||||
4. **Render fidelity suite** (LR-BEHAV-RENDER-FIDELITY, P1): measure our output against Lightroom on the same CC0 raws
|
||||
(references stay in the local `plan/`), then tune against the numbers.
|
||||
5. **Lens profiles of our own** (LR-EDIT-OPTICS-PROFILE, P1): DNG, Panasonic / Leica RW2 and Sony ILCE-7RM4A Bayer ARW
|
||||
embedded distortion are supported; broaden validation and decode remaining vignetting / lateral CA metadata.
|
||||
6. **AI model strategy** (maintainer decision): which permissively licensed models (or our own training) for
|
||||
segmentation masks and denoise. Bayer denoise inference is implemented in pure Rust with an opt-in GPL model; release policy and independently licensed weights remain open. Unblocks M12 and Enhance. Face detection and recognition run on our own checked Rust engine. Object / Describe masks now
|
||||
run Meta's SAM 3 in pure Rust (optional, user-consented download under the non-OSI SAM License; CDN mirrors still
|
||||
to be set up, docs/ai-masks.md); Subject / Sky / People, Raw Details and Super Resolution are still open.
|
||||
7. **Then:** HDR (Q), the Classic output modules (expand contact-sheet PDF export into full Print, then Map view, Book, Slideshow), video (R), localisation
|
||||
and accessibility.
|
||||
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
|
||||
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
|
||||
(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).
|
||||
Hours are calibrated on this repo's PR history; see
|
||||
[target-app-parity.md](docs/target-app-parity.md#how-hours-are-calibrated).
|
||||
|
||||
Already closed in the week of 2026-10-03: compressed NEF (#10), Move import (#29), per-library smart-preview folder,
|
||||
Local roots / cleanup, grid and catalog performance at 85k photos (#35, #37), failed-save reporting, GPU export
|
||||
hardening (#78), copyright metadata (#51), GPX geotagging (#60), import tag help and folder templates (#31, #32).
|
||||
## By dimension
|
||||
|
||||
Library folders now have records of their own in the catalog (`Catalog.folder_records`, keyed by folder path; colour
|
||||
labels first). Photos still store full paths, so moving a whole disk or folder relinks each photo. If that becomes a
|
||||
problem (an "Update Folder Location" for a renamed or replaced drive, journal growth on large moves), the next step is
|
||||
the Classic model: photos point to a folder id (root + relative path), and the records keyed by path become those rows.
|
||||
| Dimension | Ready | Breadth | Remaining | Doc |
|
||||
|---|---:|---:|---:|---|
|
||||
| Features | ~61% | ~77% (checklist 81.1%) | 600–1,100 h | [target-app-parity](docs/target-app-parity.md#features) |
|
||||
| ↳ RAW cameras, colour, lens profiles | ~56% | 81% of 1,446 Adobe models decode, 16% verified | 255–480 h | [raw-parity](docs/raw-parity.md) |
|
||||
| UI/UX fidelity | ~70% | ~85% | 40–70 h | [ui-parity](docs/ui-parity.md) |
|
||||
| File formats (non-raw) | ~70% | ~85% | 30–55 h | [file-format-parity](docs/file-format-parity.md) |
|
||||
| Hardware | ~40% | ~50% | 40–80 h | [hardware-parity](docs/hardware-parity.md) |
|
||||
| Localization | ~52% of the 12 key languages | 7 of 12 present | 130–210 h (+145–255 h new scripts) | [localization-parity](docs/localization-parity.md) |
|
||||
| Performance | ~70% | ~80% | 30–50 h | [target-app-parity](docs/target-app-parity.md#by-dimension) |
|
||||
| Stability | ~60% | — | 30–60 h | [target-app-parity](docs/target-app-parity.md#by-dimension) |
|
||||
| Platforms | ~60% | macOS, Windows, Linux, FreeBSD, web | 25–45 h | [target-app-parity](docs/target-app-parity.md#by-dimension) |
|
||||
| Ecosystem / plug-ins | ~15% | ~25% | 40–80 h | [target-app-parity](docs/target-app-parity.md#by-dimension) |
|
||||
| AI features | ~20% | ~30% | 120–220 h (overlaps features) | [target-app-parity](docs/target-app-parity.md#ai) |
|
||||
|
||||
Image navigation now supports native pinch zoom and two-finger pan in Detail, Compare and Reference views.
|
||||
The whole-image preview still has a configurable size cap (2,560 px default), so 100% on larger photos does not
|
||||
yet guarantee original-pixel detail; visible-region rendering remains a gap (LR-VIEW-ZOOM).
|
||||
## Features
|
||||
|
||||
## Milestones
|
||||
|
||||
**Status legend:** ✅ done · 🚧 in progress · ⬜ not started
|
||||
|
||||
| # | Milestone | Scope (summary) | Estimate (h) | Status |
|
||||
|---|---|---|---|---|
|
||||
| M0 | Skeleton + visual shell | workspace, xtask CI + layering, geom/color/raster, develop model, pipeline v0, catalog v0, engine commands, Lightroom-look UI (grid, loupe, filmstrip, Edit panel), control channel, MCP, web build | 3–5 | ✅ |
|
||||
| M1 | Library core | import (JPEG/PNG/TIFF/WebP), EXIF/XMP, persistent catalog (op log + snapshots), albums, ratings/flags/labels, filter/search/sort, thumbnail cache, 100k-photo grid | 6–10 | ✅ (100k-photo grid scale test pending) |
|
||||
| M2 | Pipeline v1 (quality) | WB temp/tint, profiles, local tone mapping (highlights/shadows), curves, HSL, point colour, colour grading, texture/clarity/dehaze, vignette, grain, B&W, auto tone/WB, histogram, before/after | 10–15 | ✅ (look tuning vs our references ongoing) |
|
||||
| M3 | RAW I | TIFF/DNG (LJ92, deflate, tiles, opcodes), demosaic (AHD/PPG/bilinear), highlight recovery, DNG colour model, CR2, NEF, ARW, embedded previews | 10–15 | 🚧 (DNG, CR2, ARW, NEF uncompressed + Huffman lossless/lossy, embedded previews ✅; NEF lossy-after-split ⬜) |
|
||||
| M4 | Crop, geometry, optics | crop tool + overlays, straighten, Upright (auto/level/vertical/full/guided), manual transforms, CA, defringe, manual lens corrections | 6–10 | ✅ |
|
||||
| M5 | Performance | source pyramids, wgpu compute pipeline (CPU oracle), draft/full renders, prefetch, budgets (16 ms slider updates on 24 MP) | 10–15 | 🚧 (stage cache, source pyramid, wgpu pipeline, prefetch, memory budget ✅; colour NR at half resolution, GPU histogram ⬜) |
|
||||
| M6 | Masking | brush, linear/radial gradients, colour/luminance/depth range, add/subtract/intersect/invert, all local adjustments, masks panel | 8–12 | 🚧 (brush/linear/radial/colour/luminance range, add/subtract/intersect, masks panel ✅; depth range, AI masks ⬜) |
|
||||
| M7 | Detail | sharpening + masking preview, luminance/colour NR, Denoise, Raw Details, Super Resolution | 6–10 | 🚧 (sharpening, luminance/colour NR ✅; AI Denoise 🟡 (Bayer, optional weights; policy/fidelity open); Raw Details, Super Resolution ⬜) |
|
||||
| M8 | Heal / Remove | content-aware remove (PatchMatch), heal, clone, brush spots, visualize spots, red/pet eye | 6–10 | 🚧 (heal, clone, auto source, visualize spots, red/pet eye ✅; PatchMatch remove ⬜) |
|
||||
| M9 | Presets, profiles, versions, sync | preset browser + amount, create/import presets, profile browser, versions, history, copy/paste/sync settings | 5–8 | ✅ |
|
||||
| M10 | Export & share | export dialog (JPEG/PNG/TIFF/DNG/AVIF/JXL/original), sizing, sharpening, metadata, watermark, naming, batch jobs, XMP sidecars, HDR export | 6–10 | 🚧 (all formats incl. DNG/original, sizing, presets, background jobs, HDR gain map JPEG / PQ AVIF ✅; JXL encode ⬜) |
|
||||
| M11 | RAW II | CR3, RAF (X-Trans), ORF, RW2, PEF, SRW, 3FR, IIQ + long tail; camera calibration DB; HEIC/AVIF/JXL import | 20–35 | 🚧 (CR3 lossless CRX and C-RAW, RAF uncompressed and lossless/lossy compressed, RW2 (every raw format), PEF, ORF uncompressed ✅; **camera colour calibration** 🚧 (guarded ARW, NEF, RW2 and RAF preview fitting; measured database still missing), CR3, compressed ORF ⬜) |
|
||||
| M12 | AI & smart features | subject/sky/background/people/object masks, semantic search, faces/People (permissively licensed models, pure-Rust inference) | 20–40 | ⬜ |
|
||||
| M13 | Merge | HDR merge (deghost), panorama (projections, boundary warp, fill edges), HDR panorama | 10–15 | ✅ |
|
||||
| M14 | Video | import/playback/trim via FilmCraft crates, global edits + presets on video, video export | 6–10 | ⬜ |
|
||||
| M15 | Classic modules | Map, Book, Slideshow, Print, Web; smart collections, stacks, virtual copies, publish services, tethering | 25–40 | 🚧 (smart albums, stacks, virtual copies, compare/survey ✅; Map/Book/Slideshow/Print/Web ⬜) |
|
||||
| M16 | 1.0 polish | preferences, shortcut editor, accessibility, localization, packaging (dmg/msi/AppImage/web), hardening | 10–20 | 🚧 (settings, keyboard shortcuts sheet, packaging basics ✅; English/Chinese (Simplified, Traditional)/Japanese/Brazilian Portuguese/Spanish/German/Russian/Ukrainian localisation 🟡; accessibility and further locales ⬜) |
|
||||
|
||||
## Parity estimate (feature count updated 2026-10-08; effort estimate from 2026-10-02)
|
||||
|
||||
**By feature count** — from `docs/parity.md` (one row per Lightroom feature, menu item and shortcut; `cargo xtask
|
||||
parity` prints this line on every run, so it stays current):
|
||||
|
||||
| Scope | Weighted completion | Rows | 2026-10-02 |
|
||||
| Area | Ready | Breadth | Remaining |
|
||||
|---|---:|---:|---:|
|
||||
| P0 (core) | **98.2%** | 200 | 98.7% |
|
||||
| P1 (important parity) | **95.6%** | 149 | 94.4% |
|
||||
| P2 (later / AI / niche, incl. Classic modules) | **41.6%** | 160 | 29.4% |
|
||||
| **All in-scope rows** | **79.7%** | 509 | 75.6% |
|
||||
| Import and library | 80% | 90% | 25–45 h |
|
||||
| RAW decoding and camera coverage | 76% | 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 |
|
||||
| Masking | 45% | 67% | 60–110 h |
|
||||
| Remove, heal, Enhance | 30% | 45% | 70–130 h |
|
||||
| Presets, profiles, versions, sync | 85% | 95% | 8–15 h |
|
||||
| Export | 75% | 89% | 15–30 h |
|
||||
| Merge and HDR | 60% | 85% | 20–35 h |
|
||||
| Views, compare, zoom, culling | 70% | 90% | 15–30 h |
|
||||
| Classic output modules (Map, Book, Slideshow, Print, publish, tethering) | 10% | 15% | 90–150 h |
|
||||
| Video | 0% | 0% | 25–45 h |
|
||||
|
||||
The 2026-10-05 count includes three new 🟡 rows that make quality gaps visible (camera colour calibration, verified
|
||||
camera coverage, render fidelity), which is why P0 dipped slightly.
|
||||
Weights and evidence: [target-app-parity.md](docs/target-app-parity.md#features).
|
||||
|
||||
✅ counts 1, 🟡 ½, ⬜ 0; out-of-scope rows (cloud sharing, Adobe accounts…) are left out.
|
||||
## Languages
|
||||
|
||||
**By remaining effort** — rows are not equal: a shortcut and the whole Book module are one row each, and what is
|
||||
left is the heavy part (AI, video, Classic output modules, undocumented raw codecs). Remaining work in **Opus agent-hours**
|
||||
(one agent working continuously; calibrated on this project — a single lead agent closed ≈ 45 tracker rows of
|
||||
UI/feature work in ≈ 5 h on 2026-10-01, and ≈ 60 more (preset import incl. `.lrtemplate` / DNG / zip and masks, smart-album
|
||||
rule editor, auto sync, keyword and label sets, import options and DNG conversion, smart previews, external-editor round
|
||||
trip, slideshow, auto import…) in ≈ 12 h on 2026-10-02; four to six parallel agents built M0–M13 in ≈ 25 active hours):
|
||||
Measured from `crates/ui-egui/locales` (share of 2,304 catalog messages translated); none is `full`
|
||||
while lower-layer errors stay English. Detail: [localization-parity.md](docs/localization-parity.md).
|
||||
|
||||
| Work package | Tracker rows | Agent-hours | Risk |
|
||||
| Language | Code | Translated | Status |
|
||||
|---|---|---:|---|
|
||||
| Remaining P0/P1 UI and library features (folder rename/move, keyword painter, people view…) | ≈ 8 | 5–10 | low |
|
||||
| Raw codecs: CR3 (CRX), compressed ORF, NEF lossy-after-split, HEIC/AVIF decode | LR-IMP-FORMATS | 40–80 | **high** — clean-room black-box analysis, no permissive specs |
|
||||
| Lens-profile database of our own (calibration targets, fitting, data) | LR-EDIT-OPTICS-PROFILE | 15–30 | data collection |
|
||||
| Video: playback, trim, edits, export (pure-Rust decode, ideally shared with FilmCraft) | R. Video | 20–40 | medium |
|
||||
| AI: subject / sky / background / people / object masks, object-aware remove, AI denoise, super resolution, lens blur, people & faces, natural-language search, culling | ≈ 30 | 80–150 | **high** — permissively licensed weights, pure-Rust inference, maybe training |
|
||||
| HDR editing, display, visualisation and export | Q. HDR, LR-EXP-HDR | 15–25 | medium |
|
||||
| Classic modules: Map, Book, Slideshow module, Print, publish services, tethering, soft proofing | ≈ 50 | 60–100 | medium (large, well-understood) |
|
||||
| Smaller P2 items: Enhance dialog, export to Photos, help / what's new, accessibility, localisation, sidecar variants | ≈ 15 | 12–25 | low |
|
||||
| Look tuning, performance budgets (colour NR at half resolution on CPU + GPU, 100k-photo library), packaging, hardening | — | 25–45 | medium |
|
||||
| **Total remaining** | | **≈ 270–505** | |
|
||||
| English | en | 100% | full (source) |
|
||||
| Simplified Chinese | zh-hans | 87% | partial |
|
||||
| Spanish | es | 86% | partial |
|
||||
| Hindi | hi | 0% | none (no Devanagari shaping) |
|
||||
| Arabic | ar | 0% | none (no RTL / shaping) |
|
||||
| French | fr | 88% | partial |
|
||||
| Portuguese (Brazil) | pt-br | 85% | partial |
|
||||
| Indonesian | id | 0% | none |
|
||||
| Japanese | ja | 87% | partial |
|
||||
| German | de | 91% | partial |
|
||||
| Korean | ko | 0% | none (no Hangul face) |
|
||||
| Vietnamese | vi | 0% | none |
|
||||
|
||||
Spent so far ≈ 105–145 agent-hours, so **by effort the project is ≈ 20–35% of the way to complete Lightroom + Classic
|
||||
parity**, and ≈ 45–60% of the way for cloud-Lightroom parity without AI and the Classic modules (remaining ≈ 130–255 h,
|
||||
most of it the raw codecs, lens data, video and HDR).
|
||||
Also shipped: Traditional Chinese (87%), Russian (74%), Ukrainian (99%).
|
||||
|
||||
**Wall clock:** ≈ 270–505 h for one agent working alone; with 4–6 parallel agents (≈ 70% parallel efficiency, merges and
|
||||
CI under load cost the rest) **≈ 65–125 h of continuous work**. The AI package and the raw codecs carry most of the
|
||||
uncertainty: they can finish faster if suitable permissive models / documentation turn up, or stall on licensing.
|
||||
## Upcoming
|
||||
|
||||
## Totals
|
||||
Ranked toward beta; detail in [docs/roadmap.md](docs/roadmap.md), gaps in [docs/gaps.md](docs/gaps.md).
|
||||
|
||||
Remaining from 2026-10-02 evening (see *Parity estimate* above for the breakdown):
|
||||
1. Camera colour of our own: measured calibration for the popular models (50–90 h)
|
||||
2. CR3 for every Canon body (25–45 h)
|
||||
3. Render-fidelity suite against Lightroom, then tuning (30–60 h)
|
||||
4. Full-resolution zoom (8–15 h)
|
||||
5. AI masks: Subject / Sky / People (40–70 h + model decision)
|
||||
6. Compressed ORF and HE NEF (28–55 h)
|
||||
7. Lens profile database of our own (40–80 h)
|
||||
8. Tests in CI on macOS, Windows and Linux (6–12 h)
|
||||
9. Per-model raw verification (20–35 h)
|
||||
|
||||
| Target | Remaining agent-hours | Wall clock, 4–6 parallel agents |
|
||||
|---|---:|---:|
|
||||
| Cloud-Lightroom parity without AI or Classic modules | ≈ 130–255 h | ≈ 35–65 h |
|
||||
| Full parity incl. AI, video and the Classic modules | ≈ 270–505 h | ≈ 65–125 h |
|
||||
## Progress log
|
||||
|
||||
The milestone estimates in the table above were made before work started and are kept for calibration (M0–M13 took
|
||||
≈ 25 active hours with parallel agents against an estimate of ≈ 110–170 h for those milestones).
|
||||
- 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
|
||||
verified body). Full ~61%, mainstream ~49%, essentials ~64%; beta ~14 points away.
|
||||
- 2026-10-10 (final): full ready is a weighted sum over the dimensions (~59%; method aligned with
|
||||
the standard); mainstream practitioner ~51% (450–840 h), essentials user ~63% (160–300 h);
|
||||
alpha gate passes.
|
||||
- 2026-10-10: full re-measure for the progress-docs standard: stage alpha, ready ~55%, checklist
|
||||
81.1%; new docs (target-app-parity, gaps, roadmap, architecture, raw / file-format / hardware / UI
|
||||
/ localization parity); `docs/parity.md` renamed `docs/parity-checklist.md`. Landed today: Nikon
|
||||
lossy-after-split NEF (#633), ORF 12.8 bpp (#651), HDR gain map JPEG / PQ AVIF / float TIFF export
|
||||
(#646), Lightroom-like Auto (#628), activity stack.
|
||||
- 2026-10-09: Sony ILCE-7CR camera colour: bundled profile from 125 photos; on 26 withheld photos mean
|
||||
ΔE vs the camera JPEG 4.07 → 3.29. HEIC in release builds (#609), Samsung uncompressed SRW,
|
||||
contact-sheet PDF export, Ukrainian and French UI, release v0.5.0.
|
||||
- 2026-10-08: independent Rust CR3 lossless and version 0x100/0x200 C-RAW decoding, six exact
|
||||
full-sensor regressions on M50 / R100 / R8; guarded CR3 camera-JPEG colour fitting
|
||||
([cr3.md](docs/cr3.md)).
|
||||
- 2026-10-08: Fujifilm lossless / lossy compressed RAF: pure-Rust striped decoder, full sensor arrays
|
||||
verified on 17 CC0 and 7 supplied files (13 bodies). Fujifilm camera colour: bundled X-H2S / X-T4
|
||||
profiles from 201 / 545 photos; on 150 withheld files mean ΔE X-H2S 1.70 → 1.62, X-T4 2.43 → 2.34.
|
||||
AI RAW denoise (#384), Lightroom catalog import, German, Spanish and Russian UI.
|
||||
- 2026-10-07: Panasonic RW2 / Leica RWL / Panasonic RAW decode in every raw format, established on
|
||||
178 CC0 files from 118 bodies; RW2 file-local camera look (140 of 174 files). Faces: recognition in
|
||||
pure Rust and People view.
|
||||
- 2026-10-03 – 10-05: community PRs (#42–#51, #60) and 25+ issues: compressed NEF, Move import,
|
||||
folder templates, Local roots and cleanup, 85k-photo grid and catalog performance, background
|
||||
compaction, failed-save errors, GPU export hardening. Added the honest *Where we stand* assessment
|
||||
and tracker rows for camera colour, camera coverage and render fidelity.
|
||||
- 2026-10-02: parity estimate added (`cargo xtask parity` prints weighted completion); milestones
|
||||
refreshed.
|
||||
- 2026-10-01: RAW II formats: RAF (uncompressed Bayer + X-Trans), RW2 (packed), PEF (incl. Huffman),
|
||||
ORF (uncompressed); embedded previews for every container incl. CR3; raw corpus test with 37 CC0
|
||||
samples.
|
||||
- 2026-09-30 (later): app running with the full Lightroom-style UI; pipeline v0; DNG / CR2 / ARW;
|
||||
README showcase. ≈ 8 h elapsed.
|
||||
- 2026-09-30: roadmap created; M0 in progress; research docs (Lightroom reference, Rust imaging
|
||||
ecosystem) complete.
|
||||
|
||||
## Risks that coding hours alone don't retire
|
||||
## Revision history
|
||||
|
||||
- **AI features** (subject/sky/people masks, generative remove) need model weights with licences we can ship; classical
|
||||
fallbacks first. No permissively licensed sky-segmentation or raw-denoise model was found — we may need to train our own.
|
||||
- **Camera colour and lens data** is a data problem: we never use Adobe's matrices, DCPs or LCPs. DNG-embedded data first,
|
||||
then our own calibration; long-tail camera/lens coverage grows over time.
|
||||
- **Raw-format sources:** decided 2026-10-05: decoders are written from *prose* format descriptions (even ones
|
||||
published alongside GPL code); decoder source is never read. Still open: freedom-to-operate review for local
|
||||
Laplacian filters, PatchMatch and HEVC (HEIC).
|
||||
- **Look parity** with Adobe's default rendering is tuned by eye today; the planned fidelity suite (LR-BEHAV-RENDER-FIDELITY)
|
||||
turns it into measured comparisons against local-only Lightroom references. Retuning changes existing edits, so it
|
||||
ships as a new process version (`docs/process-versions.md`): photos keep their look until they are updated.
|
||||
|
||||
## Raw format coverage and known gaps
|
||||
|
||||
Sony ILCE-7M4 downsized lossless ARW (subsampled YCbCr 4:2:0 / 4:2:2 tiles) now decodes to linear RGB;
|
||||
private 3:2 & 4:3 examples verified through native rendering & full-resolution 16-bit export.
|
||||
|
||||
CR3 lossless Bayer and version 0x100/0x200 C-RAW sensor decoding is verified pixel-exactly on Canon M50, R100 and R8; any other CR3, or one that fails to decode, opens from its embedded JPEG as before. See [`docs/cr3.md`](docs/cr3.md) for coding limits, reference provenance and colour limitations.
|
||||
|
||||
Decoded (CC0 corpus from raw.pixls.us, `cargo xtask corpus --download`, `crates/raw/tests/corpus.rs`): DNG (uncompressed,
|
||||
LJ92, lossy JPEG / Smart Previews, Deflate, float, linear, DNG 1.7 JPEG XL tiles: lossless ones bit-exact on synthetic files,
|
||||
lossy ones unclipped in the declared linear primaries, checked on one real file), CR2, ARW (uncompressed, ARW2, LJ92; as-shot white balance and black level of pre-2017 bodies from the encrypted
|
||||
`SR2SubIFD`, decrypted with a keystream recovered by black-box analysis, `crates/raw/src/vendor/sr2.rs`, `crates/raw/src/vendor/arw.rs`), NEF/NRW uncompressed and Huffman-compressed (lossless, lossy type 1/2, 12/14-bit), RAF uncompressed and lossless/lossy compressed (Bayer and
|
||||
X-Trans, 14/16-bit real-file verification), RW2 / Leica RWL / Panasonic RAW in every raw format (compressed formats 4 and 6, the prefix-coded strips of format 8,
|
||||
packed formats 2, 5 and 7, the 16-bit words of the 2005–2007 bodies; all recovered by black-box analysis of 178 CC0 files from
|
||||
118 bodies, `crates/raw/src/vendor/rw2.rs`), PEF (uncompressed and Huffman), ORF uncompressed (16-bit and 12-bit packed). Supported containers yield their embedded JPEG preview when present (including CR3). The engine uses it for RAW variants it cannot decode yet; HEVC-only CR3 previews are not decoded.
|
||||
|
||||
Not decoded yet — preview only (no permissively licensed description; black-box analysis incomplete):
|
||||
- **Olympus compressed ORF**, **Canon CR3 unverified CRX variants** (M11.1), **Canon sRAW/mRAW**.
|
||||
|
||||
**Camera colour matrices:** ARW, NEF, RW2, RAF, CR3, CR2, PEF, Samsung SRW and Olympus ORF files can use guarded, separate chromaticity and tone estimates from their own embedded JPEG (see `docs/camera-preview-colour.md`); this is a per-file camera-look estimate with relative WB, not measured calibration or absolute-Kelvin WB. 52 models whose fit is rejected (or that have no usable JPEG) start from matrices fitted to their measured spectral sensitivities instead (rawtoaces-data, Apache-2.0; `crates/raw/src/spectral.rs`). Other non-DNG raws and rejected fits use the documented neutral fallback (camera RGB ≈ linear sRGB, flagged
|
||||
`matrix_is_fallback`) with the file's as-shot white-balance multipliers. Clean sources to evaluate next: manufacturer
|
||||
matrices stored in the files themselves (Olympus ImageProcessing `ColorMatrix`, Pentax equivalents; Panasonic RW2 files carry none) and our
|
||||
own chart-based calibration (M11.4). Adobe matrices are never used.
|
||||
|
||||
## Lightroom Classic catalog migration
|
||||
|
||||
File → Import Lightroom Catalog… reads `.lrcat` plus committed WAL pages directly through a pure-Rust
|
||||
SQLite reader. Originals stay in place; ratings, flags, labels, XMP metadata, hierarchical keywords,
|
||||
collections/sets, virtual copies and supported develop settings migrate into LightCraft. Existing edits
|
||||
are preserved by default, reimport identities are persistent, and source settings/history/snapshots are
|
||||
archived before catalog mutation. Missing originals remain available for relinking.
|
||||
|
||||
Rendering is approximate: unsupported Adobe profiles/AI/process settings are reported and archived;
|
||||
history/snapshots remain source data, and smart collections import current membership. The Lightroom
|
||||
database is read-only; LightCraft owns subsequent edits. See `docs/lightroom-catalog-import.md`.
|
||||
|
||||
## Log
|
||||
- 2026-09-30: roadmap created; M0 in progress; research docs (Lightroom reference, Rust imaging ecosystem) complete.
|
||||
- 2026-09-30 (later): app running with the full Lightroom-style UI; pipeline v0; DNG/CR2/ARW; README showcase. ≈ 8 h elapsed.
|
||||
- 2026-10-02: parity estimate added (xtask parity prints weighted completion); milestone statuses refreshed.
|
||||
- 2026-10-08: Fujifilm camera colour: guarded JPEG matching and relative WB, plus bundled X-H2S/X-T4 profiles from 201/545 photos. On 150 withheld files the pooled profiles improve mean ΔE slightly over per-file fitting (X-H2S 1.70 → 1.62, X-T4 2.43 → 2.34); dark X-H2S samples 8.74 → 2.25. Measured calibration remains open.
|
||||
- 2026-10-08: Fujifilm lossless/lossy compressed RAF: pure-Rust striped decoder; full sensor arrays verified against a black-box reference on 17 CC0 files and 7 supplied X-H2S / X-T4 files (13 camera bodies, 14/16-bit Bayer and X-Trans). Camera colour calibration remains a separate gap.
|
||||
- 2026-10-01: RAW II formats: RAF (uncompressed Bayer + X-Trans), RW2 (packed), PEF (incl. Huffman), ORF (uncompressed); embedded previews for every container incl. CR3; raw corpus test with 37 CC0 samples.
|
||||
- 2026-10-03 – 10-05: community PRs (#42–#51, #60) and 25+ issues landed: compressed NEF, Move import, folder templates,
|
||||
Local roots and cleanup, 85k-photo grid and catalog performance, background compaction, failed-save errors, GPU
|
||||
export hardening, clippy 1.99. Added the honest *Where we stand* assessment and *Where we're going* priorities; added
|
||||
tracker rows for camera colour, camera coverage and render fidelity.
|
||||
- 2026-10-07: Panasonic RW2 / Leica RWL / Panasonic RAW decode in every raw format (compressed 4/6/8, packed 2/5/7,
|
||||
16-bit words), black levels, in-camera aspect crops and mapped-out defects established on 178 CC0 files from 118
|
||||
bodies; RW2 gets the file-local camera look (accepted on 140 of 174 files with a preview).
|
||||
- 2026-10-08: independent Rust CR3 lossless and version 0x100/0x200 C-RAW decoding, six exact full-sensor regressions on M50/R100/R8; any CR3 decode error falls back to the embedded JPEG; guarded CR3 camera-JPEG colour fitting with independent framing validation (`docs/cr3.md`). Unverified CRX variants and broader model verification remain.
|
||||
- 2026-10-09: Sony ILCE-7CR camera colour: bundled profile from 125 photos. On 26 withheld photos mean ΔE vs the camera JPEG 4.07 → 3.29; all 131 photos accepted, where 8 fell back to the neutral matrix without it. Measured calibration remains open.
|
||||
|
||||
## Chinese and Japanese interfaces, and text watermarks
|
||||
|
||||
English, Simplified Chinese, Traditional Chinese (Taiwan) and Japanese interface languages are persisted in UI state, and the
|
||||
language table (`crates/ui-egui/src/i18n.rs`) drives the menus, settings and fonts, so another
|
||||
language is a table entry plus two catalogs (docs/localization.md). Core menus and panels are
|
||||
translated; untranslated text retains English. Ukrainian covers all existing catalog keys, command/control/rule labels
|
||||
and format messages, with count-neutral labels and numeric dates; technical errors from lower layers remain English.
|
||||
CJK glyphs (Chinese: Noto Sans CJK SC; Japanese UI:
|
||||
BIZ UDPGothic; watermarks: BIZ UDMincho) come from storytold/craft-fonts, embedded by builds made
|
||||
with the optional `CRAFT_FONTS_DIR` input (all releases), so no system fonts are needed. Text watermarks now accept
|
||||
`vertical: true` in export JSON/presets and expose an orientation selector. Japanese
|
||||
characters stay upright in top-to-bottom columns, with newlines starting columns to the
|
||||
left. This is basic lettering, without tate-chu-yoko, ruby, kinsoku, or general vertical
|
||||
OpenType shaping. The same coverage renderer serves 8/16/32-bit exports.
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 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 |
|
||||
| 2026-10-10 | minor | Alpha gate added (core-workflow check): passes, stays alpha |
|
||||
| 2026-10-10 | major | Restructured to the progress-docs standard; re-measured; *Where we stand*, *Parity estimate* and *Totals* moved to docs/target-app-parity.md, milestones and risks to docs/roadmap.md, raw coverage to docs/raw-parity.md, catalog migration to docs/file-format-parity.md, CJK notes to docs/localization-parity.md |
|
||||
| 2026-10-08 | minor | *Where we stand* by dimension and by kind of user |
|
||||
| 2026-10-02 | major | Parity estimate and effort table |
|
||||
| 2026-09-30 | major | Created |
|
||||
@@ -418,7 +418,7 @@ fn parse_one_region(item: &XmpValue, px_dims: Option<(f64, f64)>) -> Option<Regi
|
||||
// frame and writes the orientation as the region's `mwg-rs:Rotation` (π for 3, −π/2 for 6, +π/2 for
|
||||
// 8; 0 for 1) while `AppliedToDimensions` names the upright size. Turn it into the upright frame.
|
||||
// MWG has no way to say "mirrored", so orientations 2/4/5/7 can't be told apart from their unmirrored
|
||||
// twins here; boxes on mirrored photos are taken as written (see LR-LIB-PEOPLE in docs/parity.md).
|
||||
// twins here; boxes on mirrored photos are taken as written (see LR-LIB-PEOPLE in docs/parity-checklist.md).
|
||||
let rotation = item.field("mwg-rs:Rotation").and_then(XmpValue::text).and_then(parse_number).filter(|r| r.is_finite());
|
||||
let (quarter, half) = (std::f64::consts::FRAC_PI_2, std::f64::consts::PI);
|
||||
let (cx, cy, w, h) = match rotation {
|
||||
|
||||
@@ -27,7 +27,7 @@ pub const LANGUAGE_COMMANDS: &[UiCommand] = &[
|
||||
];
|
||||
|
||||
/// Every UI command: the languages, then everything else. `xtask parity` reads both tables from
|
||||
/// this file, so an id listed in `docs/parity.md` is checked wherever it is declared.
|
||||
/// this file, so an id listed in `docs/parity-checklist.md` is checked wherever it is declared.
|
||||
pub fn ui_commands() -> impl Iterator<Item = &'static UiCommand> {
|
||||
LANGUAGE_COMMANDS.iter().chain(UI_COMMANDS)
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ pub fn format(m: Modifiers, k: Key) -> Option<String> {
|
||||
|
||||
/// Secondary key bindings for commands that already exist: `(shortcut, command id, params JSON)`.
|
||||
/// They complement the primary shortcut declared on the command (Lightroom-desktop keys that our
|
||||
/// primary keymap assigns elsewhere, see docs/parity.md → Shortcuts). Shown in Help → Keyboard Shortcuts.
|
||||
/// primary keymap assigns elsewhere, see docs/ui-parity.md → Shortcuts). Shown in Help → Keyboard Shortcuts.
|
||||
pub const ALIASES: &[(&str, &str, &str)] = &[
|
||||
("Cmd+D", "library.selectNone", "{}"),
|
||||
("Shift+E", "dialog.export", "{}"),
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# Architecture
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created from the code; the full design notes stay in the local `plan/architecture.md`) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
|
||||
How LightCraft is built today. The longer design document (`plan/architecture.md`) is local-only
|
||||
(`plan/` is gitignored); this page is the committed, current summary. Sizes are Rust lines counted
|
||||
on 2026-10-10 (≈ 202,000 tracked lines in 505 files: 24 library crates, 3 apps and `xtask`).
|
||||
|
||||
## Layers
|
||||
|
||||
`cargo xtask layers` (part of `cargo xtask ci`, `xtask/src/layers.rs`) enforces that nothing below
|
||||
L5 depends on egui, eframe, winit or rfd, and that each crate only uses lower layers.
|
||||
|
||||
| Layer | Crates (lines) | Role |
|
||||
|---|---|---|
|
||||
| L0 | `geom` (1.4k), `color` (0.9k), `raster` (0.8k), `tiff` (2.0k), `fetch` (1.4k), `sysmem` (0.1k) | Matrices and warps, colour spaces and transfer functions, float image buffers, TIFF/IFD read and write, pinned HTTPS model downloads, the one `unsafe` FFI call (`malloc_zone_pressure_relief`) |
|
||||
| L1 | `raw` (22.3k), `codecs` (7.3k), `meta` (4.3k), `develop` (2.5k), `denoise-core` (2.2k), `denoise` (2.7k), `faces` (5.3k), `scenes` (1.0k), `heif` (2.1k, optional) | Raw decoders and demosaic, DNG colour model; standard codecs and encoders; EXIF/XMP/IPTC; the non-destructive edit model and control specs; AI denoise; face detection and recognition; procedural demo photos; HEIC |
|
||||
| L2 | `pipeline` (9.8k) | The develop pipeline: scene-referred float, resolution independent; the CPU reference (oracle) for everything else |
|
||||
| L3 | `catalog` (11.0k), `gpu` (5.1k), `preview` (1.3k), `merge` (3.8k), `segment` (2.3k) | Library model and persistence; wgpu compute twin of the pipeline; thumbnail/preview cache and job pool; HDR and panorama merge; SAM 3 segmentation |
|
||||
| L4 | `engine` (53.2k) | Session, command registry (everything is a command), history, render and export jobs, import, Lightroom catalog and preset import, faces index, view-models |
|
||||
| L5 | `ui-egui` (46.9k), `mcp` (2.3k) | The Lightroom-style egui interface (swappable); the MCP server |
|
||||
| L6 | `apps/lightcraft` (2.8k), `apps/lightcraft-cli` (1.5k), `apps/lightcraft-web` (3.4k), `xtask` (2.7k) | Desktop app (eframe + wgpu, native menus, control server), CLI (render, commands, calibrate, snapshot, MCP), WASM build, tooling |
|
||||
|
||||
## Data model
|
||||
|
||||
- **Photo** records in `catalog` hold the original's path, content hash, metadata, ratings, flags,
|
||||
labels, keywords, faces and the current `develop::Settings`. Albums, smart albums (rule trees),
|
||||
stacks, virtual copies, versions and folder records live alongside.
|
||||
- **Persistence** (`crates/catalog/src/journal.rs`): an append-only journal of human-readable
|
||||
operations plus periodic snapshots, compacted in the background; torn appends and crashes are
|
||||
tested (`tests_torn_append.rs`, `tests_journal.rs`). A lock file guards against two writers.
|
||||
- **Edits** are a `develop::Settings` value (every slider is a control spec with id, range and
|
||||
default), normalized to image coordinates so previews and exports match. Process versions
|
||||
(`docs/process-versions.md`) keep old edits rendering the same after a retune.
|
||||
- **Sidecars**: XMP read and write with Adobe `crs:` interop (`docs/xmp-interop.md`); Lightroom
|
||||
Classic `.lrcat` import through a pure-Rust SQLite reader (`docs/lightroom-catalog-import.md`).
|
||||
|
||||
## Rendering
|
||||
|
||||
1. **Decode** (`raw`, `codecs`): raw files to linear camera RGB (demosaic, black/white levels,
|
||||
opcodes, highlight handling) and a camera-to-XYZ colour model; standard images to linear light
|
||||
through their ICC profile.
|
||||
2. **Develop** (`pipeline`): white balance, profile, exposure and tone (local Laplacian
|
||||
highlights/shadows), curves, HSL / colour mixer, point colour, colour grading, texture, clarity,
|
||||
dehaze, detail (sharpening, NR, AI denoise result), optics (lens profile, CA, defringe,
|
||||
vignette), geometry (crop, Upright, transforms), masks with local adjustments, heal/clone, grain,
|
||||
effects. Stage caching and a source pyramid make slider drags cheap.
|
||||
3. **GPU** (`gpu`): the same stages in WGSL on Metal / DX12 / Vulkan, checked against the CPU path
|
||||
(within 1/255); GPU errors fall back to the CPU (`docs/gpu-pipeline.md`).
|
||||
4. **Display and export**: display-profile conversion (`docs/display-profiles.md`); export through
|
||||
one encoder for app, CLI, MCP and web (`lightcraft_engine::export`).
|
||||
|
||||
## Agent control
|
||||
|
||||
Every action is an engine command (id, label, menu path, shortcut, params, enabled, run). The UI,
|
||||
the CLI, the JSON-lines control channel (`docs/control-protocol.md`) and MCP (`docs/mcp.md`) all
|
||||
dispatch by id, and headless snapshots render the UI without a window.
|
||||
|
||||
## Quality gates
|
||||
|
||||
`cargo xtask ci`: fmt, clippy `-D warnings` with the never-crash lints, the HEIF build, tests,
|
||||
`parity` (every id and path cited in [parity-checklist.md](parity-checklist.md) exists), `layers`,
|
||||
`assets` (every asset attributed, no Adobe formats) and the WASM build. Other workflows build and
|
||||
test FreeBSD and Windows ARM64, lint packaging, and build releases.
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | major | Created from the code (crate sizes, layers, data model, rendering, control, gates) |
|
||||
@@ -0,0 +1,79 @@
|
||||
# File format parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created; formats measured from the code and the target's Info.plist) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
|
||||
Every format Lightroom reads or writes, with our support, fidelity and tests. Camera raw formats are
|
||||
deep enough to have their own document: [raw-parity.md](raw-parity.md).
|
||||
|
||||
**How measured:** the target's document types come from the installed Lightroom 9.6
|
||||
`Info.plist` (`CFBundleDocumentTypes`: catalog `mcat`, `xmp`, toolkit / module / library bundles, and
|
||||
the raw-and-image list: jpg, tif, dng, heic and 27 raw extensions) plus Lightroom Classic's documented
|
||||
import and export formats. Ours come from `crates/codecs/src/sniff.rs`, `crates/codecs/src/encode.rs`,
|
||||
`crates/engine/src/export.rs`, `crates/engine/src/import.rs` and the tests named below.
|
||||
|
||||
## Images (non-raw)
|
||||
|
||||
| Format | Target reads | Target writes | LightCraft reads | LightCraft writes | Notes / tests |
|
||||
|---|---|---|---|---|---|
|
||||
| JPEG | ✅ | ✅ | ✅ (parallel decoder, ICC, EXIF orientation) | ✅ quality, size limit, ICC, metadata | `crates/codecs/src/jpeg.rs`, export tests |
|
||||
| TIFF | ✅ 8/16/32-bit | ✅ 8/16-bit, LZW/ZIP | ✅ 1–64-bit integer, 16–64-bit float, bilevel, CCITT fax, WhiteIsZero | ✅ 8/16-bit, 32-bit float linear, none / LZW / ZIP | `crates/tiff`, `crates/codecs/src/tiff_codec.rs` |
|
||||
| PNG | ✅ | ✅ | ✅ | ✅ | |
|
||||
| PSD / PSB | ✅ (maximized-compatibility composite) | ✅ (Classic: PSD export, edit-in round trip) | ✅ merged composite | ⬜ (external-editor round trip writes 16-bit TIFF) | `crates/codecs/src/psd.rs` |
|
||||
| HEIC / HEIF | ✅ | ⬜ (Classic) / HDR only | ✅ in every release build (`crates/heif`, heic-rs) | ⬜ | `heif` feature on by packaging scripts |
|
||||
| AVIF | ✅ | ✅ (HDR) | ⬜ recognised, not decoded (no permissive pure-Rust AV1 decoder) | ✅ 8/10-bit, PQ HDR | |
|
||||
| JPEG XL | ✅ | ✅ | ✅ (`jxl-oxide`) incl. DNG 1.7 JXL tiles | ⬜ | |
|
||||
| WebP | not in its document types | ⬜ | ✅ | ✅ | beyond target |
|
||||
| GIF, BMP | ⬜ | ⬜ | ✅ | ⬜ | beyond target |
|
||||
| DNG (from raw) | ✅ | ✅ incl. lossy, embedded original | ✅ | ✅ uncompressed or LJ92; ⬜ lossy DNG, embedded original | `crates/raw/src/dngwrite.rs` |
|
||||
| Render to DNG (15.5) | — | ✅ | — | ⬜ | new in Classic 15.5 |
|
||||
| Original + sidecar | — | ✅ | — | ✅ | |
|
||||
| HDR gain map JPEG (ISO 21496-1) | ✅ | ✅ | ✅ (gain map read) | ✅ | `crates/codecs/src/gainmap.rs` |
|
||||
| PQ / HLG HDR | ✅ | ✅ AVIF, JXL, TIFF | — | 🟡 PQ AVIF, float TIFF; no HLG | |
|
||||
| Contact sheet / print PDF | — | ✅ (Print module: PDF / JPEG / printer) | — | 🟡 paginated contact-sheet PDF (A4 / Letter, 150 dpi, sRGB) | `crates/engine/src/contact_sheet.rs` |
|
||||
| Video (MP4, MOV, AVCHD…) | ✅ playback, trim, edit | ✅ export | 🟡 catalogued (kind, duration) | ⬜ | see video gap |
|
||||
|
||||
## Colour spaces and profiles
|
||||
|
||||
| Feature | Target | LightCraft |
|
||||
|---|---|---|
|
||||
| Export colour spaces | sRGB, Adobe RGB, Display P3, ProPhoto, Rec.2020, custom ICC | ✅ sRGB, Display P3, Adobe RGB-compatible, ProPhoto, Rec.2020 with gamut mapping (CPU and GPU), embedded ICC; ⬜ custom ICC output profiles; AVIF stays sRGB |
|
||||
| Input ICC (JPEG / TIFF / PNG) | ✅ | ✅ matrix / TRC and LUT profiles (moxcms) |
|
||||
| Soft proofing with printer profiles | ✅ | 🟡 |
|
||||
|
||||
## Metadata, sidecars, presets and catalogs
|
||||
|
||||
| Format | Target | LightCraft | Notes |
|
||||
|---|---|---|---|
|
||||
| XMP sidecars (`crs:` develop settings, ratings, keywords, regions) | read / write | ✅ read / write, manual (⌘S) and automatic | [xmp-interop.md](xmp-interop.md) |
|
||||
| EXIF / IPTC / XMP embedded on export | ✅ | ✅ with metadata filters | `crates/meta` |
|
||||
| Develop presets `.xmp` | ✅ | ✅ import (mapping of supported settings) | |
|
||||
| Legacy presets `.lrtemplate` | ✅ (converted) | ✅ import | |
|
||||
| Camera / creative profiles (`.dcp`, `.xmp` profiles) | ✅ | ⬜ deliberately (Adobe profile formats are never used); `.cube` LUT profiles ✅ | |
|
||||
| Lens profiles `.lcp` | ✅ | ⬜ deliberately | |
|
||||
| Other apps' presets | — | ✅ Luminar `.lmp` / `.mplumpack`, `.zip` bundles | beyond target |
|
||||
| Lightroom Classic catalog `.lrcat` | native | 🟡 import (ratings, flags, labels, keywords, collections, virtual copies, supported develop settings; read-only pure-Rust SQLite incl. WAL) | [lightroom-catalog-import.md](lightroom-catalog-import.md) |
|
||||
| Lightroom (cloud) library `.lrlibrary` | native | ⬜ | cloud library format, local cache only |
|
||||
| Write back to `.lrcat` | native | ⬜ (one-way migration by design) | |
|
||||
| Keyword lists (text) | import / export | ✅ | |
|
||||
| GPX track logs | ✅ | ✅ | `crates/meta/src/gpx.rs` |
|
||||
| Export presets, metadata presets, filename templates | ✅ (`.lrtemplate`) | ✅ own JSON | not interchangeable |
|
||||
| Lightroom plug-ins (`.lrplugin`, `.lrdevplugin`) | ✅ | ⬜ | see ecosystem in [target-app-parity.md](target-app-parity.md) |
|
||||
|
||||
## Scores
|
||||
|
||||
| Part | Weight | Ready for real work | Kind |
|
||||
|---|---:|---:|---|
|
||||
| Standard image import / export | 35% | ~85% | estimated (table above; missing: AVIF read, JXL / PSD write, lossy DNG) |
|
||||
| Sidecars, metadata, presets | 25% | ~85% | estimated |
|
||||
| Lightroom catalog migration | 25% | ~50% | estimated (one-way, approximate rendering of unsupported settings) |
|
||||
| HDR, print, video output | 15% | ~35% | estimated |
|
||||
| **Non-raw file formats** | 100% | **~70%** | estimated; raw is in [raw-parity.md](raw-parity.md) (~50%) |
|
||||
|
||||
Remaining: **30–55 h** (AVIF decode 8–15 h if a permissive decoder is written or found; JXL encode
|
||||
4–8 h; PSD write 4–8 h; lossy DNG and Render to DNG 4–8 h; HLG 3–5 h; catalog import depth 8–12 h).
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | major | Created from the code and the installed Lightroom's document types |
|
||||
@@ -0,0 +1,77 @@
|
||||
# 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
|
||||
|
||||
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
|
||||
working on). When you close a gap, delete or shrink its entry, update its rows in
|
||||
[parity-checklist.md](parity-checklist.md), and the numbers in [target-app-parity.md](target-app-parity.md)
|
||||
and [ROADMAP.md](../ROADMAP.md) if they move.
|
||||
|
||||
Hours are Opus 5.5 agent wall-clock hours (see [target-app-parity.md](target-app-parity.md#how-hours-are-calibrated)).
|
||||
`B` marks a gap that blocks **beta**.
|
||||
|
||||
## Ranked
|
||||
|
||||
| # | 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) |
|
||||
| 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) |
|
||||
| 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) |
|
||||
| 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) |
|
||||
| 6 B | **Compressed ORF** (every Olympus / OM body since ~2008) | measured: 66 of 78 Olympus / OM models preview-only; `orf.rs` refuses; OM bucket 3% of photographers, 3% of them fully work | +2.6 points; best gain per hour of any raw gap (~0.2) | 8–15 | [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) |
|
||||
| 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) |
|
||||
| 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) |
|
||||
| 14 | **HDR display** (EDR / Windows HDR); HLG; HDR settings from `crs` XMP | HDR rows 70%; LR-VIEW-HDR-DISPLAY ⬜ | HDR editing works blind on HDR monitors | 12–25 | [hardware-parity](hardware-parity.md) |
|
||||
| 15 | **Print module**: custom packages, printer colour management (contact-sheet PDF only) | LRC-PRINT rows | Classic users who print | 25–40 | [target-app-parity](target-app-parity.md#features) |
|
||||
| 16 | **Map view, Book, Slideshow module, publish services** | LRC-MAP / BOOK / SS rows ⬜ | Classic users; publish services matter for Flickr / SmugMug workflows | 60–100 | [target-app-parity](target-app-parity.md#features) |
|
||||
| 17 | **Tethered capture** | ⬜ | studio photographers | 25–45 + cameras | [hardware-parity](hardware-parity.md) |
|
||||
| 18 | **Video**: playback, trim, global edits, export | VID rows 0% | users who mix stills and clips | 25–45 | [target-app-parity](target-app-parity.md#features) |
|
||||
| 19 | **Plug-in ecosystem**: no Lightroom SDK equivalent (export / publish plug-ins, metadata plug-ins) | ⬜ | pro workflows built on plug-ins (LR/Enfuse, Jeffrey's exporters, Negative Lab Pro) | 40–80 + owner decision | [target-app-parity](target-app-parity.md#by-dimension) |
|
||||
| 20 | **Long-tail raw formats**: compressed SRW, ARQ pixel shift, IIQ, Hasselblad compression, X3F, CRW, MRW, ERF, KDC, DCR, MEF, GPR, old FinePix | raw-parity.md | small user share each | 45–85 | [raw-parity](raw-parity.md) |
|
||||
| 21 | **Localization**: 9 of 15 shipped languages partial (74–99% of catalog messages), lower-layer errors English; Hindi, Arabic, Indonesian, Korean, Vietnamese absent; no RTL or complex shaping | measured from catalogs | non-English users see mixed English | 55–90 (shipped to full); 145–255 (five new) | [localization-parity](localization-parity.md) |
|
||||
| 22 | **Pen pressure**, OS monitor profiles, follow-window colour | hardware-parity.md | brush users with tablets; multi-monitor setups | 11–22 | [hardware-parity](hardware-parity.md) |
|
||||
| 23 | **Accessibility** audit with screen readers; canvas tools keyboard-reachable | LR-BEHAV-ACCESS 🟡 | blind and low-vision users | 10–20 | [ui-parity](ui-parity.md) |
|
||||
| 24 | **Brush live preview and masking feel** (#517, #518); Feather / Edge mask refinement (15.5) | issues | masking feels slower than Lightroom | 8–12 | [ui-parity](ui-parity.md) |
|
||||
| 25 | **File writes**: JXL encode, PSD export, lossy DNG, Render to DNG; AVIF import | file-format-parity.md | interchange edge cases | 25–45 | [file-format-parity](file-format-parity.md) |
|
||||
| 26 | **Performance at scale**: 85k-photo library opens in 1.7–4.7 s; 100k grid test pending; colour NR at half resolution | ROADMAP log, gpu-pipeline.md | large-catalog users | 15–30 | [target-app-parity](target-app-parity.md#by-dimension) |
|
||||
| 27 | **Windows / Linux runtime coverage**: Windows installer UI unverified on Windows (#79); GPU path proven on Apple only | ROADMAP, issues | non-Mac users find bugs first | 15–30 | [hardware-parity](hardware-parity.md) |
|
||||
| 28 | **Small Classic shortcuts and keys**: rating `[` `]`, flag cycling, filter-bar keys, F1 help, panel keys (Tab, F5–F8) | [ui-parity](ui-parity.md#shortcuts) | Classic muscle memory | 4–8 | [ui-parity](ui-parity.md) |
|
||||
|
||||
Beta-blocking gaps (B) total **~230–430 h**; with the stability and platform work they need around them,
|
||||
**~340–600 h** to beta (incl. 40–80 h for the ~92 open core-path user issues) (see [target-app-parity.md](target-app-parity.md#stage)).
|
||||
|
||||
## Gaps by kind
|
||||
|
||||
- **Feature:** 5, 8, 11, 12, 13, 15, 16, 18, 19
|
||||
- **UI / UX:** 4, 23, 24, 28
|
||||
- **File format:** 2, 6, 7, 10, 13, 20, 25 (raw ones in [raw-parity.md](raw-parity.md))
|
||||
- **Hardware:** 14, 17, 22, 27
|
||||
- **Localization:** 21
|
||||
- **Quality / fidelity:** 1, 3
|
||||
- **Stability and platforms:** 9, 26, 27
|
||||
|
||||
## Closed recently (kept for calibration)
|
||||
|
||||
- 2026-10-10: Nikon lossy-after-split NEF (#633), ORF 12.8 bpp (#651), HDR gain map / PQ AVIF / float
|
||||
TIFF export (#646), activity stack (#345).
|
||||
- 2026-10-09: HEIC in release builds (#609), Samsung uncompressed SRW (#459), contact-sheet PDF (#563),
|
||||
Ukrainian UI (#564), Sony ILCE-7CR profile.
|
||||
- 2026-10-08: CR3 CRX lossless and C-RAW (#279), Fujifilm compressed RAF (#282), AI RAW denoise (#384),
|
||||
Lightroom catalog import (#218), German, Spanish, Russian UI.
|
||||
- 2026-10-07: RW2 every format (#215), faces recognition in pure Rust (#174).
|
||||
- 2026-10-05: compressed NEF (#86). The older history is in [ROADMAP.md](../ROADMAP.md#progress-log).
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 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 |
|
||||
@@ -0,0 +1,50 @@
|
||||
# Hardware parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created from the code, gpu-pipeline.md and the parity checklist) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
|
||||
What Lightroom does with the machine's hardware, per platform, and what LightCraft does. Sources:
|
||||
[gpu-pipeline.md](gpu-pipeline.md), [display-profiles.md](display-profiles.md), [denoise.md](denoise.md),
|
||||
[ai-masks.md](ai-masks.md), `crates/gpu`, `crates/engine/src/devices.rs`, `crates/ui-egui/src/panels/second.rs`.
|
||||
|
||||
| Feature | Target | LightCraft: macOS | Windows | Linux / BSD | Web | Status |
|
||||
|---|---|---|---|---|---|---|
|
||||
| GPU for display and editing | Metal / DX12, "Use GPU for display / image processing / export" | wgpu Metal: geometry, resize, blur, WB, NR, guided filter, dehaze, masks, finish; CPU fallback per render | DX12 only (Vulkan opt-in, #136) | Vulkan | CPU only (no WebGPU yet) | 🟡 defringe, spot removal, heuristic masks, long brushes and high-bit exports stay on CPU |
|
||||
| GPU export | ✅ | ✅ (6000 × 4000 in ~0.3 s vs ~1.2 s CPU) | ✅ | ✅ | — | ✅ (black-export fix on an Intel iGPU, #78) |
|
||||
| AI on GPU / neural engine | Metal / DirectML / Core ML, model per feature | AI denoise on GPU or CPU (setting); SAM 3 on Metal via candle; faces on CPU | CPU / GPU denoise | CPU / GPU denoise | — | 🟡 no Core ML / Neural Engine / DirectML |
|
||||
| HDR (EDR) display | ✅ (macOS EDR, Windows HDR) | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ (LR-VIEW-HDR-DISPLAY) |
|
||||
| Monitor profile | automatic per display, follows the window | 🟡 picked by hand | 🟡 | 🟡 | — | 🟡 OS profile not read; no follow across monitors |
|
||||
| Second window / second monitor | ✅ (Classic) | ✅ (⌘F11) | ✅ | ✅ | — | ✅ (Classic secondary-window keys missing) |
|
||||
| Pen pressure / tilt (brush masks) | ✅ pressure for size / flow | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| Trackpad gestures | pinch zoom, pan | ✅ pinch, two-finger pan | 🟡 (winit) | 🟡 | 🟡 | ✅ on macOS |
|
||||
| Card readers / cameras as import sources | ✅ (devices panel, eject after import) | ✅ mounted volumes with DCIM | ✅ | ✅ | — | 🟡 no eject-after-import check, no MTP / PTP phones |
|
||||
| Tethered capture | ✅ Classic (Canon, Nikon, Sony, Leica) | ⬜ | ⬜ | ⬜ | — | ⬜ |
|
||||
| Printers | ✅ Print module, printer colour management | ⬜ (PDF contact sheets only) | ⬜ | ⬜ | — | ⬜ |
|
||||
| Control surfaces (MIDI / Loupedeck via plug-ins) | via SDK plug-ins | control channel and MCP can drive every command | same | same | — | 🟡 different mechanism; no MIDI mapping |
|
||||
| Multi-core CPU | ✅ | ✅ worker pools, parallel JPEG decode, parallel import copy | ✅ | ✅ | single thread | ✅ |
|
||||
| Memory pressure | managed | ✅ memory budget, `crates/sysmem` returns allocator pages on macOS | ✅ budget | ✅ budget | — | ✅ |
|
||||
|
||||
## Score
|
||||
|
||||
**~40% ready** (estimated): the GPU editing path is real and fast (measured: 24 MP exposure drag
|
||||
3.9 ms on GPU vs 22–42 ms CPU; NR drag 18 ms vs 301–471 ms), but HDR display, pen pressure,
|
||||
tethering, printing, automatic monitor profiles and neural-engine inference are missing. GPU
|
||||
correctness is proven on Apple GPUs; other vendors rely on user reports.
|
||||
|
||||
## Remaining (Opus 5.5 agent hours)
|
||||
|
||||
| Work | Hours | Needs |
|
||||
|---|---:|---|
|
||||
| HDR display (EDR on macOS, Windows HDR, Linux where possible) | 10–20 | an HDR display to verify (human) |
|
||||
| OS monitor profile, follow window across displays | 5–10 | multi-monitor setup |
|
||||
| Pen pressure for brush masks (winit tablet events or a pure-Rust tablet layer) | 6–12 | a tablet |
|
||||
| Remaining stages on GPU (defringe, spot removal, masks) | 10–20 | |
|
||||
| Tethered capture (PTP over USB in pure Rust, Canon / Nikon / Sony first) | 25–45 | cameras (human) |
|
||||
| Printing with colour management | 15–25 | printers (human) |
|
||||
| Neural-engine / DirectML inference for AI features | 10–20 | depends on the AI model decision |
|
||||
| **Total** | **80–150 h** (the core set for beta, HDR display + monitor profile + pen pressure: 20–40 h) | |
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | major | Created |
|
||||
@@ -0,0 +1,92 @@
|
||||
# Localization parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (first per-language measurement from the catalogs) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
|
||||
How far each interface language is from `full`. How to add or maintain a language is in
|
||||
[localization.md](localization.md); per-language notes are in `localization-<code>.md`
|
||||
([zh-hans](localization-zh-hans.md), [zh-hant](localization-zh-hant.md), [ja](localization-ja.md),
|
||||
[pt-br](localization-pt-br.md), [es](localization-es.md), [de](localization-de.md),
|
||||
[ru](localization-ru.md)).
|
||||
|
||||
## The target
|
||||
|
||||
Lightroom 9.6 (installed on the owner's Mac) ships 16 interface languages, listed from its bundle's
|
||||
`.lproj` folder names: English, German, Spanish, French, Italian, Japanese, Korean, Norwegian Bokmål,
|
||||
Dutch, Polish, Portuguese (Brazil), Russian, Swedish, Thai, Simplified Chinese and Traditional
|
||||
Chinese. It does **not** ship Hindi, Arabic, Indonesian or Vietnamese, so for those LightCraft would
|
||||
go beyond the target.
|
||||
|
||||
## How the numbers are measured
|
||||
|
||||
**Measured** (a Python count over `crates/ui-egui/locales/*.json`, 2026-10-10):
|
||||
|
||||
- The denominator is every message any catalog knows: the union of the plain catalogs' keys (2,074
|
||||
English source strings: menus, commands, controls, panels, dialogs, tooltips, presets, What's New
|
||||
lines) plus the 230 messages of the formats catalogs (`*-formats.json`: text with runtime values and
|
||||
date patterns), 2,304 messages in all.
|
||||
- A message counts as translated when the catalog has a non-empty value that differs from the English
|
||||
key. Some identical values are correct (`ISO`, `OK` in German), so the figure slightly understates
|
||||
coverage; on the other hand, strings that never reach a catalog (technical errors raised in lower
|
||||
crates, some `format!` text outside `tr_format!`) are not in the denominator at all. That is why no
|
||||
language is `full` even at 99%.
|
||||
- The UI has 563 distinct `tr("…")` literals and 198 `tr_format!` messages in `crates/ui-egui` and
|
||||
`apps/`; command, control, menu and preset labels reach the catalogs through `display_label`.
|
||||
|
||||
Script support is checked against the code: `language_table!` in `crates/ui-egui/src/i18n.rs` lists
|
||||
scripts `Latn`, `Cyrl`, `Hans`, `Hant`, `Jpan` only. The UI is egui, which has no bidirectional layout
|
||||
and no complex-script shaping, so Arabic (RTL, joining) and Devanagari (conjuncts, reordering) cannot
|
||||
render correctly today.
|
||||
|
||||
Native-speaker review: no catalog has had a formal review. Several catalogs have edits from community
|
||||
contributors whose commits only touch that language (ja, zh-hans, zh-hant, fr, de, ru, uk, pt-br);
|
||||
that is promising but is not recorded as review, so the column says `no (community edits)`.
|
||||
|
||||
## The twelve key languages
|
||||
|
||||
| # | Language | Code | UI strings translated | Dialogs / tooltips / help | Script support | Native review | Status | To `full` |
|
||||
|---|---|---|---:|---|---|---|---|---:|
|
||||
| 1 | English | `en` | 2,304 / 2,304 (100%, source) | all; Help ▸ What's New and the shortcut sheet; no full user manual | Latin (Inter) | n/a | **full** | 0 h |
|
||||
| 2 | Simplified Chinese | `zh-hans` | 1,994 / 2,304 (87%) | menus, panels, dialogs, presets, profiles, dates; lower-layer errors English | Hans via craft-fonts (Noto Sans CJK SC); IME through winit; no vertical text in UI (not in target either) | no (community edits) | partial | 6–10 h |
|
||||
| 3 | Spanish | `es` | 1,972 / 2,304 (86%) | as zh-hans | Latin | no (community edits) | partial | 6–10 h |
|
||||
| 4 | Hindi | `hi` | 0 (0%) | none | **Devanagari shaping missing** (egui has no complex shaping) | no | none (target: not shipped) | 50–90 h (shaping 25–50 h, shared with Arabic) |
|
||||
| 5 | Arabic | `ar` | 0 (0%) | none | **RTL layout and Arabic shaping missing** | no | none (target: not shipped) | 60–110 h (RTL mirroring 30–50 h + shaping, shared with Hindi) |
|
||||
| 6 | French | `fr` | 2,021 / 2,304 (88%) | as zh-hans | Latin | no (community edits) | partial | 5–9 h |
|
||||
| 7 | Portuguese (Brazil) | `pt-br` | 1,966 / 2,304 (85%) | as zh-hans | Latin | no (community edits) | partial | 6–10 h |
|
||||
| 8 | Indonesian | `id` | 0 (0%) | none | Latin (Inter covers it) | no | none (target: not shipped) | 10–16 h |
|
||||
| 9 | Japanese | `ja` | 1,995 / 2,304 (87%) | as zh-hans; vertical export watermarks | Jpan via craft-fonts (BIZ UDPGothic / UDMincho); IME through winit | no (community edits) | partial | 6–10 h |
|
||||
| 10 | German | `de` | 2,104 / 2,304 (91%) | as zh-hans; What's New translated line by line | Latin | no (community edits) | partial | 4–8 h |
|
||||
| 11 | Korean | `ko` | 0 (0%) | none | **no Korean (Hangul) face**: needs a non-Adobe OFL face in craft-fonts (Noto CJK is allowed only for Chinese) | no | none | 14–22 h |
|
||||
| 12 | Vietnamese | `vi` | 0 (0%) | none | Latin with stacked diacritics (Inter covers it; check combining marks) | no | none (target: not shipped) | 10–16 h |
|
||||
|
||||
## Other languages LightCraft ships (3)
|
||||
|
||||
| Language | Code | UI strings translated | Script | Native review | Status | To `full` |
|
||||
|---|---|---:|---|---|---|---:|
|
||||
| Traditional Chinese (Taiwan) | `zh-hant` | 1,993 / 2,304 (87%) | Hant; uses the Simplified Chinese face until craft-fonts has a TC face | no (community edits) | partial | 8–14 h (incl. the font) |
|
||||
| Russian | `ru` | 1,704 / 2,304 (74%) | Cyrillic (Inter) | no (community edits) | partial | 8–12 h |
|
||||
| Ukrainian | `uk` | 2,287 / 2,304 (99%) | Cyrillic (Inter) | no (community edits) | partial (lower-layer errors English) | 2–4 h |
|
||||
|
||||
Target languages LightCraft lacks: Italian, Korean, Dutch, Polish, Swedish, Norwegian Bokmål, Thai
|
||||
(Thai needs shaping and line breaking without spaces). Each Latin-script one is ~10–16 h; Thai
|
||||
~20–35 h on top of the shaping work.
|
||||
|
||||
## Shared work before any language is `full` (counted once, ~20–35 h)
|
||||
|
||||
- Route lower-layer error messages (catalog, raw, codecs, engine) through translatable message ids
|
||||
instead of English `format!` strings (~12–20 h).
|
||||
- A check in `cargo xtask ci` that every user-visible literal reaches a catalog (~4–8 h).
|
||||
- A user manual / help pages beyond What's New and the shortcut sheet (Lightroom links to online
|
||||
help; ~4–8 h for a translatable in-app help index).
|
||||
- Native-speaker review passes (human; cannot be done by agents).
|
||||
|
||||
## Totals
|
||||
|
||||
- Bring the 9 shipped non-English catalogs to `full`: ~55–90 h (incl. the shared work).
|
||||
- Add the 5 missing key languages: ~145–255 h, most of it RTL and complex shaping in egui.
|
||||
- Reach the target's 16 languages: + ~60–100 h (Italian, Dutch, Polish, Swedish, Norwegian, Thai).
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | major | Created: per-language counts measured from the catalogs, the twelve key languages, script support, estimates |
|
||||
@@ -1,7 +1,15 @@
|
||||
# Lightroom parity tracker
|
||||
# Lightroom parity checklist
|
||||
|
||||
A living checklist of every Lightroom feature LightCraft aims to match, what we have, and what is missing. Agents and
|
||||
humans pick work from **[Top gaps](#top-gaps)**; whoever lands a feature updates its row in the same commit.
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** minor (renamed from `parity.md`; Top gaps moved to gaps.md, shortcut notes to ui-parity.md) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
|
||||
The measured, row-by-row checklist: one row per Lightroom feature, menu item and shortcut, what we
|
||||
have and what is missing. It answers *does the feature exist?* (feature breadth). Whether it is good
|
||||
enough to replace Lightroom is assessed in [target-app-parity.md](target-app-parity.md), and the work
|
||||
list is [gaps.md](gaps.md). Whoever lands a feature updates its row in the same commit.
|
||||
|
||||
The rows are maintained by hand; the summary block is generated (`cargo xtask parity --write`), and
|
||||
`cargo xtask parity` (part of `cargo xtask ci`) checks that every command id, control id and path
|
||||
cited here still exists. Formerly docs/parity.md.
|
||||
|
||||
- **Ids** come from the (local, gitignored) reference in `plan/lightroom/`: `LR-…` = feature catalog (03),
|
||||
`MENU-…` = menu items (04), `KEY-…` / `KEYC-…` = keyboard shortcuts (06, desktop / Classic), `LRC-…` = Classic
|
||||
@@ -13,9 +21,6 @@ humans pick work from **[Top gaps](#top-gaps)**; whoever lands a feature updates
|
||||
id (`lightcraft-cli controls`), plus source files. A trailing `*` matches a prefix (`ctl:mixer.*`).
|
||||
- Feature names and notes are our own words. No Adobe text, screenshots or assets belong here.
|
||||
|
||||
`cargo xtask parity` checks that every `cmd:`/`ctl:` id and file path below still exists (part of `cargo xtask ci`)
|
||||
and prints the summary; `cargo xtask parity --write` refreshes the summary table below.
|
||||
|
||||
## Summary
|
||||
|
||||
<!-- parity:summary -->
|
||||
@@ -42,92 +47,21 @@ and prints the summary; `cargo xtask parity --write` refreshes the summary table
|
||||
| S. Export (EXP) | 15 | 2 | 1 | 0 | 7/7 (100%) | 7/7 (100%) |
|
||||
| T. Share (SHARE) | 0 | 0 | 0 | 4 | — | — |
|
||||
| U. Map & location (MAP) | 0 | 1 | 1 | 0 | — | 0/1 (0%) |
|
||||
| V. Preferences (PREF) | 7 | 1 | 2 | 2 | 1/1 (100%) | 5/5 (100%) |
|
||||
| V. Preferences (PREF) | 6 | 2 | 2 | 2 | 1/1 (100%) | 4/5 (80%) |
|
||||
| W. Cloud & AI infrastructure (CLOUD / AI) | 1 | 0 | 1 | 2 | — | — |
|
||||
| X. Cross-cutting behaviours (BEHAV) | 18 | 6 | 1 | 1 | 8/8 (100%) | 6/9 (67%) |
|
||||
| Y. Menus | 82 | 0 | 4 | 8 | 47/47 (100%) | 23/23 (100%) |
|
||||
| Z. Keyboard shortcuts (desktop) | 75 | 3 | 3 | 1 | 49/52 (94%) | 23/24 (96%) |
|
||||
| Lightroom Classic extras | 32 | 11 | 39 | 9 | — | 22/24 (92%) |
|
||||
| **Total** | 393 | 39 | 84 | 36 | 192/200 (96%) | 142/152 (93%) |
|
||||
| Lightroom Classic extras | 33 | 15 | 35 | 9 | — | 23/25 (92%) |
|
||||
| **Total** | 397 | 49 | 73 | 36 | 192/200 (96%) | 143/155 (92%) |
|
||||
|
||||
Weighted completion (✅ = 1, 🟡 = ½, 🚫 left out): **79.9%** of 516 in-scope rows — P0 98.0% of 200 · P1 95.7% of 152 · P2 42.9% of 163.
|
||||
Weighted completion (✅ = 1, 🟡 = ½, 🚫 left out): **81.2%** of 519 in-scope rows — P0 98.0% of 200 · P1 95.2% of 155 · P2 47.2% of 163.
|
||||
<!-- /parity:summary -->
|
||||
|
||||
## Top gaps
|
||||
## Top gaps and shortcut notes
|
||||
|
||||
Ordered by user impact, then tier, then effort. The checklist above counts features that *exist*; these are the gaps
|
||||
that decide whether a photographer can switch (see the honest assessment in [ROADMAP.md](../ROADMAP.md#where-we-stand)).
|
||||
Take the first one nobody is working on.
|
||||
|
||||
1. **LR-PROF-CAMERACOLOR** (P0): our own camera colour calibration. Sony ARW, Nikon NEF and Panasonic RW2 now get a guarded file-local fit to their own embedded JPEG (colour matrix + hue/saturation/value table + tone and chroma curves, relative WB; per-model profiles pooled from many photos via `lightcraft-cli calibrate` for ARW and NEF; ARW: 7 of 10 public samples accepted, mean ΔE vs the camera JPEG 17–26 → 3–10; NEF: 13 of 13 decodable samples from 6 bodies accepted, ΔE 13–46 → 3–8, one mixed-light scene 13 → 12; RW2: 140 of 174 public samples accepted, from 93 of the 114 bodies with a preview, median ΔE 5.0); Nikon CropArea and untagged-preview ColorSpace metadata are respected; measured calibration and fidelity remain missing. Other non-DNG raws and rejected fits still use a neutral matrix. Expand validated preview fitting and use matrices the files carry themselves; never Adobe data.
|
||||
2. **LR-IMP-FORMATS** (P0): **CR3** first (every Canon body since ~2018), then compressed RAF / ORF, Nikon
|
||||
1. **LR-PROF-CAMERACOLOR** (P0): our own camera colour calibration. Sony ARW, Nikon NEF, Panasonic RW2 and Fujifilm RAF now get a guarded file-local fit to their own embedded JPEG (colour matrix + hue/saturation/value table + tone and chroma curves, relative WB; per-model profiles pooled from many photos via `lightcraft-cli calibrate` for ARW, NEF and RAF; ARW: 7 of 10 public samples accepted, mean ΔE vs the camera JPEG 17–26 → 3–10; NEF: 13 of 13 decodable samples from 6 bodies accepted, ΔE 13–46 → 3–8, one mixed-light scene 13 → 12; RW2: 140 of 174 public samples accepted, from 93 of the 114 bodies with a preview, median ΔE 5.0; RAF: 23 of 24 references accepted with bundled X-H2S/X-T4 profiles; 150 withheld-file tests improve mean ΔE slightly over per-file fitting); measured calibration and fidelity remain missing. Other non-DNG raws and rejected fits still use a neutral matrix. Expand validated preview fitting and use matrices the files carry themselves; never Adobe data.
|
||||
2. **LR-IMP-FORMATS** (P0): **CR3** first (every Canon body since ~2018), then compressed ORF, Nikon
|
||||
1. **LR-PROF-CAMERACOLOR** (P0): our own camera colour calibration. Sony ARW, Nikon NEF and Panasonic RW2 now get a guarded file-local fit to their own embedded JPEG (colour matrix + hue/saturation/value table + tone and chroma curves, relative WB; per-model profiles pooled from many photos via `lightcraft-cli calibrate` for ARW and NEF; ARW: 7 of 10 public samples accepted, mean ΔE vs the camera JPEG 17–26 → 3–10; NEF: 13 of 13 decodable samples from 6 bodies accepted, ΔE 13–46 → 3–8, one mixed-light scene 13 → 12; RW2: 140 of 174 public samples accepted, from 93 of the 114 bodies with a preview, median ΔE 5.0); measured calibration and fidelity remain missing. Other non-DNG raws and rejected fits still use a neutral matrix. Expand validated preview fitting and use matrices the files carry themselves; never Adobe data.
|
||||
2. **LR-IMP-FORMATS** (P0): CR3 lossless Bayer and version 0x100/0x200 C-RAW now decodes (M50/R100/R8 full sensor exact). Remaining unverified CRX variants, compressed RAF / ORF, Nikon
|
||||
Canon sRAW; AVIF decode (HEIC decodes behind the codecs' non-default `heif` feature:
|
||||
the optional `lightcraft-heif` crate on heic-rs, the same decoder and policy as PhotoCraft). Clean-room, from prose descriptions only (see
|
||||
`crates/raw/src/vendor/nefc.rs` for how compressed NEF was done). Until decoded, such photos are `preview_only`.
|
||||
3. **LR-IMP-CAMERA-COVERAGE** (P0): per-model verification; grow the CC0 corpus and fix per-model bugs (like the CR2
|
||||
colour-filter layout, fixed in #85 by reading the file's own tag).
|
||||
4. **LR-BEHAV-RENDER-FIDELITY** (P1): a side-by-side fidelity suite against Lightroom renders (kept local in `plan/`),
|
||||
then tune tone, highlights, texture/clarity/dehaze, NR and sharpening against it. A retune that changes how existing
|
||||
settings render ships as a new process version, so existing edits keep their look (`docs/process-versions.md`).
|
||||
4b. **LR-VIEW-ZOOM** (P0): finish the sharp zoomed views of issue #323: windows for compare, overlays and soft proofing
|
||||
(Before/After has them); check sharpness and the wide-stage margin on real raw photos (only synthetic scenes so far).
|
||||
5. **LR-EDIT-OPTICS-PROFILE** (P1): a lens-profile database of our own (corrections embedded in DNG files and the
|
||||
distortion correction Panasonic / Leica cameras record in RW2 / RWL files work today; issue #256). Sony ILCE-7RM4A Bayer
|
||||
ARW 16-sample tables in native 3:2 framing now feed the same distortion path; broader coverage and Sony
|
||||
vignetting / lateral CA remain (see `docs/sony-lens-corrections.md`).
|
||||
6. **AI masks and Enhance** (LR-MASK-SUBJECT / SKY / PEOPLE / OBJECTS, LR-EDIT-DETAIL-DENOISE, SUPERRES, LENSBLUR):
|
||||
Object and Describe masks run SAM 3 in pure Rust (`crates/segment`); the weights (SAM License) are never bundled:
|
||||
the app offers a consented, verified download, but **LightCraft's CDN mirrors are not configured yet** (the
|
||||
built-in list is empty, so today users need their own mirror or a manual install). Subject / Sky / People could
|
||||
use the same model with fixed prompts; denoise / super-resolution models remain a maintainer decision.
|
||||
7. **HDR** (Q. HDR, LR-EXP-HDR), **video** (R. Video), **Classic output modules** (Map view, Book, Slideshow module,
|
||||
Print, publish): large, well understood, lower priority than 1–5. Contact-sheet PDF export now covers a
|
||||
basic Print workflow; custom picture packages, printer integration and print colour management remain open.
|
||||
8. **LR-VIEW-ZOOM** (P0): pinch zoom and two-finger pan now work, with stable image cursors between gesture events.
|
||||
The whole-image preview is still capped by
|
||||
Settings → Performance → Preview size (2,560 px by default). Render visible regions at native resolution so
|
||||
100% can reliably show original-pixel detail on larger photos.
|
||||
|
||||
Recognition runtime gap closed (LR-PREF-PEOPLE): the pinned SFace and AuraFace models now run on the shared pure-Rust
|
||||
CPU engine and agree with an independent reference runtime on public crops. Live-face threshold calibration, small-face
|
||||
coverage and separated clusters remain open; see [faces.md](faces.md).
|
||||
|
||||
## Shortcuts: conflicts and missing bindings
|
||||
|
||||
Compared `plan/lightroom/06-shortcuts.md` (desktop part) with our bindings: command specs in `crates/engine/src/cmd/`,
|
||||
`UI_COMMANDS` in `crates/ui-egui/src/menus.rs` and secondary bindings (`ALIASES`) in `crates/ui-egui/src/shortcuts.rs`.
|
||||
`no_conflicting_bindings` (same file) fails when one key fires two actions.
|
||||
|
||||
**Fixed (M16.1):** added Lightroom-desktop keys as secondary bindings for existing commands — ⌘D Select None, ⇧E
|
||||
Export dialog, Space Toggle zoom, ⇧M Create Version, ⇧X Reject + advance, ⇧U Unflag + advance. `⇧Y` fired both
|
||||
Before/After Split and the History panel; History lost the binding. `W` and `⇧⌘I` also fired the engine command
|
||||
under the UI command that wraps it (a no-op error); the UI command now wins.
|
||||
|
||||
**Deliberate differences (our key → Lightroom desktop key)** — each is a conflict with another binding we have:
|
||||
|
||||
| Action | Ours | Lightroom desktop | Why |
|
||||
|---|---|---|---|
|
||||
| Pick flag | P | Z | Z = toggle zoom (Classic convention); P is the Classic pick key |
|
||||
| Photos panel (left) | ⌘⇧L | P | P = pick |
|
||||
| Expand/collapse edit sections | ⌘⌥1–5 | ⌘1–6 | ⌘0 = Zoom to Fit, ⌘1 = Zoom 100 %; Geometry lives in the Crop panel |
|
||||
| Histogram | ⌘⇧H | ⌘0 | ⌘0 = Zoom to Fit |
|
||||
| Square Grid | ⇧G | (none; ⇧G = Guided Upright) | Guided Upright is a button in the Crop panel |
|
||||
| Export dialog | ⌘⇧E (+ ⇧E) | ⇧E | ⌘⇧E is "Edit in Photoshop" there; no external-editor command yet |
|
||||
| Crop overlay cycle | ⇧O | O | O = mask overlay; ⇧O (mask colour / overlay orientation) unused otherwise |
|
||||
| Create Version | ⌘⇧S (+ ⇧M) | ⇧M (Windows: Ctrl+⇧S) | — |
|
||||
| Select None | ⌘⇧A (+ ⌘D) | ⌘D | — |
|
||||
|
||||
**Library culling (KEYC-RATING):** `0–5`, `6–9` and `P/X/U` reach egui on macOS even when displayed in the native menu (adapted from PR #261; issue #283). `Shift+0–9` applies and advances once; `Shift+P` picks and advances in Photo Grid / Square Grid and retains Presets elsewhere. See [library shortcuts](library-shortcuts.md) for the verified Classic mapping and regression coverage. Remaining Classic gaps: rating `[` / `]`, flag cycling and filter-bar keys.
|
||||
|
||||
**Still missing / broken:**
|
||||
- No command yet: F1 help (verify the rest of the old list: full screen, settings, stacks,
|
||||
visualize spots and merges have commands now).
|
||||
- `H` opens Remove; Lightroom also uses it (Classic) to hide pins — pins toggle from View → Show Mask Pins.
|
||||
- ⌘M / ⌘H / ⌘Q / ⌘W rely on the platform window defaults (unverified).
|
||||
Moved on 2026-10-10: the ranked gaps are in [gaps.md](gaps.md); shortcut conflicts, deliberate
|
||||
differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
|
||||
|
||||
<!-- Sections below hold one row per id. Keep the column order: Id | Feature | Tier | Status | Evidence | Notes. -->
|
||||
|
||||
@@ -644,7 +578,7 @@ visible menu bar yet: the menu model is only exposed through the control channel
|
||||
## Z. Keyboard shortcuts (desktop)
|
||||
|
||||
From `06-shortcuts.md` part 1. Evidence is our binding; conflicts are explained in
|
||||
[Shortcuts: conflicts and missing bindings](#shortcuts-conflicts-and-missing-bindings).
|
||||
[UI parity → Shortcuts](ui-parity.md#shortcuts).
|
||||
|
||||
| Id | Feature | Tier | Status | Evidence | Missing / notes |
|
||||
|---|---|---|---|---|---|
|
||||
@@ -837,3 +771,10 @@ dialog offers Horizontal/Vertical and multiline text. Japanese glyphs fall back
|
||||
Mincho faces (BIZ UDMincho; on the web build, BIZ UDPGothic) when built with `CRAFT_FONTS_DIR`. Vertical lettering uses upright em cells and right-to-left newline columns;
|
||||
Latin stays upright. Advanced Japanese composition remains open. Regression coverage:
|
||||
`export::tests::japanese_watermarks_support_vertical_columns`, `japanese_watermark_options_and_legacy_defaults`, `watermarks_work_without_craft_fonts`.
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | minor | Renamed from `parity.md` (progress-docs standard); Top gaps moved to gaps.md (its duplicated items 1–2 from a bad merge resolved there), shortcut notes moved to ui-parity.md. Rows unchanged; a recount of the rows gives 81.1% of 517 in-scope rows (P0 98.0%, P1 95.1%, P2 46.9%), so the generated summary above is due a `cargo xtask parity --write` |
|
||||
| 2026-09-30 – 2026-10-10 | — | Rows added and updated with each feature (see `git log -- docs/parity.md docs/parity-checklist.md`) |
|
||||
@@ -32,7 +32,7 @@ Today there is one process, **V1**: LightCraft's rendering from before process v
|
||||
passing: settings saved without the field must stay V1, not become the new latest. That is the
|
||||
field's `#[serde(default = "ProcessVersion::legacy")]`; the struct-level `Default` gives new
|
||||
settings the latest instead.
|
||||
4. Render a few procedural scenes on both processes and compare, and update `docs/parity.md`.
|
||||
4. Render a few procedural scenes on both processes and compare, and update `docs/parity-checklist.md`.
|
||||
|
||||
## What gets which process
|
||||
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
# 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)
|
||||
|
||||
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
|
||||
model. The numbers feed [target-app-parity.md](target-app-parity.md); individual shortfalls are
|
||||
ranked in [gaps.md](gaps.md). Details per format: [cr3.md](cr3.md),
|
||||
[raf-compression.md](raf-compression.md), [sony-lens-corrections.md](sony-lens-corrections.md),
|
||||
[camera-preview-colour.md](camera-preview-colour.md), [denoise.md](denoise.md).
|
||||
|
||||
## Headline
|
||||
|
||||
| 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) |
|
||||
| **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 |
|
||||
| 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) |
|
||||
|
||||
Re-measure with `python3 docs/raw/coverage.py` (standard library only): it classifies every Adobe
|
||||
model from the format rules in the script (which mirror `crates/raw/src`) plus the per-model evidence,
|
||||
rewrites [raw/coverage.tsv](raw/coverage.tsv) and prints the tables below; `--check` fails when the
|
||||
committed table is stale.
|
||||
|
||||
## How it was measured
|
||||
|
||||
- **Adobe's list**: helpx "Camera Raw supported cameras" (the live page refuses scripted requests, so
|
||||
the Wayback Machine capture of 2026-10-03 was parsed): 1,446 camera rows from 40 makers after
|
||||
dropping profile-only rows; maker, model, extension(s), Camera Matching profile, minimum Camera Raw
|
||||
version. The year a model was added is approximated from that Camera Raw major version.
|
||||
- **What we decode**: the decoders and their refusals in `crates/raw/src` (`lib.rs` routing, `vendor/*.rs`
|
||||
coding variants, `crx.rs` CRX limits, `orf.rs` / `srw.rs` compressed refusals), the import list
|
||||
`lightcraft_engine::import::EXTENSIONS`, and `KNOWN_UNSUPPORTED` in `crates/raw/tests/corpus.rs`. Doc
|
||||
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
|
||||
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
|
||||
raw.pixls.us folder names. Checks without a body list (≈ 60 NEFs, 35 CR2 bodies for the CFA layout)
|
||||
are not counted as verified.
|
||||
- **Usage weights** ([raw/usage-weights.tsv](raw/usage-weights.tsv)): maker buckets from 2025 market
|
||||
data (Nikkei production: Canon ~36%, Sony ~29%, Nikon ~14%, Fujifilm ~12% of mirrorless; BCN retail:
|
||||
Sony 29.9%, Canon 27.4%, Nikon 15.1%), adjusted for the DSLR installed base and for the makers named
|
||||
in this repo's 325 user issues (Sony 33, Nikon 31, Canon 26, phones 23, Fujifilm 9, Panasonic / Leica
|
||||
8, OM / Olympus 6, Pentax / Ricoh 6). Inside each bucket, 80% goes to the popular bodies of the last
|
||||
~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).
|
||||
|
||||
## 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 |
|
||||
| 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 | — |
|
||||
| Nikon | 99 | 5 | 94 | 0 | 0 | — (HE / HE★ is a per-shot setting, preview-only) |
|
||||
| Fujifilm | 97 | 16 | 55 | 26 | 0 | pre-X FinePix RAF without a raw IFD (estimated split) |
|
||||
| Google | 88 | 1 | 87 | 0 | 0 | — |
|
||||
| Olympus | 71 | 3 | 9 | 59 | 0 | **compressed ORF** |
|
||||
| Leica | 61 | 13 | 48 | 0 | 0 | — |
|
||||
| Xiaomi, Oppo, LG, Huawei, OnePlus, Motorola, Nokia | 139 | 0 | 139 | 0 | 0 | — (DNG) |
|
||||
| Pentax / Ricoh | 60 | 4 | 56 | 0 | 0 | — |
|
||||
| Hasselblad | 34 | 0 | 2 | 32 | 0 | Hasselblad-compressed 3FR / FFF |
|
||||
| Phase One / Leaf / Mamiya | 59 | 0 | 0 | 43 | 16 | IIQ, MOS preview; TIFF raws and MEF not imported |
|
||||
| Casio | 26 | 0 | 26 | 0 | 0 | — (DNG) |
|
||||
| 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%)** | |
|
||||
|
||||
## 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 |
|
||||
| Sony | 27% | 98% | 91% | bulk-checked |
|
||||
| Nikon | 16% | 91% | 12% | decoders cover every NEF coding but HE; few bodies verified |
|
||||
| Fujifilm | 10% | 91% | 45% | |
|
||||
| Panasonic | 4% | 100% | 98% | bulk-checked |
|
||||
| OM / Olympus | 3% | 3% | 1% | compressed ORF |
|
||||
| Phones | 3% | 93% | 1% | DNG |
|
||||
| Pentax / Ricoh | 1.5% | 94% | 14% | |
|
||||
| Leica | 1% | 95% | 5% | |
|
||||
| DJI | 1% | 95% | 0% | |
|
||||
| Medium format and others | 0.5% | 23% | 0% | IIQ, 3FR, X3F |
|
||||
| **Weighted** | 100% | **84%** | **40%** | |
|
||||
|
||||
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.
|
||||
|
||||
## Variant matrix (depth per format)
|
||||
|
||||
✅ decoded and checked on real files · 🟡 decoded, partial or unverified · ⬜ preview-only or refused.
|
||||
|
||||
| Format | Variant | Status | Evidence |
|
||||
|---|---|---|---|
|
||||
| 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 | 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 |
|
||||
| CR3 | dual-pixel raw | ⬜ | never substituted |
|
||||
| CRW | all | ⬜ | preview |
|
||||
| NEF | uncompressed, lossless, lossy type 1 / 2, lossy after split | ✅ | D5100, D7000, D7500, Z f corpus; ~60 NEFs by hand; #633 |
|
||||
| NEF | packed 14-bit stored under a compressed tag (Z 6II uncompressed) | ⬜ | #769; fix in PR #671 (not merged) |
|
||||
| NEF | High Efficiency / HE★ (JPEG XS) | ⬜ | named, preview (#193); needs a JPEG XS decoder |
|
||||
| ARW | uncompressed, cRAW (ARW2), lossless LJ92 (L / M / S) | ✅ | 86 bodies (#535); M/S black level 1024 |
|
||||
| ARW | packed 12-bit (A900) | ✅ | one CC0 file; A850 unmeasured |
|
||||
| ARW | 12-bit compressed of DSLR-A200…A390 | ⬜ | preview (#535) |
|
||||
| ARW | A100 ARW; SRF (F828, V3) | ⬜ | refused (#702); SRF not imported |
|
||||
| ARW | ARQ pixel shift | ⬜ | no code |
|
||||
| SR2 | DSC-R1 | ✅ | CC0 3221 sample |
|
||||
| RAF | uncompressed, lossless and lossy compressed; Bayer and X-Trans; GFX 14/16-bit | ✅ | 24 files from 13 bodies exact |
|
||||
| RAF | pre-X FinePix without a raw IFD | ⬜ | `raf.rs` refuses (26 Adobe models, estimated split) |
|
||||
| ORF | uncompressed 16-bit, 12-bit packed, two-field 12-bit, 12.8 bpp | ✅ | E-1, E-400, XZ-2 corpus; #651 |
|
||||
| ORF | **compressed** (every Olympus / OM body since ~2008) | ⬜ | `orf.rs` refuses; the E-M1 and E-M10 III corpus files are `KNOWN_UNSUPPORTED` |
|
||||
| RW2 / RWL / RAW | formats 2, 4, 5, 6, 7, 8 and 16-bit words | ✅ | 118 bodies (#215) |
|
||||
| PEF | uncompressed, Huffman, packed 12-bit | ✅ | K10D, K-3, K-5 IIs |
|
||||
| PEF / DNG | Pentax pixel shift | ⬜ | frames not combined |
|
||||
| SRW | uncompressed, 12-bit packed | ✅ | EX1 corpus; NX10, NX20 |
|
||||
| SRW | compressed 32770 / 32772 / 32773 | ⬜ | refused |
|
||||
| DNG | uncompressed, LJ92, lossy JPEG / Smart Preview, Deflate incl. float, LinearRaw, tiles / strips, row / column interleave | ✅ | 6 corpus DNGs; 4 ILCE-6400 JXL DNGs |
|
||||
| DNG | JPEG XL (DNG 1.7, lossless and lossy) | ✅ | synthetic bit-exact; real lossless and lossy files |
|
||||
| DNG | Apple ProRAW (incl. semantic mattes) | ✅ | iPhone 12 Pro corpus; ProfileGainTableMap read but off (ΔE00 19 against Lightroom with it on) |
|
||||
| DNG | phone DNGs (Pixel, Galaxy, Xiaomi…) | 🟡 | Pixel 2 XL only; white-level pile-up fix #548 |
|
||||
| DNG | GoPro GPR (VC-5) | ⬜ | refused |
|
||||
| 3FR / FFF | DNG-like layouts | 🟡 | decoded when uncompressed or LJ92 |
|
||||
| 3FR / FFF | Hasselblad compression | ⬜ | preview |
|
||||
| IIQ, MOS, MRW, ERF, KDC, X3F | all | ⬜ | preview |
|
||||
| DCR, MEF, MFW, DXO, GPR, TIFF raws | all | ⬜ | not imported |
|
||||
|
||||
## Demosaic, levels, crops and lens metadata
|
||||
|
||||
| Stage | Target | LightCraft | Status |
|
||||
|---|---|---|---|
|
||||
| Bayer demosaic | Adobe's own, plus AI "Raw Details" | AHD (default), PPG, bilinear (`crates/raw/src/demosaic`) | 🟡 quality unmeasured against Lightroom; no Raw Details |
|
||||
| X-Trans demosaic | ✅ | in-house edge-weighted directional | 🟡 unmeasured |
|
||||
| Foveon | ✅ (older bodies) | — | ⬜ |
|
||||
| Monochrome / LinearRaw | ✅ | handled, no demosaic | ✅ |
|
||||
| Pixel shift (Sony ARQ, Pentax, OM high-res, Nikon) | ✅ (Sony, Pentax, Nikon) | — | ⬜ |
|
||||
| Black and white levels | per model, calibrated | read from each file (masked columns, maker notes, SR2SubIFD, CMP1) | 🟡 per-body bugs keep surfacing: A450–A700 SR2 black level and M/S ARW pedestal (#535, fixed); 5D Mark IV CR2 renders dark (#455, open); white-level pile-up in phone DNGs (#548, fixed) |
|
||||
| Crop masks and aspect | ✅ | DefaultCrop, Sony recorded size, Canon AspectInfo, Panasonic in-camera crops, Nikon CropArea | 🟡 7RM3 / 7RM4 crop origin 8–32 px off (cosmetic) |
|
||||
| Lens metadata | ✅ read for profile selection | EXIF lens fields read; used only for the in-file corrections below | 🟡 |
|
||||
| Highlight reconstruction | ✅ | neutral clip, chromaticity diffusion (`highlight.rs`) | 🟡 tuned by eye |
|
||||
| AI denoise | ✅ Bayer and X-Trans, model bundled | Bayer only, user-installed weights, pure-Rust CPU / GPU | 🟡 no X-Trans, no shippable weights |
|
||||
| Super Resolution | ✅ | — | ⬜ |
|
||||
| HDR / panorama merge to raw DNG | ✅ | linear DNG (float16 HDR) with the source's colour tags | ✅ |
|
||||
| Convert to DNG | ✅ | uncompressed or LJ92 tiles (`dngwrite.rs`) | ✅ (no lossy DNG) |
|
||||
|
||||
## Colour
|
||||
|
||||
| Item | Adobe | LightCraft |
|
||||
|---|---|---|
|
||||
| Default profile per model | Adobe Standard for every model (1,500 profile names in the bundle) | the DNG's own matrices; else a pooled profile (**4 bundled**: ILCE-7CR, ILCE-7M4, X-H2S, X-T4); else a guarded per-file fit to the camera's embedded JPEG; else spectral matrices (**52 models**, rawtoaces-data); else a neutral matrix |
|
||||
| Camera Matching looks | 481 models (plus phone-maker looks) | none (the per-file JPEG fit imitates the camera's own look) |
|
||||
| Creative profiles | Adobe Color, Portrait, Landscape, Vivid, Monochrome… | our own looks (Color, Neutral, Vivid, Landscape, Portrait, Monochrome) |
|
||||
| DCP / dual-illuminant model | ✅ | dual-illuminant DNG colour (ColorMatrix / ForwardMatrix 1-2, CameraCalibration, AnalogBalance), HueSatMap, LookTable, ProfileToneCurve; external `.dcp` never loaded (clean-room) |
|
||||
| White balance in Kelvin | ✅ for every model | absolute Kelvin only where matrices exist; per-file fits give relative WB (#296, #730) |
|
||||
|
||||
**How far the default rendering is from Adobe's** (CIE ΔE; measured where stated):
|
||||
|
||||
- Against the camera JPEG (what the fit targets): the Sony bulk check (#535) accepted fits on 81 of 87
|
||||
bodies, median ΔE 5.1, ΔL\* +0.2; rejected fits fall back to a neutral matrix at median ΔE 18.5,
|
||||
ΔL\* −11, chroma ×0.39. RW2 140 of 174 files accepted, median 5.0. NEF 13 of 13, 2.9–7.8. RAF 23 of
|
||||
24, pooled X-H2S 1.62 / X-T4 2.34. SRW 2.2–7.6.
|
||||
- Against Lightroom itself (few): Sony DRO median ΔE76 7.5 → 3.3; Olympus E-1 vs Lightroom Classic
|
||||
ΔE00 11.25 → 8.30; ProRAW with its gain map ΔE00 19 (why the map is off). No measurement against
|
||||
Adobe Standard across models exists.
|
||||
- User evidence: 33 open issues about raw colour or rendering (wrong colours, dark, flat, green,
|
||||
desaturated), the largest group of open core-path issues.
|
||||
|
||||
**Colour score ~35%** (estimated): most decoded files start close to the camera's own look (ΔE ~5),
|
||||
about 10% start far off (ΔE ~18), nothing is calibrated, Kelvin WB is missing for fitted cameras, and
|
||||
the distance to Adobe Standard is unmeasured. In the readiness numbers this becomes a colour factor
|
||||
of ×0.85 for a working photographer (they correct colour by hand, at a cost) and ×0.75 for the
|
||||
essentials user (the default look is what they keep).
|
||||
|
||||
## Lens profiles
|
||||
|
||||
| Item | Adobe | LightCraft |
|
||||
|---|---|---|
|
||||
| Profile database | 3,635 profile files, 56 makers, auto-selected | **0** (Adobe LCPs never used; no database of our own) |
|
||||
| In-file corrections | ✅ | DNG opcodes (WarpRectilinear, FixVignetteRadial, GainMap…) applied; Panasonic / Leica RW2 distortion (79 photos, 13 bodies, 11 lenses); Sony tag 0x7037 distortion for the ILCE-7RM4A (2 lenses) |
|
||||
| Vignetting / lateral CA from maker notes | ✅ | ⬜ |
|
||||
| Manual distortion, vignetting, CA, defringe | ✅ | ✅ |
|
||||
|
||||
**Lens score ~10%** (estimated): automatic correction reaches roughly Panasonic / Leica, phone and
|
||||
drone DNG users (~9% of photographers by the weights above); Adobe reaches nearly everyone.
|
||||
|
||||
## Scores
|
||||
|
||||
| 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) |
|
||||
| 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 |
|
||||
|
||||
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
|
||||
the written decomposition, not new decoding.
|
||||
|
||||
## Remaining work, ranked by photographers unlocked per hour
|
||||
|
||||
Hours are Opus 5.5 agent hours, calibrated on this repo's raw PRs: RW2 every format 6.5 h (#215),
|
||||
compressed RAF 8.6 h (#282), CR3 CRX 10 h (#279), NEF lossy after split 4.7 h (#633), ORF 12.8 bpp
|
||||
1.7 h (#651), HEIC 7 h (#609). "Gain" is the change in the use-weighted share whose camera fully
|
||||
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) |
|
||||
| 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 |
|
||||
| 6 | Pre-X FinePix RAF | +0.6 | 4–8 | ~0.08 | samples |
|
||||
| 7 | Sony A100 and DSC-F828 regression (#702) | +0.1 | 1–2 | ~0.07 | samples on raw.pixls.us |
|
||||
| 8 | Canon CRW (2000–2004 bodies) | +1.2 by the uniform tail weight, far less by real use | 6–12 | ≤ 0.1 | samples |
|
||||
| 9 | Nikon HE / HE★ NEF (Z 8, Z 9, Z 6III, Z f, Z50II, Z5II set to HE) | +1.1 | 20–40 | ~0.04 | a pure-Rust JPEG XS decoder |
|
||||
| 10 | Compressed SRW, Hasselblad 3FR, IIQ, X3F, MRW, KDC, ERF, DCR, MEF, GPR | +0.6 together | 45–85 | ~0.01 | samples; low use |
|
||||
|
||||
Beyond decoding:
|
||||
|
||||
| Gap | Hours | Needs |
|
||||
|---|---:|---|
|
||||
| Measured colour calibration for the ~60 popular bodies, Kelvin WB, render-fidelity suite against Lightroom | 80–150 | chart shots per camera (a human with cameras) or licensable measured data |
|
||||
| Lens profile database of our own (fitting tools, data format, top 100 lenses), maker-note vignetting / CA | 40–80 | calibration shots (a human with lenses) |
|
||||
| Demosaic and highlight quality measured against Lightroom; X-Trans AI denoise | 15–30 | |
|
||||
| **Total RAW** | **255–480 h** (decoding list above 120–220 h; ~60% parallelizes) | |
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 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 |
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Measure LightCraft's raw camera coverage against Adobe's supported-camera list.
|
||||
|
||||
python3 docs/raw/coverage.py # print the summary, rewrite docs/raw/coverage.tsv
|
||||
python3 docs/raw/coverage.py --check # exit 1 if coverage.tsv is stale
|
||||
|
||||
Inputs (all in docs/raw/):
|
||||
adobe-cameras.tsv Adobe's published list (maker, camera, extensions, ...).
|
||||
evidence.tsv per-model evidence: verified decodes, known preview-only or refused bodies.
|
||||
usage-weights.tsv estimated share of photographers per maker bucket and popular bodies.
|
||||
|
||||
Every Adobe-listed model gets one class:
|
||||
verified decoded from sensor data, and a real file from this body was checked (evidence.tsv)
|
||||
unverified the decoder path for its format and coding should handle it; no sample checked
|
||||
preview opens as the embedded JPEG (format or coding not decoded)
|
||||
unsupported not imported, refused, or decodes wrongly
|
||||
|
||||
The format rules below mirror the decoders in crates/raw/src (see docs/raw-parity.md). When a decoder
|
||||
changes, update the rules and evidence, rerun, and commit coverage.tsv with the docs.
|
||||
Standard library only; no third-party packages.
|
||||
"""
|
||||
|
||||
import csv
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# Olympus ORF bodies that write uncompressed / packed data (crates/raw/src/vendor/orf.rs). Everything else
|
||||
# writes compressed ORF, which is preview-only (the E-M5 II / PEN-F high-res mode alone is decoded).
|
||||
ORF_DECODED = re.compile(r"^(E-1|E-10|E-20|EVOLT E-300|EVOLT E-330|EVOLT E-400|EVOLT E-500|E-300|E-330|E-500|Camedia C-\S+.*|Stylus XZ-2 iHS)$")
|
||||
# Samsung SRW bodies with compressed raw data (crates/raw/src/vendor/srw.rs refuses 32770 / 32772 / 32773).
|
||||
SRW_COMPRESSED = re.compile(r"(^|\W)(NX1|NX30|NX300|NX300M|NX500|NX2000|NX3000|NX3300|NX mini|EK-GN\d+|EK-KN\d+)(\W|$)")
|
||||
# Fujifilm bodies before the X series whose RAF has no raw IFD (crates/raw/src/vendor/raf.rs).
|
||||
RAF_OLD = re.compile(r"^(FinePix (E|F|S\d|S\d{3,4}|IS)|IS Pro|S5Pro|S3Pro|S2Pro)", re.I)
|
||||
|
||||
# Probability that an unverified body of a format decodes correctly, used for the use-weighted share only.
|
||||
CONFIDENCE = {"DNG": 0.95, "CR2": 0.95, "CR3": 0.6, "NEF": 0.9, "NRW": 0.9, "ARW": 0.9, "SR2": 0.8, "RAF": 0.95,
|
||||
"RW2": 0.95, "RWL": 0.95, "RAW": 0.95, "PEF": 0.9, "ORF": 0.8, "SRW": 0.8}
|
||||
|
||||
|
||||
def read_tsv(name):
|
||||
with open(os.path.join(HERE, name), newline="", encoding="utf-8") as f:
|
||||
lines = [line for line in f if not line.startswith("#")]
|
||||
return list(csv.DictReader(lines, delimiter="\t"))
|
||||
|
||||
|
||||
def exts(field):
|
||||
return [e.strip().upper() for e in re.split(r"[,/+]", re.sub(r"\(.*?\)", "", field)) if e.strip()]
|
||||
|
||||
|
||||
def classify(maker, camera, ext_field):
|
||||
"""(class, format, reason) from the format rules alone."""
|
||||
es = exts(ext_field)
|
||||
for e in es:
|
||||
if e == "DNG":
|
||||
return "unverified", "DNG", "DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)"
|
||||
if e == "CR2":
|
||||
return "unverified", "CR2", "CR2 lossless JPEG decoder"
|
||||
if e == "CR3":
|
||||
return "unverified", "CR3", "CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview"
|
||||
if e in ("NEF", "NRW"):
|
||||
return "unverified", e, "NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only"
|
||||
if e == "ARW":
|
||||
return "unverified", "ARW", "ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)"
|
||||
if e == "SR2":
|
||||
return "unverified", "SR2", "SR2 decoder"
|
||||
if e == "RAF":
|
||||
if RAF_OLD.search(camera):
|
||||
return "preview", "RAF", "pre-X FinePix RAF without a raw IFD"
|
||||
return "unverified", "RAF", "RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)"
|
||||
if e in ("RW2", "RWL") or (e == "RAW" and maker in ("Panasonic", "Leica")):
|
||||
return "unverified", e, "Panasonic decoder, every raw format"
|
||||
if e == "PEF":
|
||||
return "unverified", "PEF", "PEF decoder (uncompressed, Huffman, packed 12-bit)"
|
||||
if e == "ORF":
|
||||
if ORF_DECODED.match(camera):
|
||||
return "unverified", "ORF", "uncompressed / packed ORF"
|
||||
return "preview", "ORF", "compressed ORF is not decoded"
|
||||
if e == "SRW":
|
||||
if SRW_COMPRESSED.search(camera):
|
||||
return "preview", "SRW", "compressed SRW is not decoded"
|
||||
return "unverified", "SRW", "uncompressed / packed SRW"
|
||||
e = es[0] if es else ""
|
||||
if e in ("CRW", "3FR", "FFF", "IIQ", "MOS", "ERF", "KDC", "MRW", "X3F", "RAW", "ORI"):
|
||||
return "preview", e, f"{e} is opened from its embedded JPEG only"
|
||||
return "unsupported", e, f"{e or 'unknown'} is not imported"
|
||||
|
||||
|
||||
def main():
|
||||
adobe = read_tsv("adobe-cameras.tsv")
|
||||
evidence = {(r["maker"], r["camera"]): r for r in read_tsv("evidence.tsv")}
|
||||
rows = []
|
||||
for a in adobe:
|
||||
cls, fmt, reason = classify(a["maker"], a["camera"], a["extensions"])
|
||||
ev = evidence.get((a["maker"], a["camera"]))
|
||||
if ev:
|
||||
cls, reason = ev["status"], ev["source"]
|
||||
rows.append({"maker": a["maker"], "camera": a["camera"], "format": fmt, "year_added": a["year_added"], "class": cls, "reason": reason})
|
||||
|
||||
out = os.path.join(HERE, "coverage.tsv")
|
||||
header = ["maker", "camera", "format", "year_added", "class", "reason"]
|
||||
text = "# Generated by docs/raw/coverage.py; do not edit.\n" + "\t".join(header) + "\n"
|
||||
text += "".join("\t".join(r[k] for k in header) + "\n" for r in rows)
|
||||
if "--check" in sys.argv:
|
||||
with open(out, encoding="utf-8") as f:
|
||||
if f.read() != text:
|
||||
print("docs/raw/coverage.tsv is stale: run python3 docs/raw/coverage.py")
|
||||
return 1
|
||||
else:
|
||||
with open(out, "w", encoding="utf-8") as f:
|
||||
f.write(text)
|
||||
|
||||
classes = ["verified", "unverified", "preview", "unsupported"]
|
||||
by_maker = {}
|
||||
for r in rows:
|
||||
by_maker.setdefault(r["maker"], {c: 0 for c in classes})[r["class"]] += 1
|
||||
print("| Maker | Adobe models | verified | unverified | preview | unsupported |")
|
||||
print("|---|---:|---:|---:|---:|---:|")
|
||||
for m, c in sorted(by_maker.items(), key=lambda kv: -sum(kv[1].values())):
|
||||
print(f"| {m} | {sum(c.values())} | " + " | ".join(str(c[k]) for k in classes) + " |")
|
||||
tot = {k: sum(c[k] for c in by_maker.values()) for k in classes}
|
||||
n = sum(tot.values())
|
||||
print(f"| **All** | **{n}** | " + " | ".join(f"**{tot[k]}** ({100 * tot[k] / n:.0f}%)" for k in classes) + " |")
|
||||
recent = [r for r in rows if r["year_added"] and int(r["year_added"]) >= 2017]
|
||||
rc = {k: sum(1 for r in recent if r["class"] == k) for k in classes}
|
||||
print(f"\nModels added since 2017 (ACR 10+): {len(recent)}: " + ", ".join(f"{k} {rc[k]}" for k in classes))
|
||||
|
||||
# Use-weighted share of photographers whose camera fully works (decodes from sensor data).
|
||||
weights = read_tsv("usage-weights.tsv")
|
||||
by_cam = {(r["maker"], r["camera"]): r for r in rows}
|
||||
total = works = verified_share = 0.0
|
||||
print("\n| Bucket | Weight | Camera fully works | of which verified bodies |")
|
||||
print("|---|---:|---:|---:|")
|
||||
for b in [w for w in weights if w["kind"] == "maker"]:
|
||||
makers = b["makers_or_camera"].split(",")
|
||||
popular = [w["makers_or_camera"] for w in weights if w["kind"] == "body" and w["bucket"] == b["bucket"]]
|
||||
members = [r for r in rows if r["maker"] in makers]
|
||||
pop_rows = [r for m in makers for (mk, cam), r in by_cam.items() if mk == m and cam in popular]
|
||||
missing = set(popular) - {r["camera"] for r in pop_rows}
|
||||
if missing:
|
||||
print(f"usage-weights.tsv: unknown cameras {sorted(missing)}", file=sys.stderr)
|
||||
return 1
|
||||
rest = [r for r in members if r["camera"] not in popular]
|
||||
|
||||
def score(r):
|
||||
if r["class"] == "verified":
|
||||
return 1.0
|
||||
if r["class"] == "unverified":
|
||||
return CONFIDENCE.get(r["format"], 0.7)
|
||||
return 0.0
|
||||
|
||||
def mean(rs, f):
|
||||
return sum(f(r) for r in rs) / len(rs) if rs else 0.0
|
||||
|
||||
if pop_rows:
|
||||
s = 0.8 * mean(pop_rows, score) + 0.2 * mean(rest, score)
|
||||
v = 0.8 * mean(pop_rows, lambda r: r["class"] == "verified") + 0.2 * mean(rest, lambda r: r["class"] == "verified")
|
||||
else:
|
||||
s, v = mean(members, score), mean(members, lambda r: r["class"] == "verified")
|
||||
w = float(b["weight"])
|
||||
total += w
|
||||
works += w * s
|
||||
verified_share += w * v
|
||||
print(f"| {b['bucket']} | {w:g}% | {100 * s:.0f}% | {100 * v:.0f}% |")
|
||||
print(f"| **Weighted** | {total:g}% | **{100 * works / total:.0f}%** | **{100 * verified_share / total:.0f}%** |")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,249 @@
|
||||
# Per-model evidence that overrides the format rules in coverage.py. status: verified | preview | unsupported.
|
||||
# "verified" means a real file from this body decoded from sensor data in a corpus test or a recorded bulk check (source column).
|
||||
maker camera status source
|
||||
Apple iPhone 12 Pro Rear Wide Camera verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 40D verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 550D (EOS Digital Rebel T2i, EOS Kiss X4 Digital) verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 5D Mark II verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 5DS R verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 6D verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
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 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)
|
||||
Fujifilm GFX 100RF (Final Support) verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm GFX 100S verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm GFX 50S verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-A2 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-A5 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-E1 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-E5 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-H2 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-H2S verified docs/raf-compression.md (supplied files, exact sensor arrays)
|
||||
Fujifilm X-M5 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T2 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T20 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T4** verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T5 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T50 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Google Pixel 2 XL verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Leica C (Typ 112) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica D-Lux (Typ 109) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica D-Lux 3 verified PR #215: raw.pixls.us bulk check of every RW2 / RWL / RAW body
|
||||
Leica D-Lux 4 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica D-Lux 5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica D-Lux 6 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica D-Lux 7 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica Digilux 2 verified PR #215: raw.pixls.us bulk check of every RW2 / RWL / RAW body
|
||||
Leica Digilux 3 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica V-LUX (Typ 114) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica V-LUX 1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica V-LUX 4 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica V-LUX 5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Nikon COOLPIX B700 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon D5100 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon D7000 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon D7500 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon Z f verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Olympus E-1 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Olympus EVOLT E-400 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Olympus Stylus XZ-2 iHS verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Panasonic LUMIX DC - G97 (DC-G99M2) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-FZ1000M2 (DC-FZ10002) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-FZ80 (DC-FZ82, DC-FZ85) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-G100 (DC-G110) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-G100D verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-G9 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-G95D verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-G99 (DC-G90, DC-G91, DC-G95) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GF10 (DC-GF90) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GF9 (DC-GX850, DC-GX800) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GH5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GH5M2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GH5s verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GH6 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GH7 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GX880 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-GX9 (DC-GX7MK3) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-LX100 II verified PR #215: raw.pixls.us bulk check of every RW2 / RWL / RAW body
|
||||
Panasonic LUMIX DC-S1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S1H verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S1M2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S1M2ES (Final Support) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S1R verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S1RM2 (Final Support) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S5M2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S5M2X verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-S9 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-TX2D (DC-TZ200D, DC-TZ202D, DC-TZ220D, DC-ZS200D, DC-ZS220D) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-ZS70 (DC-TZ90, DC-TZ91, DC-TZ92, DC-TZ93) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-ZS80 (DC-TZ95, DC-TZ96, DC-TZ97) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-ZS80D (DC-TZ95D, DC-TZ96D) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DCG9M2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-CM1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FX150 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ100 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ1000 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ150 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ18 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ200 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ2500 (DMC-FZ2000, DMC-FZH1) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ28 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ30 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ300 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ330 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ35 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ38 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ40 (DMC-FZ45) verified PR #215: raw.pixls.us bulk check of every RW2 / RWL / RAW body
|
||||
Panasonic LUMIX DMC-FZ50 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ70 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ72 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-FZ8 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G10 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G3 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G6 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G7 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-G8 (DMC-G80, DMC-G81, DMC-G85) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GF1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GF2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GF3 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GF5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GF6 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GF7 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GF8 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GH1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GH2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GH3 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GH4 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GM1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GM1S verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GM5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GX1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GX7 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GX8 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-GX85 (DMC-GX80, DMC-GX7MK2) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-L1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-L10 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LF1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LX1 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LX100 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LX2 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LX3 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LX5 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LX7 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-LX9 (DMC-LX10, DMC-LX15) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-ZS100 (DMC-ZS110, DMC-TZ100, DMC-TZ101, DMC-TZ110, DMC-TX1) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-ZS40 (DMC-TZ60, DMC-TZ61) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-ZS50 (DMC-TZ70, DMC-TZ71) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DMC-ZS60 (DMC-TZ80, DMC-TZ81, DMC-TZ85) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX ZS200 (DC-TX2, DC-TZ200, DC-TZ202, DC-TZ220, DC-ZS220) verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Pentax K-3 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Pentax K-5 IIs verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Pentax K10D verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Ricoh GR III verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Samsung TL500 (EX1) verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Sony A100 (DSLR-A100) unsupported issue #702: regression, refused as not a readable photo
|
||||
Sony A200 (DSLR-A200) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A230 (DSLR-A230) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A290 (DSLR-A290) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A300 (DSLR-A300) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A3000 (ILCE-3000) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A33 (SLT-A33) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A330 (DSLR A330) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A35 (SLT-A35) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A350 (DSLR-A350) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A3500 (ILCE-3500) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A37 (SLT-A37) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A380 (DSLR-A380) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A390 (DSLR-A390) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A450 (DSLR-A450) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A500 (DSLR-A500) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A5000 (ILCE-5000) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A5100 (ILCE-5100) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A550 (DSLR-A550) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A55V (SLT-A55V) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies
|
||||
Sony A560 (DSLR-A560) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A57 (SLT-A57) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A58 (SLT-A58) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A580 (DSLR-A580) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A6000 (ILCE-6000) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A6100 (ILCE-6100) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A6300 (ILCE-6300) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A6400 (ILCE-6400) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A65 (SLT-A65) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A6500 (ILCE-6500) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A6600 (ILCE-6600) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A6700 (ILCE-6700) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A68 (ILCA-68) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7 (ILCE-7) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7 II (ILCE-A7M2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies
|
||||
Sony A7 III (ILCE-7M3) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7 IV (ILCE-7M4) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A700 (DSLR-A700) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A77 (SLT-A77) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A77 II (ILCA-77M2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7C (ILCE-7C) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7C II (ILCE-7CM2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7CR (ILCE-7CR) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7R (ILCE-7R) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7R II (ILCE-7RM2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7R III (ILCE-7RM3) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7R IIIA (ILCE-7RM3A) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7R IV (ILCE-7RM4) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7R IVA (ILCE-7RM4A) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7R V (ILCE-7RM5) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7S (ILCE-7S) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7S II (ILCE-7SM2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7s III (ILCE-7SM3) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A850 (DSLR-A850) preview issue #535: preview-only on the raw.pixls.us sample
|
||||
Sony A9 (ILCE-9) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A9 II (ILCE-9M2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A9 III (ILCE-9M3) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A900 (DSLR-A900) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A99 (SLT-A99V) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies
|
||||
Sony A99 II (ILCA-99M2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony Alpha 1 (ILCE-1)* verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony DSC-F828 unsupported issue #702 (SRF refused); SRF not in the import list
|
||||
Sony DSC-HX95 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony DSC-HX99 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony DSC-V3 unsupported SRF not in the import list
|
||||
Sony FX3 (ILME-FX3) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony FX30 (ILME-FX30) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-3 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-3N verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-5 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-5N verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-5R verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-5T verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-6 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-7 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-C3 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-F3 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony QX1 (ILCE-QX1) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX0 (DSC-RX0) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX0 II (DSC-RX0M2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX1 (DSC-RX1) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX10 (DSC-RX10) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX10 II (DSC-RX10M2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX10 III (DSC-RX10M3) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX10 IV (DSC-RX10M4) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 (DSC-RX100) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 II (DSC-RX100M2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 III (DSC-RX100M3) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 IV (DSC-RX100M4) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 V (DSC-RX100M5) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 VA (DSC-RX100M5A) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 VI (DSC-RX100M6) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX100 VII (DSC-RX100M7) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX1R (DSC-RX1R) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony RX1R II (DSC-RX1RM2) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony ZV-1 (DCZV1/B) verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony ZV-E1 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony ZV-E10 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 3.
|
@@ -0,0 +1,114 @@
|
||||
# Estimated share of Lightroom raw photographers by camera maker, and the popular bodies of the last ~8 years inside each.
|
||||
# Sources (2026-10-10): Nikkei 2025 mirrorless production via PhotoRumors (Canon 2.3 M, Sony 1.8 M, Nikon 0.86 M, Fujifilm 0.75 M
|
||||
# units, i.e. ~36 / 29 / 14 / 12 % of CIPA's 6.31 M); BCN 2025 Japanese retail via PetaPixel (Sony 29.9 %, Canon 27.4 %, Nikon 15.1 %);
|
||||
# camera makers named in this repo's user issues (325 issues: Sony 33, Nikon 31, Canon 26, phones 23, Fujifilm 9, Panasonic/Leica 8,
|
||||
# OM/Olympus 6, Pentax/Ricoh 6, Samsung NX 5). Canon and Nikon get extra weight for their installed base of DSLRs.
|
||||
# Rows "maker" give the maker bucket's weight (percent of photographers); rows "body" give a popular body inside a bucket.
|
||||
# Inside a bucket, the listed bodies share 80 % equally and every other Adobe-listed model of the bucket's makers shares 20 %.
|
||||
kind bucket makers_or_camera weight
|
||||
maker Canon Canon 33
|
||||
maker Sony Sony 27
|
||||
maker Nikon Nikon 16
|
||||
maker Fujifilm Fujifilm 10
|
||||
maker Panasonic Panasonic 4
|
||||
maker OM / Olympus Olympus,OM Digital Solutions 3
|
||||
maker Phones Apple,Google,Samsung,Xiaomi,Huawei,Oppo,OnePlus,LG,Motorola,Nokia 3
|
||||
maker Pentax / Ricoh Pentax,Ricoh 1.5
|
||||
maker Leica Leica 1
|
||||
maker DJI DJI 1
|
||||
maker Medium format and others Hasselblad,Phase One,Leaf,Mamiya,Sigma,Kodak,Konica Minolta,Epson,Casio,GoPro,Insta360,Zeiss,Pixii,Light,Skydio,Parrot,Yuneec,Contax,DxO 0.5
|
||||
body Canon EOS R6 Mark II 1
|
||||
body Canon EOS R5 1
|
||||
body Canon EOS R6 1
|
||||
body Canon EOS R7 1
|
||||
body Canon EOS R8 1
|
||||
body Canon EOS R10 1
|
||||
body Canon EOS R50 1
|
||||
body Canon EOS RP 1
|
||||
body Canon EOS R (** see note) 1
|
||||
body Canon EOS R5 Mark II 1
|
||||
body Canon EOS R6 Mark III 1
|
||||
body Canon EOS R3 1
|
||||
body Canon EOS R100 1
|
||||
body Canon EOS 90D 1
|
||||
body Canon EOS M50 (EOS Kiss M) 1
|
||||
body Canon EOS M50 Mark II 1
|
||||
body Canon EOS M6 Mark II 1
|
||||
body Canon EOS-5D Mark IV (** see note) 1
|
||||
body Canon EOS 6D Mark II 1
|
||||
body Canon EOS 80D 1
|
||||
body Canon EOS 250D (EOS Rebel SL3, EOS 200D II, EOS Kiss X10) 1
|
||||
body Canon EOS 1500D (EOS Rebel T7, EOS Kiss X90, EOS 2000D) 1
|
||||
body Sony A7 IV (ILCE-7M4) 1
|
||||
body Sony A7 III (ILCE-7M3) 1
|
||||
body Sony A7R V (ILCE-7RM5) 1
|
||||
body Sony A7R IV (ILCE-7RM4) 1
|
||||
body Sony A7C (ILCE-7C) 1
|
||||
body Sony A7C II (ILCE-7CM2) 1
|
||||
body Sony A7CR (ILCE-7CR) 1
|
||||
body Sony A6400 (ILCE-6400) 1
|
||||
body Sony A6700 (ILCE-6700) 1
|
||||
body Sony A6600 (ILCE-6600) 1
|
||||
body Sony A6100 (ILCE-6100) 1
|
||||
body Sony Alpha 1 (ILCE-1)* 1
|
||||
body Sony A9 III (ILCE-9M3) 1
|
||||
body Sony ZV-E10 1
|
||||
body Sony A7s III (ILCE-7SM3) 1
|
||||
body Sony RX100 VII (DSC-RX100M7) 1
|
||||
body Nikon Z 6 II 1
|
||||
body Nikon Z 6 III 1
|
||||
body Nikon Z 8 1
|
||||
body Nikon Z 9 (*See note) 1
|
||||
body Nikon Z f 1
|
||||
body Nikon Z 5 1
|
||||
body Nikon Z 50 1
|
||||
body Nikon Z 50 II 1
|
||||
body Nikon Z fc 1
|
||||
body Nikon Z 7 II 1
|
||||
body Nikon D850 1
|
||||
body Nikon D750 1
|
||||
body Nikon D7500 1
|
||||
body Nikon D780 1
|
||||
body Fujifilm X-T5 1
|
||||
body Fujifilm X-T4** 1
|
||||
body Fujifilm X-S20 1
|
||||
body Fujifilm X-S10 1
|
||||
body Fujifilm X-H2S 1
|
||||
body Fujifilm X-H2 1
|
||||
body Fujifilm X100V** 1
|
||||
body Fujifilm X100VI 1
|
||||
body Fujifilm X-T30 II 1
|
||||
body Fujifilm X-E4 1
|
||||
body Fujifilm X-T50 1
|
||||
body Fujifilm GFX 100S 1
|
||||
body Fujifilm X-M5 1
|
||||
body Panasonic LUMIX DC-S5 1
|
||||
body Panasonic LUMIX DC-S5M2 1
|
||||
body Panasonic LUMIX DC-GH6 1
|
||||
body Panasonic LUMIX DC-GH5M2 1
|
||||
body Panasonic LUMIX DCG9M2 1
|
||||
body Panasonic LUMIX DC-G9 1
|
||||
body Panasonic LUMIX DC-S1 1
|
||||
body Panasonic LUMIX DC-GX9 (DC-GX7MK3) 1
|
||||
body Panasonic LUMIX DMC-G8 (DMC-G80, DMC-G81, DMC-G85) 1
|
||||
body Panasonic LUMIX DC-LX100 II 1
|
||||
body OM / Olympus OM-D E-M1 Mark III 1
|
||||
body OM / Olympus OM-D E-M1 Mark II 1
|
||||
body OM / Olympus OM-D E-M10 Mark IV 1
|
||||
body OM / Olympus OM-D E-M5 Mark III 1
|
||||
body OM / Olympus PEN E-P7 1
|
||||
body OM / Olympus Stylus Tough TG-6 1
|
||||
body OM / Olympus OM System OM-1 1
|
||||
body OM / Olympus OM System OM-1 MARK II 1
|
||||
body OM / Olympus OM System OM-5 1
|
||||
body Pentax / Ricoh K-1 II (* see note) 1
|
||||
body Pentax / Ricoh K-3 Mark III 1
|
||||
body Pentax / Ricoh KF 1
|
||||
body Pentax / Ricoh K-70 1
|
||||
body Pentax / Ricoh GR III 1
|
||||
body Pentax / Ricoh GR IIIx 1
|
||||
body Leica Q3 1
|
||||
body Leica Q2 1
|
||||
body Leica M11 1
|
||||
body Leica SL2 1
|
||||
body Leica M10 1
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 8.
|
+113
@@ -0,0 +1,113 @@
|
||||
# Roadmap: milestones, current focus and what's next
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created; milestones moved here from ROADMAP.md, focus re-ranked after the 2026-10-10 re-measure) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
|
||||
Forward-looking plan. The summary with the headline numbers is [ROADMAP.md](../ROADMAP.md); the
|
||||
ranked shortfalls are [gaps.md](gaps.md); the numbers come from [target-app-parity.md](target-app-parity.md).
|
||||
LightCraft has no `cargo xtask scorecard`; the measured checklist is
|
||||
[parity-checklist.md](parity-checklist.md) (`cargo xtask parity`).
|
||||
|
||||
## Current focus
|
||||
|
||||
Toward **beta** (~340–600 Opus 5.5 agent hours; ranked, each a gap in [gaps.md](gaps.md)):
|
||||
|
||||
1. **Camera colour of our own** (gap 1, 50–90 h): chart-based calibration for the most-used models,
|
||||
building on the per-file JPEG fits and pooled profiles (`lightcraft-cli calibrate`); never Adobe
|
||||
data.
|
||||
2. **CR3 for every Canon body** (gap 2, 25–45 h): the remaining CRX variants, sRAW / mRAW, HEIF CR3;
|
||||
clean-room from prose descriptions (decided 2026-10-05; compressed NEF is the template).
|
||||
3. **Render-fidelity suite** (gap 3, 30–60 h): score our output against Lightroom's on the same CC0
|
||||
raws (references local in `plan/`), then tune; a retune ships as a new process version.
|
||||
4. **Full-resolution zoom** (gap 4, 8–15 h): visible-region rendering so 100% shows original pixels.
|
||||
5. **AI masks** (gap 5, 40–70 h): Subject / Sky / People on licensable weights; configure the SAM 3
|
||||
mirror. Needs the maintainer's model decision.
|
||||
6. **Compressed ORF and HE NEF** (gaps 6–7, 28–55 h).
|
||||
7. **Lens profiles of our own** (gap 8, 40–80 h).
|
||||
8. **Tests in CI on macOS, Windows and Linux** (gap 9, 6–12 h).
|
||||
9. **Per-model verification** (gap 10, 20–35 h).
|
||||
|
||||
## Alpha gate
|
||||
|
||||
The target's core workflows: what a typical Lightroom user does every day. Alpha requires each to
|
||||
work end to end on the main platform (macOS) and the work to save and reopen. Checked on 2026-10-10
|
||||
against the code, tests, issues and [gaps.md](gaps.md).
|
||||
|
||||
| Workflow | Works end to end? | Evidence | Hours to pass |
|
||||
|---|---|---|---:|
|
||||
| 1. Import a shoot (raw + JPEG) from a card or folder into the library | yes | Add / Copy / Move import with templates, duplicates, devices with DCIM, background import with cancel (`crates/engine/src/import.rs`, `tests_import.rs`, `tests_import_move.rs`); checklist A 83% | 0 |
|
||||
| 2. Cull: rate, flag, label, compare / survey, filter, check focus | yes (partial: focus check) | ratings / flags / labels with advance, Compare, Survey ≤ 48, filter bar, smart albums (checklist B–D 88–92%); 100% zoom is capped by the preview size (2,560 px default, adjustable in Settings), gap 4 — degrades focus checks on large files but does not block culling | 0 (8–15 h to close gap 4, beta) |
|
||||
| 3. Develop raws non-destructively (global sliders, crop, masks, heal) | yes for most cameras (partial: Canon CR3 outside the verified variants, compressed ORF, HE NEF open as embedded previews) | Sony, Nikon (except HE), Fujifilm, Panasonic, Pentax, CR2, DNG decode from sensor data (raw-parity.md); every Edit slider, crop / Upright, brush / gradient / range masks, heal / clone (checklist F, H, K); colour estimated per file rather than measured, gaps 1–3 | 0 (coverage and colour gaps are beta blockers 1–3, 6–7) |
|
||||
| 4. Save, quit and reopen the work | yes | crash-safe journal + snapshots, torn-append and crash tests (`crates/catalog/src/journal.rs`, `tests_journal.rs`, `tests_torn_append.rs`); XMP sidecars read / write; failed saves reported | 0 |
|
||||
| 5. Batch-apply a look: presets, copy / paste / sync settings | yes | presets (incl. `.xmp` / `.lrtemplate` import), copy / paste / sync, auto sync (checklist L 86%, N 100%) | 0 |
|
||||
| 6. Export deliverables (JPEG / TIFF, size, sharpening, metadata, watermark, naming) | yes | one encoder for app, CLI and MCP (`crates/engine/src/export.rs`, `tests_export.rs`); checklist S 89% | 0 |
|
||||
|
||||
**Result: passes.** Every core workflow runs end to end on macOS and the work survives quit and
|
||||
reopen; the partial rows degrade fidelity for some cameras and large files but don't stop the
|
||||
workflow, so LightCraft stays **alpha** (ready for real work ~61%, above the ~40% bar).
|
||||
|
||||
## After beta
|
||||
|
||||
Enhance (Raw Details, Super Resolution, X-Trans denoise), content-aware remove, HDR display, the
|
||||
Classic output modules (Print, then Map, Book, Slideshow, publish services), tethering, video,
|
||||
plug-in ecosystem, localization to `full` and new scripts (RTL, shaping). Estimates in
|
||||
[gaps.md](gaps.md) entries 11–28; ~500–1,300 h after beta.
|
||||
|
||||
## Milestones
|
||||
|
||||
Original wall-clock estimates (made before work started, 4–6 parallel agents) are kept for
|
||||
calibration: M0–M13 took ≈ 25 active hours against an estimate of ≈ 110–170 h.
|
||||
|
||||
**Status legend:** ✅ done · 🚧 in progress · ⬜ not started
|
||||
|
||||
| # | Milestone | Scope (summary) | Estimate (h) | Status |
|
||||
|---|---|---|---|---|
|
||||
| M0 | Skeleton + visual shell | workspace, xtask CI + layering, geom/color/raster, develop model, pipeline v0, catalog v0, engine commands, Lightroom-look UI (grid, loupe, filmstrip, Edit panel), control channel, MCP, web build | 3–5 | ✅ |
|
||||
| M1 | Library core | import (JPEG/PNG/TIFF/WebP), EXIF/XMP, persistent catalog (op log + snapshots), albums, ratings/flags/labels, filter/search/sort, thumbnail cache, 100k-photo grid | 6–10 | ✅ (100k-photo grid scale test pending) |
|
||||
| M2 | Pipeline v1 (quality) | WB temp/tint, profiles, local tone mapping (highlights/shadows), curves, HSL, point colour, colour grading, texture/clarity/dehaze, vignette, grain, B&W, auto tone/WB, histogram, before/after | 10–15 | ✅ (look tuning vs our references ongoing) |
|
||||
| M3 | RAW I | TIFF/DNG (LJ92, deflate, tiles, opcodes), demosaic (AHD/PPG/bilinear), highlight recovery, DNG colour model, CR2, NEF, ARW, embedded previews | 10–15 | ✅ (DNG, CR2 incl. sRAW, ARW, NEF uncompressed / lossless / lossy / lossy after split, embedded previews) |
|
||||
| M4 | Crop, geometry, optics | crop tool + overlays, straighten, Upright (auto/level/vertical/full/guided), manual transforms, CA, defringe, manual lens corrections | 6–10 | ✅ |
|
||||
| M5 | Performance | source pyramids, wgpu compute pipeline (CPU oracle), draft/full renders, prefetch, budgets (16 ms slider updates on 24 MP) | 10–15 | 🚧 (stage cache, source pyramid, wgpu pipeline, prefetch, memory budget ✅; colour NR at half resolution, GPU histogram ⬜) |
|
||||
| M6 | Masking | brush, linear/radial gradients, colour/luminance/depth range, add/subtract/intersect/invert, all local adjustments, masks panel | 8–12 | 🚧 (brush/linear/radial/colour/luminance range, add/subtract/intersect, masks panel ✅; depth range, AI masks ⬜) |
|
||||
| M7 | Detail | sharpening + masking preview, luminance/colour NR, Denoise, Raw Details, Super Resolution | 6–10 | 🚧 (sharpening, luminance/colour NR ✅; AI Denoise 🟡 (Bayer, optional weights; policy/fidelity open); Raw Details, Super Resolution ⬜) |
|
||||
| M8 | Heal / Remove | content-aware remove (PatchMatch), heal, clone, brush spots, visualize spots, red/pet eye | 6–10 | 🚧 (heal, clone, auto source, visualize spots, red/pet eye ✅; PatchMatch remove ⬜) |
|
||||
| M9 | Presets, profiles, versions, sync | preset browser + amount, create/import presets, profile browser, versions, history, copy/paste/sync settings | 5–8 | ✅ |
|
||||
| M10 | Export & share | export dialog (JPEG/PNG/TIFF/DNG/AVIF/JXL/original), sizing, sharpening, metadata, watermark, naming, batch jobs, XMP sidecars, HDR export | 6–10 | 🚧 (all formats incl. DNG/original, sizing, presets, background jobs, HDR gain map JPEG / PQ AVIF ✅; JXL encode ⬜) |
|
||||
| M11 | RAW II | CR3, RAF (X-Trans), ORF, RW2, PEF, SRW, 3FR, IIQ + long tail; camera calibration DB; HEIC/AVIF/JXL import | 20–35 | 🚧 (RAF all, RW2 every format, PEF, ORF uncompressed and 12.8 bpp, SRW uncompressed, HEIC ✅; CR3 🟡 (3 bodies verified); **camera colour calibration** 🚧 (per-file JPEG fits, 4 bundled profiles, 52 spectral matrices; measured database missing); compressed ORF / SRW, HE NEF, IIQ, X3F ⬜) |
|
||||
| M12 | AI & smart features | subject/sky/background/people/object masks, semantic search, faces/People (permissively licensed models, pure-Rust inference) | 20–40 | 🚧 (faces: detection, recognition, People view ✅; Object / Describe masks via SAM 3 🟡; Subject / Sky / People masks, semantic search ⬜) |
|
||||
| M13 | Merge | HDR merge (deghost), panorama (projections, boundary warp, fill edges), HDR panorama | 10–15 | ✅ |
|
||||
| M14 | Video | import/playback/trim via FilmCraft crates, global edits + presets on video, video export | 6–10 | ⬜ |
|
||||
| M15 | Classic modules | Map, Book, Slideshow, Print, Web; smart collections, stacks, virtual copies, publish services, tethering | 25–40 | 🚧 (smart albums, stacks, virtual copies, compare/survey ✅; contact-sheet PDF 🟡; Map/Book/Slideshow/Print/Web ⬜) |
|
||||
| M16 | 1.0 polish | preferences, shortcut editor, accessibility, localization, packaging (dmg/msi/AppImage/web), hardening | 10–20 | 🚧 (settings, keyboard shortcuts sheet, packaging basics ✅; English/Chinese (Simplified, Traditional)/Japanese/Brazilian Portuguese/Spanish/German/Russian/Ukrainian localisation 🟡; accessibility and further locales ⬜) |
|
||||
|
||||
## Risks that coding hours alone don't retire
|
||||
|
||||
- **AI features** (subject / sky / people masks, generative remove) need model weights with
|
||||
licences we can ship; classical fallbacks first. No permissively licensed sky-segmentation or
|
||||
raw-denoise model was found; we may need to train our own.
|
||||
- **Camera colour and lens data** is a data problem: we never use Adobe's matrices, DCPs or LCPs.
|
||||
DNG-embedded data first, then our own calibration; long-tail coverage grows over time and needs
|
||||
people with cameras, lenses and charts.
|
||||
- **Raw-format sources:** decoders are written from prose format descriptions (even ones published
|
||||
alongside GPL code); decoder source is never read (decided 2026-10-05). Still open:
|
||||
freedom-to-operate review for local Laplacian filters, PatchMatch and HEVC (HEIC).
|
||||
- **Look parity** with Adobe's default rendering is tuned by eye until the fidelity suite exists.
|
||||
Retuning changes existing edits, so it ships as a new process version
|
||||
([process-versions.md](process-versions.md)).
|
||||
|
||||
## Design notes kept from the old ROADMAP
|
||||
|
||||
- **Folder records:** library folders have records of their own in the catalog
|
||||
(`Catalog.folder_records`, keyed by folder path; colour labels first). Photos still store full
|
||||
paths, so moving a whole disk relinks each photo. If that becomes a problem (an "Update Folder
|
||||
Location" for a renamed drive, journal growth on large moves), the next step is the Classic model:
|
||||
photos point to a folder id (root + relative path).
|
||||
- **Zoom:** native pinch zoom and two-finger pan work in Detail, Compare and Reference views; the
|
||||
whole-image preview still has a configurable cap (2,560 px default), see gap 4.
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | minor | Beta hours 340–600; full ready ~59% in the gate note |
|
||||
| 2026-10-10 | minor | Added the Alpha gate table (core-workflow gate from the revised standard): passes, stays alpha |
|
||||
| 2026-10-10 | major | Created: milestones moved from ROADMAP.md (statuses refreshed: M3 ✅, M11 / M12 / M15 detail), current focus re-ranked toward beta, risks and design notes kept |
|
||||
@@ -0,0 +1,304 @@
|
||||
# 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)
|
||||
|
||||
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
|
||||
have their own documents: [raw-parity.md](raw-parity.md), [file-format-parity.md](file-format-parity.md),
|
||||
[ui-parity.md](ui-parity.md), [hardware-parity.md](hardware-parity.md),
|
||||
[localization-parity.md](localization-parity.md).
|
||||
|
||||
## Headline
|
||||
|
||||
| Number | Value | Kind |
|
||||
|---|---:|---|
|
||||
| **Feature breadth**, checklist | **81.1%** of 517 in-scope rows (P0 98.0%, P1 95.1%, P2 46.9%) | **measured**: recount of [parity-checklist.md](parity-checklist.md) rows (✅ 1, 🟡 ½, 🚫 left out), the same rule `cargo xtask parity` uses |
|
||||
| **Feature breadth**, weighted by use | **~77%** | estimated: feature-area table below |
|
||||
| **Ready for real work** (full target) | **~61%** (range 56–66%) | estimated: weighted sum over the dimensions with written weights, see [below](#ready-for-real-work-mainstream-practitioner-and-essentials-user) |
|
||||
| **Mainstream practitioner** | **~49%** (range 44–54%) | estimated: weekly areas of a working photographer, depth 71.8% × 0.804 × colour 0.85 |
|
||||
| **Essentials user** | **~64%** (range 59–69%) | estimated: core features at default settings, depth 77.4% × 0.830 |
|
||||
| Remaining to **beta** | **~340–600 h** | estimated; ~60% parallelizes |
|
||||
| Remaining to **full parity** | **~1,000–1,800 h** | estimated; ~70% parallelizes |
|
||||
| **Stage** | **alpha** | see [Stage](#stage) |
|
||||
|
||||
## The target and how it was measured
|
||||
|
||||
- **Target:** Lightroom Classic 15.5 (August 2026; latest per Adobe's release notes) for the
|
||||
library, modules and depth; Lightroom 9.6 (the cloud-library desktop app), installed on the
|
||||
owner's Mac at `/Applications/Adobe Lightroom CC`, for the interface LightCraft's layout follows.
|
||||
Both share the Camera Raw engine.
|
||||
- **Installed bundle, inspected by listing only** (the clean-room rule forbids reading contents):
|
||||
`Info.plist` document types (31 raw extensions, jpg, tif, heic, xmp, catalog bundles); 16
|
||||
`.lproj` localizations; `CameraProfiles` (1,500 Adobe Standard and 395 Camera Matching model
|
||||
names); `LensProfiles` (3,635 files, 56 makers); `ModelZoo` (37 AI model names). The app was not
|
||||
launched.
|
||||
- **LightCraft side:** origin/main at `b70ae174` (2026-10-10): code counts (226 engine commands, 143
|
||||
UI commands, 122 + 10 develop controls, 2,561 tests, ≈ 202,000 Rust lines in 24 crates + 3 apps),
|
||||
the checklist rows, raw corpus manifests, locale catalogs, CI workflows, docs.
|
||||
- **Behaviour and output** were not compared against a running Lightroom in this pass; the
|
||||
measured ΔE figures in [raw-parity.md](raw-parity.md) come from earlier work.
|
||||
|
||||
**Presence is not parity.** ✅ rows are set by whoever lands a feature and have not been checked
|
||||
systematically against Lightroom's behaviour; bugs keep turning up in ✅ areas (CR2 colour-filter
|
||||
phase #85, duplicate Local entries #22, black GPU exports on an Intel iGPU #78).
|
||||
|
||||
## By dimension
|
||||
|
||||
| Dimension | Breadth | Ready for real work | Remaining | Doc |
|
||||
|---|---:|---:|---:|---|
|
||||
| Features (weighted areas below) | ~77% (checklist 81.1%, measured) | ~61% | 600–1,100 h | [Features](#features) |
|
||||
| ↳ RAW cameras, colour and lens profiles (part of features) | 81% of Adobe's 1,446 models decode (16% verified), measured | ~56% | 255–480 h | [raw-parity.md](raw-parity.md) |
|
||||
| UI/UX fidelity | ~85% | ~70% | 40–70 h | [ui-parity.md](ui-parity.md) |
|
||||
| File formats (non-raw: images, sidecars, presets, catalogs) | ~85% | ~70% | 30–55 h | [file-format-parity.md](file-format-parity.md) |
|
||||
| Hardware | ~50% | ~40% | 40–80 h (+ tethering and printing, counted under Classic modules) | [hardware-parity.md](hardware-parity.md) |
|
||||
| Localization (12 key languages) | 7 of 12 present | ~52% (mean of the 12, measured) | 130–210 h for the target's set; +145–255 h for Hindi, Arabic, Indonesian, Vietnamese, Korean | [localization-parity.md](localization-parity.md) |
|
||||
| Performance | ~80% | ~70% | 30–50 h | 24 MP GPU slider 3.9 ms, export 0.3 s (measured, [gpu-pipeline.md](gpu-pipeline.md)); 85k library opens in 1.7–4.7 s; 100k test pending |
|
||||
| Stability | — | ~60% | 30–60 h | never-crash lints and guards workspace-wide, crash-tested journal, 2,561 tests; but CI runs tests only on FreeBSD, user reports keep finding bugs in ✅ areas |
|
||||
| Platforms | macOS, Windows (x64 / x86 / ARM64), Linux (AppImage, deb, rpm, Flatpak, Nix), FreeBSD, web | ~60% | 25–45 h | macOS is where it is tested; Windows installer UI unverified on Windows (#79); web experimental (CPU only) |
|
||||
| Ecosystem / plug-ins | ~25% | ~15% | 40–80 h + owner decision | no Lightroom SDK equivalent (export, publish, metadata plug-ins); beyond the target: JSON-lines control channel, MCP server with 28 tools + one per command, CLI |
|
||||
| AI features | ~30% | ~20% | 120–220 h + model decisions | [AI](#ai) (overlaps the masking and Enhance rows; not added twice) |
|
||||
|
||||
## Features
|
||||
|
||||
Weights are a judgement of what Lightroom users spend their time on (library and develop dominate;
|
||||
Classic output modules and video are used by few). Breadth and readiness per area are estimated
|
||||
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 |
|
||||
| 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 |
|
||||
| Masking | 8% | 67% | 45% | 60–110 h | checklist K 67.4%; AI masks heuristic or SAM 3 without mirror |
|
||||
| Remove, heal, Enhance (denoise, Raw Details, Super Resolution, Lens Blur) | 7% | 45% | 30% | 70–130 h | checklist I 75%, P 0% |
|
||||
| Presets, profiles, versions, history, sync | 5% | 95% | 85% | 8–15 h | |
|
||||
| Export | 6% | 89% | 75% | 15–30 h | checklist S 88.9% |
|
||||
| Merge and HDR | 3% | 85% | 60% | 20–35 h | merge 100%, HDR 70% (no HDR display) |
|
||||
| Views, compare, zoom, culling | 5% | 90% | 70% | 15–30 h | zoom detail P0 gap |
|
||||
| Classic output modules (Map, Book, Slideshow, Print, Web, publish, tethering) | 4% | 15% | 10% | 90–150 h | Classic extras 48% counts many small keys; the modules themselves are mostly ⬜ |
|
||||
| Video | 1% | 0% | 0% | 25–45 h | catalogued only |
|
||||
| **Weighted** | 100% | **~77%** | **~61%** (60.6%) | **600–1,100 h** | |
|
||||
|
||||
## AI
|
||||
|
||||
Lightroom 9.6 ships 37 on-device models (names listed from its `ModelZoo`), covering subject, sky,
|
||||
portrait, skin and object selection with refinement, depth estimation, denoise, dust detection,
|
||||
reflections removal, distraction / people detection, culling scores (eyes open, blur, aesthetics) and
|
||||
search embeddings; generative remove runs in Adobe's cloud.
|
||||
|
||||
| Feature | LightCraft | Status |
|
||||
|---|---|---|
|
||||
| Subject / Sky / Background masks | classical heuristics; the file's own DNG semantic mattes | 🟡 |
|
||||
| People (faces, body, hair, skin…) and Landscape masks | — | ⬜ |
|
||||
| Object / Describe masks | SAM 3 in pure Rust (Metal / CPU); opt-in 3.4 GB download, no mirror configured | 🟡 |
|
||||
| Depth range mask, Lens Blur | — | ⬜ |
|
||||
| AI Denoise | Bayer only, pure-Rust CPU / GPU, user-installed weights | 🟡 |
|
||||
| Raw Details, Super Resolution | — | ⬜ |
|
||||
| Generative remove, distractions, reflections | — (generative is out of scope: cloud) | ⬜ |
|
||||
| Dust detection | ✅ | ✅ |
|
||||
| Faces / People | YuNet detection, SFace / AuraFace recognition (opt-in downloads), People view | ✅ (MVP, [faces.md](faces.md)) |
|
||||
| Assisted culling | focus, bursts | 🟡 (no eyes-open / aesthetics scores) |
|
||||
| Auto (tone), adaptive presets | Auto calibrated on Lightroom's Auto results (#628); no adaptive presets | 🟡 |
|
||||
| Natural-language search | — | ⬜ |
|
||||
|
||||
**Blocked on a model strategy** (maintainer decision): licensable weights or our own training;
|
||||
pure-Rust inference is proven (faces, SAM 3, denoise).
|
||||
|
||||
## Ready for real work, mainstream practitioner and essentials user
|
||||
|
||||
Three readiness numbers (craftrules `standards/progress-docs.md`). The full number is a weighted
|
||||
sum over the dimensions with written weights. Mainstream and essentials take the weighted depth of
|
||||
the areas their user touches, then apply written multiplicative discounts for what still stops real
|
||||
work. Each has its own hours to ~95%, calibrated as in [How hours are calibrated](#how-hours-are-calibrated)
|
||||
(essentials ⊂ mainstream ⊂ full):
|
||||
|
||||
| Audience | Ready | Opus 5.5 agent wall-clock hours to ~95% | Work that dominates |
|
||||
|---|---:|---:|---|
|
||||
| Full target (ready for real work) | **~61%** | **1,000–1,800 h** (~70% parallelizes) | raw colour, lens and camera data; AI models; Classic output modules; localization; plug-in ecosystem |
|
||||
| Mainstream practitioner | **~49%** | **450–840 h** (~60% parallelizes) | camera colour and render fidelity; CR3 / ORF / HE NEF; lens database; subject / sky masks; Lightroom XMP exchange; stability |
|
||||
| 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 |
|
||||
|
||||
### Full target (ready for real work): ~61%
|
||||
|
||||
Weighted sum over the dimensions of [By dimension](#by-dimension) (AI is left out because it
|
||||
overlaps the masking and Enhance feature areas). RAW decoding and camera colour are their own rows,
|
||||
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) |
|
||||
| Camera colour and default rendering | 6% | 35% |
|
||||
| UI/UX fidelity | 8% | 70% |
|
||||
| File formats (non-raw) | 6% | 70% |
|
||||
| Hardware | 3% | 40% |
|
||||
| Localization | 3% | 52% |
|
||||
| Performance | 6% | 70% |
|
||||
| Stability | 8% | 60% |
|
||||
| Platforms | 4% | 60% |
|
||||
| Ecosystem / plug-ins | 2% | 15% |
|
||||
| **Weighted sum** | 100% | **60.6% ≈ 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
|
||||
strong library, presets, UI and format dimensions.
|
||||
|
||||
**Why the numbers moved with the RAW measurement:** decoding measured model by model against
|
||||
Adobe's list is better than the earlier 50% estimate (84% of photographers' cameras decode, 76% after
|
||||
a bug discount), colour is lower (35%, was 40%) and is now its own row. Net: full +2 points.
|
||||
Mainstream now carries colour as a ×0.85 discount on top of the measured coverage (−2 points);
|
||||
essentials replaces its guessed 45% raw look with 84% × 0.75 (+1 point).
|
||||
|
||||
### Discounts (evidence: open issues from users, 2026-10-10)
|
||||
|
||||
| Discount | Mainstream | Essentials | Evidence |
|
||||
|---|---:|---:|---|
|
||||
| Interaction fidelity / UI clarity | ×0.95 | ×0.95 | brush live preview gaps and feathering (#517, #518); crop artefacts and limits (#731, #742, #770, #771); Compare white-balance selector (#743–#745); low-res slider previews (#330); dialogs taller than the window (#781); mouse-wheel scroll (#714); 100% zoom capped (gap 4) |
|
||||
| Stability on real machines | ×0.92 | ×0.92 | launch and quit crashes or silent startup failures (#250 macOS 12 Intel, #315 Windows Intel GPU, #431 Intel Mac, #260, #462, #783 Linux / Nouveau, #790 Windows installer); tests run in CI on FreeBSD only (gap 9) |
|
||||
| File exchange with Lightroom users (mainstream) / opening files people send (essentials) | ×0.92 | ×0.95 | Adobe XMP sidecars change colours (#290), XMP CameraProfile and Upright ignored (#204, #205), catalog import fails (#599), same Light values render differently (#523, #209), no write-back to `.lrcat`; for casual users: CR3 beyond verified bodies, compressed ORF, HE NEF open as previews (#473, #485, #556), HEIC trouble (#693) |
|
||||
| **Product** | **×0.804** | **×0.830** | |
|
||||
|
||||
### Mainstream practitioner: ~49%
|
||||
|
||||
A working photographer (wedding, portrait, events, landscape) shooting raw on one current camera,
|
||||
weekly: import, cull, develop, a few masks, sync a look, export. Excluded: Classic output modules,
|
||||
video, generative / cloud AI, plug-ins, tethering and other specialist hardware, languages other
|
||||
than the user's own.
|
||||
|
||||
| Area | Weight | Depth |
|
||||
|---|---:|---:|
|
||||
| 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)) |
|
||||
| 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%** |
|
||||
|
||||
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%).
|
||||
|
||||
### Essentials user: ~64%
|
||||
|
||||
A casual photographer with default settings: import, look through, rate, fix a few photos with the
|
||||
basic sliders, crop, apply a preset, undo, export JPEGs.
|
||||
|
||||
| Feature | Weight | Depth |
|
||||
|---|---:|---:|
|
||||
| Import photos | 15% | 80% |
|
||||
| Browse grid and detail view | 10% | 85% |
|
||||
| Rate and flag | 5% | 90% |
|
||||
| Basic sliders (exposure, contrast, highlights, shadows, white balance, vibrance / saturation) | 22% | 70% (slider strength differs from Lightroom, #196, #521) |
|
||||
| Auto | 5% | 65% (#318) |
|
||||
| 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) |
|
||||
| Export JPEG | 10% | 85% |
|
||||
| **Weighted depth** | 100% | **77.4%** |
|
||||
|
||||
77.4% × 0.830 = **~64%** (range 59–69%).
|
||||
|
||||
### User evidence (GitHub issues, excluding the four maintainers)
|
||||
|
||||
- 324 issues from 159 users; 162 open. 8,719 stars, 2,698 forks (2026-10-10).
|
||||
- Of the 162 open: **~92 core-path bugs** (33 colour / rendering, 16 decoding, ~36 UI / workflow, 7
|
||||
launch / stability), ~11 developer / test infrastructure, **~59 feature requests or niche asks**
|
||||
(plug-ins, mobile, sync servers, tablets, MIDI, geocoding, themes).
|
||||
- Praise in issue text (love / amazing / great work / awesome): ~14 issues; "thank you" in 27.
|
||||
**No explicit "switched from Lightroom" report** was found ("switched" matches 6 issues, none a
|
||||
switch report).
|
||||
- Reading: strong interest, but most open user issues are core-path, and raw colour dominates them,
|
||||
so the mainstream number is held down by default rendering rather than missing features.
|
||||
|
||||
### Why the full number moved (55% → 46% → 59%)
|
||||
|
||||
The first figure (~55%) was the feature depth "pulled down" by an unwritten judgement. A later pass
|
||||
applied the mainstream discounts to it (~46%). The standard defines the full number as a weighted
|
||||
sum over the dimensions, so it is now that sum with the weights written above: ~59%. Method aligned
|
||||
with the standard, no new evidence. The stage stays **alpha**.
|
||||
|
||||
## Stage
|
||||
|
||||
**Alpha.** Core workflows exist end to end (import, cull, develop, mask, export, catalog migration),
|
||||
but ready-for-real-work is ~61%, below the ~75% beta bar, and the main file formats have blocking
|
||||
gaps: Canon CR3 decodes from sensor data on three verified bodies only, compressed ORF and HE NEF
|
||||
open as previews, and colour on every non-DNG raw is estimated rather than measured.
|
||||
|
||||
**Alpha gate:** all six core workflows (import, cull, develop, save and reopen, batch looks, export)
|
||||
work end to end on macOS; see the table in [roadmap.md](roadmap.md#alpha-gate). The partial rows (CR3
|
||||
variants, compressed ORF, HE NEF as previews; capped 100% zoom) degrade but don't block a workflow.
|
||||
|
||||
**To beta:** ~14 points of readiness, **~340–600 h**: the nine `B` gaps in [gaps.md](gaps.md)
|
||||
(~230–430 h), plus burning down the ~92 open core-path user issues (40–80 h) and stability work
|
||||
around them. Beta needs: CR3, ORF and
|
||||
HE NEF decoding from sensor data; measured colour for the popular models and a fidelity suite with
|
||||
scores; full-resolution zoom; Subject / Sky / People masks; a lens profile database for the
|
||||
popular lenses; tests in CI on macOS, Windows and Linux.
|
||||
|
||||
## How hours are calibrated
|
||||
|
||||
Hours are Opus 5.5 agent wall-clock hours, one session working sequentially, including tests and
|
||||
verification. Calibrated on this repository's history (git log and GitHub PR open-to-merge times):
|
||||
|
||||
- **Project pace:** first commit 2026-09-30; by 2026-10-10, 1,066 non-merge commits and 325 merged
|
||||
PRs, commits in 159 distinct clock hours, with 4–6 parallel agents plus community contributors.
|
||||
On 2026-10-02 the ROADMAP recorded ≈ 105–145 agent-hours spent; M0–M13 took ≈ 25 active hours with
|
||||
parallel agents against an up-front estimate of 110–170 h.
|
||||
- **UI and library rows:** a lead agent closed ≈ 45 checklist rows in ≈ 5 h (2026-10-01) and ≈ 60 in
|
||||
≈ 12 h (2026-10-02): 6–12 minutes per small row.
|
||||
- **Raw decoders:** RW2 in every format 6.5 h (#215), compressed RAF 8.6 h (#282), CR3 CRX 10 h
|
||||
(#279), NEF lossy after split 4.7 h (#633), ORF 12.8 bpp 1.7 h (#651), HEIC 7 h (#609).
|
||||
- **Large features:** AI RAW denoise 8.3 h (#384, 12.8k lines), SAM 3 masks 14.9 h (#162),
|
||||
HDR editing and export 2.3 h (#646, on existing groundwork), contact-sheet PDF (#563), German UI
|
||||
13.8 h (#265).
|
||||
- PR open time includes queueing and review, so these are upper bounds per feature; the ranges add
|
||||
a long-tail factor of 1.3–1.5× for verification against real files.
|
||||
|
||||
### Why the estimate went up
|
||||
|
||||
The previous estimate (2026-10-02, kept below) was ≈ 270–505 h to full parity. It counted checklist
|
||||
rows only. New evidence since: the target's own lists (≈ 1,000 dedicated camera models, 3,635 lens
|
||||
profiles, 37 AI models, 16 languages) measured from the installed bundle; per-maker verification
|
||||
counts; that CI tests only FreeBSD; and the standard's added dimensions (localization, stability,
|
||||
platforms, ecosystem). The raw-codec package it estimated at 40–80 h took roughly that and closed
|
||||
most of its list; what remains is the data-heavy part (colour, lenses, models) it did not count.
|
||||
|
||||
## History of the numbers
|
||||
|
||||
| Date | Checklist (all / P0 / P1 / P2) | Ready for real work | Remaining to full parity | Source |
|
||||
|---|---|---|---|---|
|
||||
| 2026-10-10 (RAW) | 81.1% (unchanged) | ~61% full · ~49% mainstream · ~64% essentials | unchanged | RAW measured model by model against Adobe's list; RAW decode and colour as explicit rows |
|
||||
| 2026-10-10 (final) | 81.1% (unchanged) | ~59% full (weighted sum) · ~51% mainstream · ~63% essentials | full 1,000–1,800 h · mainstream 450–840 h · essentials 160–300 h | method aligned with the standard |
|
||||
| 2026-10-10 (later) | 81.1% (unchanged) | ~46% full · ~51% mainstream · ~63% essentials | 1,000–1,800 h | full × discounts (superseded) |
|
||||
| 2026-10-10 | 81.1% / 98.0% / 95.1% / 46.9% (517 rows) | ~55% | 1,000–1,800 h | this re-measure |
|
||||
| 2026-10-08 | 79.7% / 98.2% / 95.6% / 41.6% (509 rows) | 60–70% | — | ROADMAP *Where we stand* |
|
||||
| 2026-10-02 | 75.6% | — | 270–505 h (cloud parity without AI / Classic: 130–255 h) | ROADMAP *Parity estimate* |
|
||||
|
||||
The 2026-10-08 assessment by dimension, kept for evidence: feature checklist 79.7%; RAW coverage
|
||||
~55%; colour and image quality ~55–65%; AI and computational ~15–20%; workflow and library ~85%
|
||||
(single machine); Classic modules ~30%; HDR and video ~25%; platform and robustness ~70%. By kind of
|
||||
user: JPEG / DNG shooter ~85%; Nikon / Sony / Panasonic / older-Canon ~65%; Fujifilm ~65%; Canon
|
||||
CR3 / Olympus compressed ~45%; Classic power user ~45%; relies on AI ~25%. Today's numbers per user:
|
||||
JPEG / DNG ~75%; Sony, Panasonic, Fujifilm ~60%; Nikon ~55% (HE NEF); Canon CR3 ~40%; OM / Olympus
|
||||
~30%; Classic power user ~40%; relies on AI ~20%.
|
||||
|
||||
The 2026-10-02 effort table, kept for calibration: remaining P0/P1 UI 5–10 h; raw codecs 40–80 h;
|
||||
lens database 15–30 h; video 20–40 h; AI 80–150 h; HDR 15–25 h; Classic modules 60–100 h; smaller
|
||||
P2 items 12–25 h; look tuning, performance, packaging, hardening 25–45 h.
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 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 |
|
||||
| 2026-10-10 | minor | Stage re-checked against the core-workflow alpha gate: passes, stays alpha |
|
||||
| 2026-10-10 | major | Created per the progress-docs standard: full re-measure (checklist recount, installed Lightroom 9.6 bundle listing, code counts, catalogs, CI), feature areas with weights, dimensions, AI, stage, calibration; merged ROADMAP's *Where we stand* and *Parity estimate* |
|
||||
@@ -0,0 +1,81 @@
|
||||
# UI parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created; shortcut notes moved here from the checklist) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
|
||||
How LightCraft's interaction compares with Lightroom's: views, panels, tools and handles, modifier
|
||||
keys, shortcuts, zoom, context menus and feel. Rows for individual menu items and shortcuts live in
|
||||
[parity-checklist.md](parity-checklist.md) (sections Y and Z, Classic keys); this page is the
|
||||
assessment and the notes that don't fit a row. Visual reference for agents: `plan/lightroom/`
|
||||
(local, gitignored; `10-observed-ui.md` and screenshots).
|
||||
|
||||
## Measured counts (2026-10-10)
|
||||
|
||||
- 226 engine commands (`crates/engine/src/cmd/`, 30 modules) and 143 UI commands (`UI_COMMANDS` in
|
||||
`crates/ui-egui/src/menus.rs`, 73 with a shortcut) plus 10 language commands; 23 secondary
|
||||
shortcut bindings (`ALIASES`, `crates/ui-egui/src/shortcuts.rs`); a keymap editor.
|
||||
- 122 develop controls plus 10 indexed templates (`crates/develop/src/controls.rs`).
|
||||
- Checklist: menus 95.3% (86 in-scope rows), desktop shortcuts 94.4% (81 rows), Classic extras
|
||||
48.2% (82 rows), measured by recounting [parity-checklist.md](parity-checklist.md).
|
||||
- 31 panel modules (`crates/ui-egui/src/panels/`), 26 context-menu sites.
|
||||
|
||||
## Assessment by area
|
||||
|
||||
| Area | Target | LightCraft | Ready | Main gaps |
|
||||
|---|---|---|---:|---|
|
||||
| Layout and views | Lightroom: grid / detail / edit; Classic: Library, Develop, Map, Book, Slideshow, Print, Web modules, filmstrip, panels | Lightroom-style single window: Photo Grid, Square Grid, Detail, Compare, Survey (≤ 48), Before / After, People, quick slideshow, second window, filmstrip | 75% | no Classic module switcher (by design) or output modules; dark theme only |
|
||||
| Develop panels and sliders | Light, Color, Effects, Detail, Optics, Geometry, Lens Blur, Calibration | every global slider; scrub, double-click reset, Alt-drag previews where implemented | 80% | Lens Blur, Calibration panel depth; slider feel (acceleration, fine Shift-drag) unmeasured |
|
||||
| Crop, Upright, transform handles | handles, aspect lock, angle, overlays (O / ⇧O), guided Upright | ✅ all of them; overlay cycle on ⇧O | 85% | crop opacity of cut-out area (15.5) |
|
||||
| Masking tools | brush (A / B, flow, density, auto mask, pressure), linear / radial, range masks, AI masks, pins | brush, linear, radial, colour / luminance range, add / subtract / intersect / invert, masks panel, pins | 60% | brush live preview (#517 / #518), no pen pressure, no depth range, AI masks, Feather / Edge controls (15.5) |
|
||||
| Remove / heal | content-aware remove, heal, clone, visualize spots | heal, clone, auto source, visualize spots, red / pet eye | 65% | content-aware (patch synthesis) remove, generative remove, detect distractions |
|
||||
| Zoom and navigation | Fit / Fill / 1:1 / 2:1 … 11:1, Navigator, spacebar pan | Fit to 800%, pinch zoom, pan, Navigator-like | 60% | **original-pixel detail at 100% (preview capped at 2,560 px; P0 gap LR-VIEW-ZOOM)** |
|
||||
| Library culling and metadata | ratings, flags, labels with keys, painter, keywording, metadata panel, filter bar | ratings / flags / labels and advance, keyword list and sets, keywording box, metadata fields, smart albums, filter bar | 85% | painter tool, quick collection, some Classic keys |
|
||||
| Shortcuts | Lightroom desktop and Classic keymaps | Lightroom-desktop keymap with Classic additions, editable | 85% | deliberate differences below; no Classic keymap layer |
|
||||
| Context menus | everywhere | 26 sites (grid, filmstrip, albums, folders, keywords, masks, presets…) | 70% | unaudited against Lightroom's menus item by item |
|
||||
| Text fields | native editing behaviour | custom text field (LR-BEHAV-TEXTFIELD) | 70% | IME and selection edge cases |
|
||||
| Accessibility | VoiceOver / Narrator, keyboard navigation | AccessKit: sliders, buttons, dropdowns, section headers announce | 30% | canvas tools pointer-only; not audited with a screen reader |
|
||||
| Feel and responsiveness | GPU-interactive sliders (15.3) | ≤ 16 ms slider budget on GPU; background renders | 75% | colour NR at half resolution, 100k-photo grid test |
|
||||
| **UI/UX overall** | | | **~70%** | estimated, weighted by use (develop and library 60%, tools 25%, rest 15%) |
|
||||
|
||||
Remaining: **40–70 h** (zoom detail 8–15 h, brush and masking feel 8–12 h, accessibility audit 10–20
|
||||
h, Classic keymap layer 4–8 h, context-menu audit 4–8 h, text-field and IME polish 4–8 h). Output
|
||||
modules and AI tools are counted with their features in [target-app-parity.md](target-app-parity.md).
|
||||
|
||||
## Shortcuts
|
||||
|
||||
Compared `plan/lightroom/06-shortcuts.md` (desktop part) with our bindings: command specs in `crates/engine/src/cmd/`,
|
||||
`UI_COMMANDS` in `crates/ui-egui/src/menus.rs` and secondary bindings (`ALIASES`) in `crates/ui-egui/src/shortcuts.rs`.
|
||||
`no_conflicting_bindings` (same file) fails when one key fires two actions.
|
||||
|
||||
**Fixed (M16.1):** added Lightroom-desktop keys as secondary bindings for existing commands — ⌘D Select None, ⇧E
|
||||
Export dialog, Space Toggle zoom, ⇧M Create Version, ⇧X Reject + advance, ⇧U Unflag + advance. `⇧Y` fired both
|
||||
Before/After Split and the History panel; History lost the binding. `W` and `⇧⌘I` also fired the engine command
|
||||
under the UI command that wraps it (a no-op error); the UI command now wins.
|
||||
|
||||
**Deliberate differences (our key → Lightroom desktop key)** — each is a conflict with another binding we have:
|
||||
|
||||
| Action | Ours | Lightroom desktop | Why |
|
||||
|---|---|---|---|
|
||||
| Pick flag | P | Z | Z = toggle zoom (Classic convention); P is the Classic pick key |
|
||||
| Photos panel (left) | ⌘⇧L | P | P = pick |
|
||||
| Expand/collapse edit sections | ⌘⌥1–5 | ⌘1–6 | ⌘0 = Zoom to Fit, ⌘1 = Zoom 100 %; Geometry lives in the Crop panel |
|
||||
| Histogram | ⌘⇧H | ⌘0 | ⌘0 = Zoom to Fit |
|
||||
| Square Grid | ⇧G | (none; ⇧G = Guided Upright) | Guided Upright is a button in the Crop panel |
|
||||
| Export dialog | ⌘⇧E (+ ⇧E) | ⇧E | ⌘⇧E is "Edit in Photoshop" there; no external-editor command yet |
|
||||
| Crop overlay cycle | ⇧O | O | O = mask overlay; ⇧O (mask colour / overlay orientation) unused otherwise |
|
||||
| Create Version | ⌘⇧S (+ ⇧M) | ⇧M (Windows: Ctrl+⇧S) | — |
|
||||
| Select None | ⌘⇧A (+ ⌘D) | ⌘D | — |
|
||||
|
||||
**Library culling (KEYC-RATING):** `0–5`, `6–9` and `P/X/U` reach egui on macOS even when displayed in the native menu (adapted from PR #261; issue #283). `Shift+0–9` applies and advances once; `Shift+P` picks and advances in Photo Grid / Square Grid and retains Presets elsewhere. See [library shortcuts](library-shortcuts.md) for the verified Classic mapping and regression coverage. Remaining Classic gaps: rating `[` / `]`, flag cycling and filter-bar keys.
|
||||
|
||||
**Still missing / broken:**
|
||||
- No command yet: F1 help (verify the rest of the old list: full screen, settings, stacks,
|
||||
visualize spots and merges have commands now).
|
||||
- `H` opens Remove; Lightroom also uses it (Classic) to hide pins — pins toggle from View → Show Mask Pins.
|
||||
- ⌘M / ⌘H / ⌘Q / ⌘W rely on the platform window defaults (unverified).
|
||||
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-10 | major | Created: measured command and shortcut counts, assessment by area, estimates; moved the shortcut conflicts section here from the checklist |
|
||||
+77
-67
@@ -1,6 +1,6 @@
|
||||
# What's new in LightCraft
|
||||
|
||||
## October 2026
|
||||
## 2026-10-10
|
||||
|
||||
### Activity stack
|
||||
- Long-running tasks show in one place, top left under the top bar, as in Lightroom Classic (issue #345): imports and
|
||||
@@ -11,6 +11,8 @@
|
||||
- Quitting while a task that can be stopped is running asks first ("Quit Anyway" stops it).
|
||||
- Agents list and stop tasks with `activity.list` and `activity.cancel`; `ui.inspect` reports them as `activity`.
|
||||
|
||||
## 2026-10-09
|
||||
|
||||
### Smart album rules
|
||||
- The rule editor's field menu is grouped: Rating, Pick Flag, Color Label and Any Searchable Text at the top, then
|
||||
submenus for Source, File, Date, Keywords & People, Description, Camera Info, Location, Size, Develop and Assisted
|
||||
@@ -129,6 +131,8 @@
|
||||
next to it while you rotate (issue #534). For an exact angle, type it in the new Angle field under Straighten and press Return
|
||||
(Esc keeps the old angle; a decimal comma works too), or click the Straighten value; hovering any slider's value now says it can be typed.
|
||||
|
||||
## 2026-10-08
|
||||
|
||||
### Albums tree
|
||||
- Album folders fold with the same disclosure triangle as Local, By Date, Folders and Keywords.
|
||||
- Right-click a folder ▸ New ▸ Create Album… / Create Smart Album… / Create Smart Album from Filter… / Create Folder…
|
||||
@@ -158,6 +162,60 @@
|
||||
press the new keys (Esc cancels), × removes it, ↺ restores the original, Reset All undoes every change. A key that
|
||||
belonged to another command moves to the new one. Menus show the new keys; agents use `app.setShortcut`.
|
||||
|
||||
### Formats
|
||||
- HEIC / HEIF photos (iPhone and Mac) open now: the optional `lightcraft-heif` crate (heic-rs, pure Rust) behind
|
||||
codecs' `heif` feature — 8- and 10-bit, alpha, grid tiles, the container's rotation/mirror/crop, ICC, EXIF and XMP.
|
||||
Off by default (HEVC patents are the distributor's call, same as PhotoCraft); official builds pass `--features heif`.
|
||||
- HEIC colours now match libheif to within one code value (they were up to ~10 off): the HEVC stream's own
|
||||
full-range/matrix signalling is honoured (iPhone photos are full range), chroma is upsampled like libheif, grids
|
||||
take their tiles' ICC profile, and `imir` mirrors the way libheif writes it. Importing a HEIC reads its size from
|
||||
the container instead of decoding it; small previews use the file's embedded thumbnail. The release packages
|
||||
(macOS, Windows, Linux, FreeBSD, Nix) now really are built with HEIC support; a build without it reports
|
||||
"HEIC/HEIF support isn't included in this build" for each `.heic`/`.heif` at import.
|
||||
|
||||
### Editing
|
||||
- The Tint slider works the right way round (issues #188, #321): left adds green, right adds magenta, as its track
|
||||
shows and as in Lightroom, and Tint values in Lightroom XMP sidecars now render as they do there. A custom Tint
|
||||
saved in an earlier version now shifts the other way; set it again (or re-run Auto / the white-balance picker).
|
||||
- White balance on DNGs (and other raws with a colour matrix) re-develops the photo for the new white through the
|
||||
camera's own colour matrices, as Lightroom does, instead of shifting the colours of the as-shot rendering: a grey
|
||||
lit by the chosen white comes out grey and saturated colours move as the camera records them. The eyedropper and
|
||||
Auto use the same model. Custom white balances on these photos render slightly differently than before.
|
||||
- Crop (issue #295): a Lock toggle keeps the aspect ratio on every handle, Custom takes your own ratio (Apply), and
|
||||
dragging a handle into the image edge stops there instead of pushing the crop out of shape.
|
||||
|
||||
### Library and views
|
||||
- Trackpads: pinch to zoom around the pointer and scroll with two fingers to pan the photo; panning keeps the photo
|
||||
inside the view. A plain mouse wheel over a zoomed photo pans it too.
|
||||
- A Folders section in the sidebar lists the folders your photos were imported from; choose one to see its photos.
|
||||
- Select All and multi-selection show every selected photo in the grid and filmstrip, not only the active one
|
||||
(issues #187, #298). Importing files that are in Recently Deleted asks whether to leave them there, restore them
|
||||
(with their edits) or import them as new; the trash view's Photo menu has Empty Recently Deleted.
|
||||
- The Import Photos review opens bigger and can be resized; its photo grid fills it (issue #337). Shift-click checks
|
||||
or unchecks a range of photos (issue #338).
|
||||
- When a folder holds several file types, the Import Photos review has a toggle per type (`ARW · 120`, `JPG · 120`):
|
||||
import only the raws and leave the JPEGs beside them (issue #344).
|
||||
|
||||
### Languages
|
||||
- The interface is available in Spanish (issue #371), German and Russian (Edit ▸ Language), alongside English,
|
||||
Chinese (Simplified and Traditional), Japanese and Brazilian Portuguese.
|
||||
|
||||
### Editing
|
||||
- Type an exact value into any slider (issue #322): click the number next to its name, type (`1.5`, `-20`, `5600`)
|
||||
and press Return; Esc keeps the old value.
|
||||
|
||||
### Editing
|
||||
- The eye on the Light, Color and Detail section headers now hides their adjustments, as it already did for Effects,
|
||||
Optics, Geometry and Calibration (issue #316).
|
||||
|
||||
### Library
|
||||
- Choosing a date under By Date or a keyword under Keywords shows those photos from All Photos, as their counts
|
||||
promise, instead of filtering whatever album or folder was open, which often showed nothing (issue #341).
|
||||
)
|
||||
)
|
||||
|
||||
## 2026-10-07
|
||||
|
||||
### RAW decoding
|
||||
- Olympus ORF raws get the starting look fitted to the camera's own JPEG too, instead of opening flat and grey (the
|
||||
E-1, E-400 and XZ-2 corpus files: all accepted), with white balance relative to the as-shot look as for the other
|
||||
@@ -214,72 +272,7 @@
|
||||
existing LightCraft edits are preserved by default. Source settings/history are archived, unsupported
|
||||
fields are reported, and the original Lightroom database stays read-only. Rendering is approximate.
|
||||
|
||||
### Formats
|
||||
- HEIC / HEIF photos (iPhone and Mac) open now: the optional `lightcraft-heif` crate (heic-rs, pure Rust) behind
|
||||
codecs' `heif` feature — 8- and 10-bit, alpha, grid tiles, the container's rotation/mirror/crop, ICC, EXIF and XMP.
|
||||
Off by default (HEVC patents are the distributor's call, same as PhotoCraft); official builds pass `--features heif`.
|
||||
- HEIC colours now match libheif to within one code value (they were up to ~10 off): the HEVC stream's own
|
||||
full-range/matrix signalling is honoured (iPhone photos are full range), chroma is upsampled like libheif, grids
|
||||
take their tiles' ICC profile, and `imir` mirrors the way libheif writes it. Importing a HEIC reads its size from
|
||||
the container instead of decoding it; small previews use the file's embedded thumbnail. The release packages
|
||||
(macOS, Windows, Linux, FreeBSD, Nix) now really are built with HEIC support; a build without it reports
|
||||
"HEIC/HEIF support isn't included in this build" for each `.heic`/`.heif` at import.
|
||||
|
||||
### Presets and profiles
|
||||
- Import presets from other editors: XMP presets, classic `.lrtemplate` files, "DNG presets" from mobile apps and `.zip`
|
||||
bundles of any of these — whole folders at once, grouped by pack. Masks inside presets come along.
|
||||
- Luminar looks: `.lmp` files and `.mplumpack` collections import as presets (grouped by collection); the sliders
|
||||
with a counterpart here come along, the rest is listed.
|
||||
- 23 new built-in presets: Portrait, Landscape, Urban, Food, Seasons, Vintage and B&W toners.
|
||||
- Importing XMP presets no longer lists bookkeeping fields (`Cluster`, `SortName`, `SupportsAmount2`, the as-shot
|
||||
white, empty Point Color slots…) as settings that couldn't be carried over.
|
||||
- A preset whose lens-profile switch is off no longer turns off the lens corrections built into a DNG (iPhone ProRAW
|
||||
and other files with embedded distortion / vignetting corrections), matching what the preset does elsewhere.
|
||||
- XMP presets apply their red / green / blue curves only when they also have the master curve and all three channel
|
||||
curves, as Lightroom does: a preset with just one channel curve (or no master curve) leaves the channels alone.
|
||||
- Imported `.cube` LUT profiles appear in the Profile menu and the profile browser, grouped by their folder, and stay
|
||||
favourites across restarts (issue #328).
|
||||
|
||||
### Editing
|
||||
- The Tint slider works the right way round (issues #188, #321): left adds green, right adds magenta, as its track
|
||||
shows and as in Lightroom, and Tint values in Lightroom XMP sidecars now render as they do there. A custom Tint
|
||||
saved in an earlier version now shifts the other way; set it again (or re-run Auto / the white-balance picker).
|
||||
- White balance on DNGs (and other raws with a colour matrix) re-develops the photo for the new white through the
|
||||
camera's own colour matrices, as Lightroom does, instead of shifting the colours of the as-shot rendering: a grey
|
||||
lit by the chosen white comes out grey and saturated colours move as the camera records them. The eyedropper and
|
||||
Auto use the same model. Custom white balances on these photos render slightly differently than before.
|
||||
- Crop (issue #295): a Lock toggle keeps the aspect ratio on every handle, Custom takes your own ratio (Apply), and
|
||||
dragging a handle into the image edge stops there instead of pushing the crop out of shape.
|
||||
|
||||
### Library and views
|
||||
- Trackpads: pinch to zoom around the pointer and scroll with two fingers to pan the photo; panning keeps the photo
|
||||
inside the view. A plain mouse wheel over a zoomed photo pans it too.
|
||||
- A Folders section in the sidebar lists the folders your photos were imported from; choose one to see its photos.
|
||||
- Select All and multi-selection show every selected photo in the grid and filmstrip, not only the active one
|
||||
(issues #187, #298). Importing files that are in Recently Deleted asks whether to leave them there, restore them
|
||||
(with their edits) or import them as new; the trash view's Photo menu has Empty Recently Deleted.
|
||||
- The Import Photos review opens bigger and can be resized; its photo grid fills it (issue #337). Shift-click checks
|
||||
or unchecks a range of photos (issue #338).
|
||||
- When a folder holds several file types, the Import Photos review has a toggle per type (`ARW · 120`, `JPG · 120`):
|
||||
import only the raws and leave the JPEGs beside them (issue #344).
|
||||
|
||||
### Languages
|
||||
- The interface is available in Spanish (issue #371), German and Russian (Edit ▸ Language), alongside English,
|
||||
Chinese (Simplified and Traditional), Japanese and Brazilian Portuguese.
|
||||
|
||||
### Editing
|
||||
- Type an exact value into any slider (issue #322): click the number next to its name, type (`1.5`, `-20`, `5600`)
|
||||
and press Return; Esc keeps the old value.
|
||||
|
||||
### Editing
|
||||
- The eye on the Light, Color and Detail section headers now hides their adjustments, as it already did for Effects,
|
||||
Optics, Geometry and Calibration (issue #316).
|
||||
|
||||
### Library
|
||||
- Choosing a date under By Date or a keyword under Keywords shows those photos from All Photos, as their counts
|
||||
promise, instead of filtering whatever album or folder was open, which often showed nothing (issue #341).
|
||||
)
|
||||
)
|
||||
## 2026-10-05
|
||||
|
||||
### Reliability
|
||||
- The Windows installer asks where to install LightCraft (Program Files by default; upgrades keep the folder you
|
||||
@@ -377,6 +370,23 @@
|
||||
library) are written atomically and saved as soon as you open another library, not only at quit. Quitting while
|
||||
changes couldn't be saved tries once more, then asks: Try Saving Again, Quit Anyway or Cancel.
|
||||
|
||||
## 2026-10-02
|
||||
|
||||
### Presets and profiles
|
||||
- Import presets from other editors: XMP presets, classic `.lrtemplate` files, "DNG presets" from mobile apps and `.zip`
|
||||
bundles of any of these — whole folders at once, grouped by pack. Masks inside presets come along.
|
||||
- Luminar looks: `.lmp` files and `.mplumpack` collections import as presets (grouped by collection); the sliders
|
||||
with a counterpart here come along, the rest is listed.
|
||||
- 23 new built-in presets: Portrait, Landscape, Urban, Food, Seasons, Vintage and B&W toners.
|
||||
- Importing XMP presets no longer lists bookkeeping fields (`Cluster`, `SortName`, `SupportsAmount2`, the as-shot
|
||||
white, empty Point Color slots…) as settings that couldn't be carried over.
|
||||
- A preset whose lens-profile switch is off no longer turns off the lens corrections built into a DNG (iPhone ProRAW
|
||||
and other files with embedded distortion / vignetting corrections), matching what the preset does elsewhere.
|
||||
- XMP presets apply their red / green / blue curves only when they also have the master curve and all three channel
|
||||
curves, as Lightroom does: a preset with just one channel curve (or no master curve) leaves the channels alone.
|
||||
- Imported `.cube` LUT profiles appear in the Profile menu and the profile browser, grouped by their folder, and stay
|
||||
favourites across restarts (issue #328).
|
||||
|
||||
### Library
|
||||
- Photos in Recently Deleted can be restored from the app: right-click ▸ Restore (or Delete Permanently), also in the
|
||||
Photo menu. The filmstrip has the photo context menu too. Adding a file again that is in Recently Deleted no
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ have none. So saving one photo never overwrites the other's metadata (`Session::
|
||||
LightCraft reads face, pet, focus and barcode regions in the Metadata Working Group's region schema
|
||||
(`mwg-rs:Regions`, `http://www.metadataworkinggroup.com/schemas/regions/`), as Lightroom, digiKam, Picasa and others
|
||||
write them, from sidecars and from XMP embedded in the file. Named faces become people in the People view
|
||||
(LR-LIB-PEOPLE in [`parity.md`](parity.md)), and every region is drawn as a box in the loupe.
|
||||
(LR-LIB-PEOPLE in [`parity-checklist.md`](parity-checklist.md)), and every region is drawn as a box in the loupe.
|
||||
|
||||
- **Read only.** LightCraft never writes `mwg-rs:Regions`; saving a sidecar keeps another application's regions byte
|
||||
for byte. Removing or resizing a box in the loupe changes the library only.
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ commands:
|
||||
pack square PNGs (<= 256 px) into a Windows .ico (see packaging/icons.sh)
|
||||
layers enforce the crate dependency layering (plan/architecture.md §3)
|
||||
parity [--write]
|
||||
check docs/parity.md (every cmd:/ctl: id and path it cites exists) and print the
|
||||
check docs/parity-checklist.md (every cmd:/ctl: id and path it cites exists) and print the
|
||||
Lightroom parity summary; --write refreshes the summary table in the document
|
||||
wasm cargo check --target wasm32-unknown-unknown for the wasm-safe crates (+ the web app)
|
||||
web [--serve [port]] [--dev]
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
//! `cargo xtask parity`: the Lightroom parity tracker (`docs/parity.md`).
|
||||
//! `cargo xtask parity`: the Lightroom parity tracker (`docs/parity-checklist.md`).
|
||||
//!
|
||||
//! - **Reference check** (in `ci`): every `` `cmd:<id>` `` must be a registered command (engine command specs, as
|
||||
//! listed by `lightcraft-cli commands --json`, or a UI command from `UI_COMMANDS`), every `` `ctl:<id>` `` a develop
|
||||
@@ -10,7 +10,7 @@
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
use std::path::Path;
|
||||
|
||||
pub const DOC: &str = "docs/parity.md";
|
||||
pub const DOC: &str = "docs/parity-checklist.md";
|
||||
const BEGIN: &str = "<!-- parity:summary -->";
|
||||
const END: &str = "<!-- /parity:summary -->";
|
||||
|
||||
|
||||
Reference in new issue
Block a user