mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-26 03:11:14 +00:00
Merge upstream/main into pr/overlay-windows (#1027 landed)
GPU handles(): only output-device proofs stay on the CPU; Show All Masks now renders zoom windows (upstream); proof-boundary tolerance in the GPU equivalence test; device-profile draft test. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
+13
-2
@@ -1,6 +1,6 @@
|
||||
# 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
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (`cargo xtask ci` reports the machine and skipped tests; `testkit`) · **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
|
||||
@@ -19,7 +19,7 @@ L5 depends on egui, eframe, winit or rfd, and that each crate only uses lower la
|
||||
| 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 |
|
||||
| L6 | `apps/lightcraft` (2.8k), `apps/lightcraft-cli` (1.5k), `apps/lightcraft-web` (3.4k), `xtask` (3.4k), `testkit` (0.2k, dev-dependency only) | Desktop app (eframe + wgpu, native menus, control server), CLI (render, commands, calibrate, snapshot, MCP), WASM build, tooling; test helpers (skips the CI report lists) |
|
||||
|
||||
## Data model
|
||||
|
||||
@@ -63,8 +63,19 @@ dispatch by id, and headless snapshots render the UI without a window.
|
||||
`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.
|
||||
|
||||
`ci` also probes the machine: OS, CPUs, RAM, the GPU adapters of each backend (from the ignored
|
||||
`gpu_probe` test of `lightcraft-gpu`, run after the workspace tests so it reuses their build; xtask
|
||||
has no wgpu), the corpus and `CRAFT_FONTS_DIR`. Tests
|
||||
that need what is missing call `lightcraft_testkit::skip!(need, reason)`, which appends a JSON line to
|
||||
the file `LIGHTCRAFT_SKIP_LOG` names. The run ends with the machine and the skips by need and reason,
|
||||
and writes `target/ci/report.json` (commit, dirty flag, machine, capabilities, each step's result and
|
||||
time, skips) and `target/ci/summary.md` (Markdown for a PR; `--summary-md` prints it). The report holds
|
||||
no host name, user name or absolute path, and nothing is uploaded. `--hardware` adds a step that runs
|
||||
the `lightcraft-gpu` tests once per backend with a hardware adapter (`LIGHTCRAFT_GPU_BACKEND`).
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-11 | minor | Quality gates: the CI machine probe, visible skips (`testkit`) and `target/ci/report.json` |
|
||||
| 2026-10-10 | major | Created from the code (crate sizes, layers, data model, rendering, control, gates) |
|
||||
|
||||
@@ -171,4 +171,22 @@ Raw decode only, 4 CPUs, release build, best of 3 wall-clock (2026-10-10). Metho
|
||||
| ILCE-7RM6 APS-C, Compressed (HQ) | 29.7 MB | 6592x4372 | 0.35 s |
|
||||
| ILCE-7RM6 APS-C, Compressed | 30.9 MB | 6592x4372 | 0.34 s |
|
||||
|
||||
The 1.0 s budget for the full-frame file is met. Parallelised: rayon over the tiles, over the 13 streams of each tile and over its 3 components.
|
||||
The 1.0 s budget for the full-frame file is met. Parallelised: rayon over the tiles, over the 13 streams of each tile and over its 3 components, and the colour reconstruction over rows.
|
||||
|
||||
2026-10-12 performance pass (output unchanged, bit for bit): the vertical wavelet pass lifts whole rows instead of gathering each column, `0^n 1` codes are counted with one `leading_zeros`, and the colour reconstruction reads rows as slices, in parallel. Same method, best of 5, the previous and the new decoder run alternately on the same machine (4 CPUs, which was busier than on 2026-10-10), best of two rounds:
|
||||
|
||||
| File | Before | After |
|
||||
|---|---|---|
|
||||
| ILCE-7RM6 FF, Compressed (HQ) | 0.56 s | 0.46 s |
|
||||
| ILCE-7RM6 FF, Compressed | 0.54 s | 0.38 s |
|
||||
| ILCE-7RM6 APS-C, Compressed (HQ) | 0.34 s | 0.23 s |
|
||||
| ILCE-7RM6 APS-C, Compressed | 0.35 s | 0.24 s |
|
||||
|
||||
2026-10-13 (output unchanged, bit for bit): the two halves of each stream, which are independent bit streams, decode in parallel; the vertical wavelet pass runs its rows in parallel; the horizontal pass lifts each row in place (scratch space reused per thread), rows in parallel, instead of allocating two vectors per row. Same method, best of 3, the previous and the new decoder run alternately, on another machine (Ryzen 7 9800X3D, a 4-CPU cgroup quota shared with other builds); CPU is the process CPU time of the decode (all threads):
|
||||
|
||||
| File | Before | After | CPU before | CPU after |
|
||||
|---|---|---|---|---|
|
||||
| ILCE-7RM6 FF, Compressed (HQ) | 0.60 s | 0.48 s | 1.14 s | 0.87 s |
|
||||
| ILCE-7RM6 FF, Compressed | 0.62 s | 0.48 s | 1.14 s | 0.89 s |
|
||||
| ILCE-7RM6 APS-C, Compressed (HQ) | 0.34 s | 0.23 s | 0.50 s | 0.40 s |
|
||||
| ILCE-7RM6 APS-C, Compressed | 0.31 s | 0.24 s | 0.51 s | 0.42 s |
|
||||
|
||||
@@ -33,7 +33,7 @@ guard.detail(&file_name);
|
||||
dead job never leaves a stuck bar. A worker that only reports progress takes a `TaskHandle` (`guard.handle()`,
|
||||
`Clone + Send`).
|
||||
- **`kind`** is a stable camelCase id that agents filter by (`export`, `import`, `scan`, `sync`, `previews`,
|
||||
`download`, `faces`…). **`label`** is a short English name in sentence case ("Building previews"). The stack shows it
|
||||
`download`, `faces`, `cache`, `focus`…). **`label`** is a short English name in sentence case ("Building previews"). The stack shows it
|
||||
translated, so add it to every catalog in `crates/ui-egui/locales/`.
|
||||
- **Progress:** `progress(done, total)`. A `total` of 0 means the amount of work isn't known yet, and the bar sweeps.
|
||||
`set_unit(Unit::Bytes)` makes the count read "12 of 340 MB"; `Unit::Percent` reads "40 %". The default `Unit::Count`
|
||||
@@ -55,10 +55,12 @@ guard.detail(&file_name);
|
||||
|---|---|---|
|
||||
| Export, contact sheet | `crates/ui-egui/src/export_task.rs` | adopt the job's flag; update the row each frame |
|
||||
| Build Previews | `crates/engine/src/cmd/previews.rs` | move the guard into the worker thread |
|
||||
| Slideshow export | `crates/engine/src/cmd/slideshow.rs`, `crates/engine/src/slideshow_export.rs` | an engine command that owns its worker and row; progress from the worker through a `TaskHandle`; results read back by command |
|
||||
| Model downloads | `crates/engine/src/face_download.rs` | report progress through a `TaskHandle` in shared state |
|
||||
| Lightroom catalog import | `crates/ui-egui/src/lightroom_import.rs` | stop being cancellable for a phase that must finish |
|
||||
| Face scan, AI Denoise | `crates/engine/src/cmd/face_recognize.rs`, `crates/engine/src/denoise.rs` | a continuous job with no ✕, kept in session state |
|
||||
| Find Missing Photos | `crates/ui-egui/src/tasks.rs` | a generic background task with a row (`kind: Some(..)`) |
|
||||
| Reading focus points | `crates/engine/src/focus_scan.rs` | a worker paced by the UI's per-frame pump (`focus.pump {pace}`); `Cancel::Flag`; commits in batches without undo steps |
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Sony ARW, Nikon NEF, Panasonic RW2, Fujifilm RAF, Canon CR3/CR2, Pentax PEF, Samsung SRW and Olympus ORF starting look
|
||||
# Sony ARW, Nikon NEF, Panasonic RW2, Fujifilm RAF, Canon CR3/CR2, Pentax PEF, Samsung SRW, Olympus ORF and Epson ERF starting look
|
||||
|
||||
ARW, NEF, RW2, RAF, CR3, CR2, PEF, SRW and ORF decoding supply sensor data and camera white-balance multipliers, but currently no measured camera colour matrix. Treating camera RGB as linear sRGB produces a dark, muted default rendering. The loader now estimates a file-local starting look from that file's embedded camera JPEG, only when a usable camera matrix is absent. All output pixels still come from the RAW sensor data; there is no JPEG replacement or uniform saturation boost.
|
||||
ARW, NEF, RW2, RAF, CR3, CR2, PEF, SRW, ORF and ERF decoding supply sensor data and camera white-balance multipliers, but currently no measured camera colour matrix. Treating camera RGB as linear sRGB produces a dark, muted default rendering. The loader now estimates a file-local starting look from that file's embedded camera JPEG, only when a usable camera matrix is absent. All output pixels still come from the RAW sensor data; there is no JPEG replacement or uniform saturation boost.
|
||||
|
||||
## Colour and tone are separate
|
||||
|
||||
@@ -17,7 +17,9 @@ Matrix-only and matrix + table looks are each completed (tone curve, then chroma
|
||||
|
||||
The matrix is applied to scene-linear sensor pixels. The curve is carried in `SourceInfo` and applied in the pipeline finish stage, after exposure/WB/local edits. It is never baked into decoded luminance or clipped to JPEG precision. CPU and GPU use the same tone LUT. Contrast, whites and blacks adjust the starting look through the display-domain controls. JPEG neutral rendering and the existing DNG colour model are unchanged.
|
||||
|
||||
One third of the pixels are held out from both fits. The combined model must reduce linear-display squared error by at least 30% and have per-channel RMS error ≤0.10 (0.055 rejected half of the public raw.pixls.us samples tried — ILCE-6400, -6700, -7M4 — whose fits were still 1.5–3× closer to the camera JPEG than the fallback and visibly better). When the fit on all pixels fails these gates, it is tried once more, with the same gates, on the pixels away from edges (where the 3×3 neighbourhood in either proxy spans a luminance ratio above 3). Many camera JPEGs are lens-corrected while the raw is not (Sony "Distortion Comp.: Auto", compacts and kit zooms), and on a detailed scene the misaligned edges alone fail the gate although the colours agree everywhere else (issue #232). The public ILCE-7RM2 samples (raw.pixls.us, one façade shot in seven compression/correction variants, 24–70 mm at 51 mm) are up to 15 px of 1440 off their JPEG; the six with distortion correction on missed the gate at held-out RMS 0.108–0.115 and opened in the grey neutral fallback, 13 L* too dark (ΔE76 16.6–16.9 against the JPEG after registering its geometry). Away from edges they pass at 0.049–0.052 and land at ΔE 3.7–3.8 with lightness within 0.6 L*, like the variant shot with distortion correction off (0.059 on all pixels, ΔE 3.9). The corpus GX80 kit-zoom sample (up to 63 px of 1440 off) passes too: 0.107 → 0.081, ΔE 19.1 → 7.9. Fits accepted on all pixels are unchanged. These are provisional acceptance gates, not a colour-accuracy certification. Singular, unrelated and aspect-mismatched references retain the documented fallback; poor-fitting ones get the partial look below when it is clearly closer to the camera JPEG, and black-and-white ones only their tone curve (below). Both fits use the same fixed proxy at every decode resolution.
|
||||
One third of the pixels are held out from both fits. The combined model must reduce linear-display squared error by at least 30% and have per-channel RMS error ≤0.10 (0.055 rejected half of the public raw.pixls.us samples tried — ILCE-6400, -6700, -7M4 — whose fits were still 1.5–3× closer to the camera JPEG than the fallback and visibly better). When the fit on all pixels fails these gates, it is tried once more, with the same gates, on the pixels away from edges (where the 3×3 neighbourhood in either proxy spans a luminance ratio above 3). Many camera JPEGs are lens-corrected while the raw is not (Sony "Distortion Comp.: Auto", compacts and kit zooms), and on a detailed scene the misaligned edges alone fail the gate although the colours agree everywhere else (issue #232). Sony's embedded lens tables now correct ILCE-7RM6 renders under Enable Lens Corrections ([Sony ARW lens corrections](sony-ilce7rm6-lens-corrections.md)), but this fit still matches its pairs without them (the sensor proxy is uncorrected); aligning the pairs first is a follow-up. The public ILCE-7RM2 samples (raw.pixls.us, one façade shot in seven compression/correction variants, 24–70 mm at 51 mm) are up to 15 px of 1440 off their JPEG; the six with distortion correction on missed the gate at held-out RMS 0.108–0.115 and opened in the grey neutral fallback, 13 L* too dark (ΔE76 16.6–16.9 against the JPEG after registering its geometry). Away from edges they pass at 0.049–0.052 and land at ΔE 3.7–3.8 with lightness within 0.6 L*, like the variant shot with distortion correction off (0.059 on all pixels, ΔE 3.9). The corpus GX80 kit-zoom sample (up to 63 px of 1440 off) passes too: 0.107 → 0.081, ΔE 19.1 → 7.9. Fits accepted on all pixels are unchanged. These are provisional acceptance gates, not a colour-accuracy certification. Singular, unrelated and aspect-mismatched references retain the documented fallback; poor-fitting ones get the partial look below when it is clearly closer to the camera JPEG, and black-and-white ones only their tone curve (below). Both fits use the same fixed proxy at every decode resolution.
|
||||
|
||||
**Lens-corrected camera JPEGs.** Some raws carry the camera's own lens correction (Fujifilm and Panasonic tables, the ILCE-7RM4A, Nikon's NikonNEFInfo) and the camera often applies it to its JPEG. Nikon Z lenses always do, and that JPEG can be zoomed in by up to 9% to fill the frame. The fit used to pair the uncorrected sensor with the corrected JPEG, so near the edges it compared pixels from different parts of the scene. Now the sensor proxy is also warped with the file's correction (`into_lens_geometry`, pixels that land outside the picture are dropped), and the fit uses whichever of the two lines up better with the JPEG, going by the correlation of their high-passed log luminance. Files whose JPEG isn't corrected keep the plain proxy. On the 29 CC0 corpus raws with a warp the alignment goes up by 0.13 on average (Panasonic GX80 0.41 to 0.83, Fujifilm X-T20 0.44 to 0.95). Mean ΔE against the camera JPEG over the 35 corpus raws of those formats goes from 3.73 to 3.61, and on 299 private Z 6II photos with Nikon's correction read it goes from 3.22 to 2.68.
|
||||
|
||||
**A partial look when the full look misses the gates.** The neutral fallback (camera RGB taken as sRGB, the default tone map) is far from the camera JPEG. Rendered for every photo on this path in the CC0 archive (1,150 files with a camera JPEG), it is 10.7 L\* too dark (median; about one stop), keeps 0.36 of the camera's colourfulness and has hues 7° off on the coloured pixels (median CIEDE2000 13.6). Its white balance is right: on the pixels the camera renders near-neutral the cast is under 1 a\*/b\* (median, every maker). The "blue" fallback on newer Sony bodies (Δb\* −22 over the whole frame on the ILCE-7RM5 sample) is a warm scene losing its colour, not a cast: its near-neutral pixels are within −1.6 b\*. So before falling back, a partial look is fitted (`fit_partial`): the quantile tone curve (registration-free, the largest part of the error), the chroma curve, and, when the scene has enough colour to learn a matrix (the full look's condition), the photo's own colour matrix at half weight, the other half the identity (`PARTIAL_MATRIX_WEIGHT`). No hue/saturation table. Half weight because, on the held-out proxy pixels of the 23 colourful photos without a look, the full matrix left 2 of them more than 2° further from the camera's hues than the neutral fallback and half weight none (median hue error 9.6° with the generic colour, 5.1° at half weight, 4.2° at full weight; on the 1,080 photos with a look 3.9° and 2.7°). Without a matrix (tone and chroma curve alone, or with one global saturation scale) about a third of all photos ended up more than 2° further from the camera's hues than the fallback, as the added colour makes the generic matrix's hue errors visible. The partial look is tried on all pixels, then away from edges, and used only when it cuts the held-out squared error below 0.7 of the neutral fallback's in linear and in gamma-encoded display values, and when the JPEG's luminance ranks the pixels like the scene's (Spearman ≥ 0.5, `PARTIAL_MIN_RANK_CORRELATION`): a curve matched to the brightness of an unrelated picture also beats the dark fallback pixel for pixel. The accepted full looks have 0.55 or more; three old Coolpix files whose raws decode wrongly have 0.07–0.27 and keep the fallback. There is no limit on the partial look's own error. On the archive (1,783 renders): all 1,087 full looks are byte-identical; of the 55 photos that reach the partial fit, 49 get it (40 on all pixels, 9 away from edges; 13 with the damped matrix, 41 with a chroma curve) and 6 keep the fallback (lens-corrected compacts: RX10, TZ80 1:1, D-LUX 4, G10 16:9, GF2 ×2). On the 49, median CIEDE2000 to the camera JPEG 14.0 → 2.1, ΔL\* −11.5 → +0.6, colourfulness 0.36 → 0.87, hue error 10.1° → 7.1°; every one is closer, by at least 1.3. Most of the others without a look never reach a fit: on 48 files (Nikon D4, Df, D300/D300S, D7000, D5100 and others) the camera JPEG proxy comes out a pixel narrower than the sensor proxy and no pairs are collected (the resize in PR #531 fixes this; with it 46 of them pass the full look's gates, CIEDE2000 17.9 → 2.9).
|
||||
|
||||
@@ -111,7 +113,7 @@ A pooled profile was tried and is not bundled. Pooling the 46 photos (158,549 co
|
||||
|
||||
One photo can show too little of a colour for its own fit to learn it: in a second shot of the lime shirt only a few dozen proxy pixels show it, next to a hillside of foliage at the same hue that the camera renders differently, and the shirt stayed yellow (hue 68° against the JPEG's 82°; a 192-pixel proxy only reached 74°). `lightcraft-cli calibrate [--max N] [--out DIR] FOLDERS…` therefore pools the colour pairs of many ARWs, NEFs or RAFs per camera model — each against its own embedded JPEG, at a 192-pixel proxy, at most 4000 pairs per photo, files spread evenly over the folders — and fits one matrix (from white-balanced camera RGB, so no single photo's white point is baked in) and one hue/saturation/value table. Models need at least 5 usable photos.
|
||||
|
||||
Profiles are JSON files `<model>.json` in `$LIGHTCRAFT_CAMERA_PROFILES`, else `<config>/camera-profiles` (macOS `~/Library/Application Support/LightCraft/camera-profiles`); a local profile replaces a built-in one. Built-in profiles live in `assets/camera-profiles/` (listed in `assets/ATTRIBUTION.md`) and are compiled in, so the app, CLI and web build share them: ILCE-7M4, fitted to 597 photos (2.2 million colour pairs) shot in 2026, mostly with the Standard creative style and DRO Auto; ILCE-7CR, 125 photos (below); X-H2S, 201 photos; X-T4, 545 photos. They hold aggregate colour statistics only. A photo of a profiled model takes its colour from the profile and fits only its own tone and chroma curves (picture styles vary per shot; with Sony's DRO on, that tone curve is then lowered as described below); the acceptance gates still apply. A rejected profile fit retries the photo's own colour and tone fit before falling back to neutral rendering. Files are read once per process and validated (version, bounded invertible matrix, table shape and finite data); a damaged file is ignored with a warning. The profiles folder's contents are part of the render cache keys, so thumbnails rendered before a profile existed are redone; smart previews built before keep their colour until rebuilt.
|
||||
Profiles are JSON files `<model>.json` in `$LIGHTCRAFT_CAMERA_PROFILES`, else `<config>/camera-profiles` (macOS `~/Library/Application Support/LightCraft/camera-profiles`); a local profile replaces a built-in one. Built-in profiles live in `assets/camera-profiles/` (listed in `assets/ATTRIBUTION.md`) and are compiled in, so the app, CLI and web build share them: ILCE-7M4, fitted to 597 photos (2.2 million colour pairs) shot in 2026, mostly with the Standard creative style and DRO Auto; ILCE-7CR, 125 photos, and ILCA-99M2, 144 photos (both below); X-H2S, 201 photos; X-T4, 545 photos; NIKON Z 6_2, 296 photos; NIKON Z 8, 261 photos; NIKON D5300, 264 photos (below). They hold aggregate colour statistics only. A photo of a profiled model takes its colour from the profile and fits only its own tone and chroma curves (picture styles vary per shot; with Sony's DRO on, that tone curve is then lowered as described below); the acceptance gates still apply. A rejected profile fit retries the photo's own colour and tone fit before falling back to neutral rendering. Files are read once per process and validated (version, bounded invertible matrix, table shape and finite data); a damaged file is ignored with a warning. The profiles folder's contents are part of the render cache keys, so thumbnails rendered before a profile existed are redone; smart previews built before keep their colour until rebuilt.
|
||||
|
||||
|
||||
### Sony ILCE-7CR
|
||||
@@ -122,6 +124,39 @@ Without a profile, 123 of the 131 photos accept their own fit; the other 8 open
|
||||
|
||||
The nine public raw.pixls.us ILCE-7CR files are one scene in every coding the camera writes (uncompressed, lossless compressed L, M and S, compressed, full frame and APS-C crop). They were not used for fitting. All nine accept their own fit at ΔE 1.3–2.1 and stay accepted with the profile, at ΔE 1.5–2.9 (mean 1.59 → 1.99). On this colourful daylight scene the per-file fit is already close. The subsampled M and S codings, which decode with unity white-balance gains, move most (2.0 → 2.8). This is a camera-JPEG look estimate like the others, not measured calibration or Lightroom parity.
|
||||
|
||||
### Sony ILCA-99M2
|
||||
|
||||
Fitted from 144 usable photos of 150 ILCA-99M2 ARWs (one photographer, seven shooting days, Standard creative style, DRO Auto, ISO 100–1600, compressed ARW, no in-camera distortion correction; Zeiss 24–70 mm F2.8 and 85 mm F1.4, Tamron and Sigma lenses), 501,511 colour pairs; the other six, one dark and nearly colourless indoor series, gave no usable colour pairs. Measured as for the ILCE-7CR.
|
||||
|
||||
Without a profile all 150 photos accept their own fit (ΔE 1.8–13.5). For validation every fifth photo in sorted name order (30) was withheld and a profile fitted to the other 120 (115 usable). On the withheld photos mean ΔE went from 5.11 with per-file fitting to 4.87 with the profile; 25 of 30 improve (by up to 0.8), the largest regression is 0.24. With the final profile all 150 photos stay accepted, mean ΔE 4.62 → 4.45 (in-sample). The one public raw.pixls.us ILCA-99M2 file (Standard, DRO Auto; not used for fitting) is accepted with and without the profile, ΔE 5.57 → 5.73. Seven shooting days are a narrow sample of scenes and light; this is a camera-JPEG look estimate like the others, not measured calibration or Lightroom parity.
|
||||
|
||||
### Canon EOS R7 and EOS R6 Mark II
|
||||
|
||||
With CR3 and CR2 input to `calibrate` (#1073), tried on one photographer's library (CR3, RAW and C-RAW, October 2025 to September 2026) and measured as above, against each file's own full-size embedded JPEG (6960 × 4640 R7, 6000 × 4000 R6 Mark II):
|
||||
|
||||
- Held out: 40 photos per body from different shoots, every fifth withheld (8 per body), profiles fitted on the other 32 (30 R7 photos with 107,286 colour pairs, 28 R6 Mark II with 93,200; both with a hue/saturation table). On the withheld photos the profile changes little: R7 mean ΔE 2.52 → 2.57 (median 2.37 → 2.25; 3 better, 3 worse, 2 unchanged; largest regression +0.51 on an almost colourless photo), R6 Mark II 6.12 → 6.09 (median 5.73 → 5.50; 3 better, 4 worse, 1 unchanged; largest regression +0.48, best gain −0.67). Mean ΔL\* 0.00 (R7) and +0.57 (R6 Mark II) either way. Not bundled.
|
||||
- The profile only replaces the colour inside an accepted per-photo fit (`fit_preview`), so a photo whose own fit is rejected renders the neutral fallback with or without it: 2 of the 16 withheld photos (one per body), plus one with a black-and-white camera JPEG, rendered identically both ways. Unlike the ILCE-7CR, where the profile rescued every rejected photo, here it cannot.
|
||||
- Library-wide (`--max 600` over 35,796 CR3s): 410 R7 photos (1.39 million pairs), 119 R6 Mark II (386k) and 38 EOS R100 (129k) gave profiles; 32 photos had no usable camera JPEG or colour (mostly moon, night and other near-colourless scenes) and one did not decode. The R6 Mark II writes its Exif model as "Canon EOS R6m2", the profile's file name too.
|
||||
- Decoding: 4 of the R6 Mark II C-RAW files tried (3 of 40 sampled, 1 of 119 in the library run) are refused with "unsupported raw variant: Canon CRX adaptive QP value 172" (or 175) and open preview-only.
|
||||
|
||||
### Nikon Z 6II
|
||||
|
||||
Fitted from 296 usable photos of 299 Z 6II NEFs (one photographer, 2024 to 2026, Standard and Auto picture controls, lossless 14-bit, with the NIKKOR Z 20mm f/1.8 S, Z 24-70mm f/4 S and the AF-S 70-200mm f/2.8G on the FTZ), 1,099,207 colour pairs. The pairs were collected with Nikon's in-file distortion correction read and the sensor proxy following it (see "Lens-corrected camera JPEGs" above), since the camera corrects every JPEG from these lenses. Measured as above: rendered at 1200 px with `lightcraft-cli render`, mean CIE76 ΔE against each file's embedded JPEG at 200 px.
|
||||
|
||||
For validation every fifth photo in sorted name order (59) was held back and a profile fitted to the other 240 (237 usable). On the held-back photos mean ΔE went from 2.73 with per-file fitting to 2.54 with the profile (median 2.49 to 2.21), 43 closer and 8 farther, the largest by 0.64. With the final profile across all 299 photos it goes from 2.68 to 2.53, but that's in-sample. The few that get noticeably worse are ISO 25600 night shots (up to +2.5), where the camera JPEG's noise reduction changes the colour a lot and a per-photo fit does better.
|
||||
|
||||
The public raw.pixls.us Z 6II file (`nef-nikon-z6ii-lossless.nef`, Vivid picture control with the Z 24-200, not used for fitting) is accepted with the profile and goes from 5.37 to 5.25.
|
||||
|
||||
### Nikon Z 8
|
||||
|
||||
Fitted from 261 usable photos of 278 Z 8 NEFs (one photographer, 2023 and 2026, almost all Standard picture control, lossless 14-bit, with the NIKKOR Z 24-120mm f/4 S and the AF-S 70-200mm f/2.8G on the FTZ; the High Efficiency files can't be decoded and were skipped), 969,860 colour pairs, collected the same way as the Z 6II's with Nikon's distortion correction read. Holding back every fifth photo (55) and fitting the other four fifths, mean ΔE on the held-back photos went from 2.55 to 2.33 (median 2.31 to 2.16), 39 closer and 10 farther, the largest by 0.46. The public raw.pixls.us Z 8 file (`nef-nikon-z8-lossless.nef`, Z 14-24 f/2.8 S, not used for fitting) is accepted with the profile and stays about the same, 3.22 to 3.27.
|
||||
|
||||
### Nikon D5300
|
||||
|
||||
Fitted from 264 usable photos of 273 D5300 NEFs (one photographer, 2014 to 2017, mostly Standard picture control with some Portrait and Landscape, lossy 12-bit, nearly all with the AF-S DX 35mm f/1.8G), 964,687 colour pairs. On the 53 held-back photos mean ΔE went from 2.86 to 2.66 (median 2.78 to 2.60), 44 closer and 6 farther, the largest by 0.63. There's no public D5300 sample in the corpus to check it against.
|
||||
|
||||
The same was tried for the photographer's D700, D750 and D80 (about 300 photos each) and it didn't help: on held-back photos the D750 stayed at 3.2 and the D700 and D80 got slightly worse, even fitting only their Standard (or normal saturation) photos. Their per-photo fits are already close and those bodies were shot with a mix of picture controls, so they have no profile.
|
||||
|
||||
## Sony Dynamic Range Optimizer (DRO)
|
||||
|
||||
Sony bodies apply DRO, a local tone operator that brightens darker regions, to their JPEG (and the preview embedded in the ARW) only; the raw data are unchanged, and the factory default is DRO Auto. The tone curve fitted to that JPEG carried the brightening into the raw's starting look, so DRO photos opened lighter than in Lightroom, darktable, Photomator or Affinity, which develop the raw without it (issue #244). On 24 ILCE-7CR photos (Standard creative style) with Lightroom 9.5.1 default exports, mean L* at 200 px: with DRO off, Lightroom matches the camera JPEG (+0.15 L*, all within ±1.4) and LightCraft matches Lightroom (−0.19 L*, median ΔE76 3.6); with DRO Lv3 or Auto (8 photos), Lightroom is 2.4–10.7 L* darker than the camera JPEG and LightCraft followed the JPEG, +6.4 L* from Lightroom (median ΔE76 7.5). The tone curves fitted to 131 ILCE-7CR photos show where: at scene luminance 0.01, 0.02, 0.05 and 0.1 the median DRO Lv3/Auto curve is 8, 10, 9 and 6 L* above the DRO-off one, and from 0.3 up they agree.
|
||||
@@ -138,7 +173,11 @@ For 52 camera models LightCraft has colour matrices fitted to the camera's measu
|
||||
(`crates/raw/src/spectral.rs`, generated into `spectral_table.rs` by `tools/spectral_camera_table.py` from
|
||||
[rawtoaces-data](https://github.com/AcademySoftwareFoundation/rawtoaces-data) v1.1.0, Apache-2.0): 22 Canon, 11 Nikon,
|
||||
11 Sony, 3 Fujifilm and 5 others, plus the other names rawtoaces-data lists for them (EOS Rebel T3i and Kiss X5 for
|
||||
the EOS 600D; bodies it lists as sharing a sensor, such as the GFX100S with the GFX 100). Per model the generator fits,
|
||||
the EOS 600D; bodies it lists as sharing a sensor, such as the GFX100S with the GFX 100), and the bodies `SAME_SENSOR`
|
||||
in `spectral.rs` adds by hand because the table is generated: Fujifilm's 26.1 MP X-Trans CMOS 4 bodies (X-T30, X-T30 II,
|
||||
X-Pro3, X100V, X-S10, X-E4) take the X-T3's matrices. Without them an X-T30 raw whose camera JPEG was shot in Acros
|
||||
(black and white) got its tone curve on the muted neutral fallback, with a grey sky where the scene had a deep blue
|
||||
one. Per model the generator fits,
|
||||
under CIE Standard Illuminant A and under D65, a white-preserving 3×3 from white-balanced camera RGB to XYZ by the
|
||||
least mean CIE76 error over rawtoaces-data's 190 training reflectances, and writes DNG `ColorMatrix1/2` and
|
||||
`ForwardMatrix1/2`. The existing DNG colour model then interpolates them for the file's as-shot white, which the
|
||||
@@ -184,16 +223,40 @@ A merge (HDR, panorama, HDR panorama) writes a linear DNG of the sources' camera
|
||||
tags. A raw without colour matrices of its own has none to give, so its merge used to render with no camera colour: an
|
||||
HDR merge of CR2s came out green and dark (issue #965). Each source now goes through `starting_colour` as when it is
|
||||
opened alone, and `starting_colour_tags` writes the result as DNG tags: one forward matrix (from the look's matrix on
|
||||
top of the camera transform) with a colour matrix and `AsShotNeutral` that agree with it at the as-shot white, the
|
||||
look's brightness of white as baseline exposure, its hue/saturation table as `ProfileHueSatMap` and its tone curve as
|
||||
`ProfileToneCurve`. Raws with their own matrices (DNG) keep their tags. Without a look the tags give the colour the raw
|
||||
falls back to (spectral matrices or the neutral fallback).
|
||||
top of the camera transform) with `AsShotNeutral`, the look's brightness of white as baseline exposure, its
|
||||
hue/saturation table as `ProfileHueSatMap` and its tone curve as `ProfileToneCurve`. Raws with their own matrices (DNG)
|
||||
keep their tags. Without a look the tags give the colour the raw falls back to (spectral matrices or the neutral
|
||||
fallback).
|
||||
|
||||
The colour matrices declare the white balance the source shows (`files::WbScaleOf::dng_white`), so the DNG opens at the
|
||||
source's As Shot temperature and tint and a white-balance edit starts from there: the camera's measured matrices
|
||||
(`lightcraft_raw::spectral`) when they give the source's scale, which reads every white as the source does; else a
|
||||
matrix under which the as-shot neutral is the white the source's scale shows (Sony's presets' reading, 6500 K / 0 on
|
||||
the relative scale, the file's own white otherwise). The forward matrix is used only with the as-shot neutral, so the
|
||||
render at As Shot doesn't depend on them. A colour matrix derived from the forward matrix, as first written, declared
|
||||
wherever the look and the generic camera model put the white: merges of real ILCE-7M3 brackets opened at 6113–7307 K /
|
||||
+115 where the ARWs show 3932–5268 K / +7, and any white-balance edit turned them green (CIEDE2000 11–13 against the
|
||||
ARW at the same Temp/Tint). With the measured matrices they open at the ARWs' As Shot, and the same Temp/Tint renders
|
||||
within CIEDE2000 0.8–1.7 of the ARW for most changes, about 5 for the largest (5268 → 3200 K, 3932 → 6500 K): the ARW
|
||||
adapts its fitted look with Bradford, the DNG rebalances in camera space.
|
||||
|
||||
The DNG renders close to, not exactly like, the source: a DNG hue/saturation table doesn't keep each pixel's luminance
|
||||
as the fitted table does, and the chroma curve has no DNG tag, so it is left out. On two CC0 CR2s (EOS 550D, 40D), an
|
||||
HDR merge of three copies of the photo against the photo alone (200 px, CIE76): mean ΔE 1.07 and 0.47, 95th
|
||||
percentile 2.65 and 1.15 (26 and 23 before, with no colour tags; 1.47 and 0.66 with the table left out too).
|
||||
|
||||
A raw whose white balance is only in its vendor multipliers (CR2, NEF, ARW…) has no `AsShotNeutral` of its own, so a
|
||||
frame carries the multipliers (`Frame::wb_multipliers`) next to its colour tags. A panorama, and an HDR merge from its
|
||||
inputs, takes its white balance from the frames that are in it: the median R/G and the median B/G of their multipliers
|
||||
(the mean of the middle two for an even count; frames without usable multipliers, or outside the panorama, do not
|
||||
vote), written as `AsShotNeutral`, the reciprocal. Any `AsShotWhiteXY` of the source is dropped with it: a reader takes
|
||||
it first, and the DNG spec has the two exclude each other. So the result is balanced for what the camera measured for
|
||||
most of its frames, not for whichever frame came first; an HDR panorama's merged brackets vote with their bracket's
|
||||
median. With no multipliers anywhere (DNG sources) the reference or first frame's tags are kept as before. For frames
|
||||
balanced alike this is the neutral `starting_colour_tags` already wrote, so the merged DNG renders as before; it matters
|
||||
when the camera balanced the frames differently, and for a caller that loads frames without a colour hook
|
||||
(`load_frame`), whose raw frames carried no white balance at all (issue #1144).
|
||||
|
||||
## Nikon crop and preview colour metadata
|
||||
|
||||
Nikon maker-note `CropArea` (0x0045) supplies the default `[left, top, width, height]` crop. The decoder validates the rectangle against the active sensor area and falls back to that area for missing or invalid values. The CFA origin is unchanged; cropping follows demosaicing.
|
||||
|
||||
@@ -80,10 +80,21 @@ filmstrip is visible.
|
||||
| `ui.resize` | `{width, height}` | Resize the window |
|
||||
| `ui.zoomFactor` | `{factor}` | Set the interface scale (0.5–3; egui's zoom keys are off, Cmd+= / Cmd+- zoom the photo) |
|
||||
| `ui.screenshot` | `{path?, headless?}` | `{path, width, height}` once the frame (with finished renders) is captured. `headless: true` draws the UI on the CPU (no compositor needed); a windowed capture that gets no frame within 2 s falls back to headless automatically. While the loupe still waits for a render, `ui.widgets {filter: "loupe:rendering"}` lists its "Rendering…" pill; `loupe:renderFailed` is the pill saying a render failed behind a stand-in; Compare and Reference panes have their own (`compare:rendering:<pane>`, `compare:renderFailed:<pane>`) |
|
||||
| `engine.execute {command: "app.export", params}` | export params (see `docs/mcp.md`), plus `preset`, `dir` / `path`, `ids`, `background` | Writes the files and returns `{files}` (one `{path, width, height, bytes, sidecars}` per file, plus `gpuFallback` — why that render fell back from the GPU to the CPU — when it did; see `docs/gpu-pipeline.md`); with `background: true` (what the Export dialog and menus use) it returns `{background: true, total}` at once and the batch runs on a worker thread — poll `ui.inspect` → `export` |
|
||||
| `engine.execute {command: "app.export", params}` | export params (see `docs/mcp.md`), plus `preset`, `dir` / `path`, `ids`, `background`; `destinationMode: "sameAsOriginal"` writes each photo into its original's folder (+ `subfolder`) instead of `dir` | Writes the files and returns `{files}` (one `{path, width, height, bytes, sidecars}` per file, plus `gpuFallback` — why that render fell back from the GPU to the CPU — when it did; see `docs/gpu-pipeline.md`); with `background: true` (what the Export dialog and menus use) it returns `{background: true, total}` at once and the batch runs on a worker thread — poll `ui.inspect` → `export` |
|
||||
| `engine.execute {command: "activity.list"}` | — | The long-running tasks in flight (imports, exports, preview builds, downloads, the face scan…), oldest first: `{tasks: [{id, kind, label, done, total, unit, detail, cancellable, cancelling, ageMs}]}`; `total` 0 = not known yet; `unit` is `count`, `bytes` or `percent`; `label` is English (the app shows it translated) |
|
||||
| `engine.execute {command: "activity.cancel"}` | `{id}` or `{all: true}` | Asks the task (or every cancellable one) to stop at its next file or photo → `{cancelled: n}`; an unknown id (it may have just finished) or a task that can't be cancelled is an error |
|
||||
| `ui.render` | `{id?, size?, path?}` | Render a photo (PNG to `path`), `{width, height}` |
|
||||
| `engine.execute {command: "slideshow.layout"}` | `{margins?, marginLeft?, …, zoomToFill?, strokeBorder?, castShadow?, backdropColor?, colorWash?, backgroundImage?, …}` (see `engine.commands`) | The slideshow's slide layout (Layout, Options, Backdrop), saved with the library; omitted keys keep their value, `{}` reads it; out-of-range numbers are clamped, a wrong type or unknown key is refused and nothing changes |
|
||||
| `engine.execute {command: "slideshow.overlays"}` | `{identityPlate?: {enabled?, text?, image?, size?, color?, opacity?, anchor?, offsetX?, offsetY?, relativeTo?, behind?}, ratingStars?: {enabled?, color?, size?, anchor?, …}, texts?: [{text?, size?, color?, opacity?, anchor?, offsetX?, offsetY?, relativeTo?, shadow?, shadowOpacity?, shadowOffset?, shadowRadius?, shadowAngle?}], addText?, removeText?, showWatermark?, watermark?}` (see `engine.commands`) | The overlays drawn on every slide, saved with the library: sizes and offsets are fractions of the slide's shorter side, anchors `topLeft`…`bottomRight` of the `slide` or the `photo`; text overlays expand tokens (`{caption}`, `{exposure}`, `{date}`, the file-naming tokens…; unknown tags show as typed); `watermark` takes the export watermark's keys. Replies with the settings and `warnings` |
|
||||
| `engine.execute {command: "slideshow.titles"}` | `{intro?: screen, ending?: screen}`, a screen being `{enabled?, color?, content?: "none"\|"identityPlate"\|"text", text?, overrideColor?, textColor?, scale?, duration?: seconds\|null}` | The intro and ending screens, saved with the library: a background colour and, centred, the Overlays identity plate or the screen's own text, in the plate's colour or `textColor` when `overrideColor` is on, `scale` = its height as a fraction of the slide's shorter side; `duration` null = the slide duration. The intro plays once before the first photo, the ending after the last when repeat is off. Replies with the settings and `warnings` |
|
||||
| `engine.execute {command: "slideshow.preview"}` | `{id?, title?, template?, width?, height?, path?}` | One slide composed with the layout and overlays, as the slideshow plays it (with `template: id`, with that template's settings instead, leaving the library's alone: the Template Browser's hover preview) (with `title: "intro"\|"ending"`, that title screen instead → `{title, enabled, width, height, plate}`): a PNG written to `path`, or returned base64 in `png` without one; `{id, width, height, cell, photo, overlays}` (`cell` and `photo` are `[x0, y0, x1, y1]` in slide pixels; `overlays` lists `{kind, box}` for each drawn overlay). Sides 16–4096; one side given takes the other from the aspect preview |
|
||||
| `engine.execute {command: "slideshow.templates.list"}` | `{}` | The Template Browser: `{templates: [{id, name, builtin, group, description?, path?}], previous, folder, problems}` — built-ins (`builtin:…`, our own designs) then user templates (`user:<file>`, files in `<settings>/slideshow-templates`, at most 1000); `problems` lists files skipped and why |
|
||||
| `engine.execute {command: "slideshow.templates.apply"}` | `{id}` or `{name}`; `{id: "previous"}` | Replaces the playback (prepare previews kept), layout, overlays and titles settings with the template's, saved with the library. No undo: the replaced settings become `previous` for the session → `{applied, name, warnings, previous, settings}` (`warnings`: a background photo not in this library, an unreadable plate or watermark image…) |
|
||||
| `engine.execute {command: "slideshow.templates.save"}` / `update` / `rename` / `delete` | `{name, replace?}` / `{id}` / `{id, name}` / `{id}` | Save the current settings as a user template (`<name>.json`; path separators and reserved characters become `_`, a taken or built-in name is refused unless `replace`), update one with the current settings, rename (its file follows), delete. Built-ins can't change |
|
||||
| `engine.execute {command: "slideshow.templates.import"}` / `export` | `{path}` / `{id, path}` | Import a template `.json` (at most 256 KB; format, version and every setting checked; a taken name gets " (2)") → `{id, name, renamed, warnings}`; export any template as `.json` |
|
||||
| `engine.execute {command: "slideshow.export"}` | `{format: "pdf"\|"jpeg"\|"video", path, size?, quality?, fps?, container?: "mp4"\|"webm", fullScreen?, speed?, name?, ids?, wait?}` | The slideshow (the photos in view, or `ids`, as composed slides between the intro and ending screens that are on) as a PDF (one page per slide; `size` = long side 64–8192 px, default 1920), a JPEG sequence (`path` = the folder, files `<name>-001.jpg`…) or AV1 video in MP4 / WebM (`size` = frame height 64–2160 or `"720p"` / `"1080p"`, `fps` 24 / 25 / 30 / 60; fades rendered as frames; no audio; at most 2 hours). Runs in the background → `{taskId, background, slides, seconds, total, width, height, warnings}`; its row is in `activity.list` (`kind: "export"`, label "Exporting slideshow"), `activity.cancel {id: taskId}` stops it and leaves no file (outputs are written as `.part` and renamed when complete). `wait: true` runs it in the call and replies with the result. One at a time |
|
||||
| `engine.execute {command: "slideshow.exportStatus"}` | — | The last slideshow export: `{taskId, format, path, running, done, total, cancelled, result?, error?}`; `result` has `pages` (PDF), `files` (JPEG) or `frames`, `samples`, `keyFrames`, `seconds`, `fps`, `container`, `codec: "av1"`, `audio: false` (video), and `skipped` / `warnings` for photos that could not be rendered |
|
||||
| `engine.execute {command: "dialog.slideshowExport"}` / `app.slideshowExport` | `{format?}` / `{format, size?, quality?, fps?, container?, fullScreen?, path?}` | View ▸ Export Slideshow…: opens the dialog; `app.slideshowExport` asks for the path with a save dialog when none is given, then starts `slideshow.export` |
|
||||
| `app.quit` | — | Close the app |
|
||||
|
||||
White balance (`develop.set` with `wb.temp` / `wb.tint`, `develop.wb`, `develop.wbPick`) is in Kelvin and tint on
|
||||
@@ -103,6 +114,14 @@ scrolling pans in both axes and respects the operating system's scrolling direct
|
||||
These gestures work in Detail (including editing tools and full-screen preview), Compare and Reference
|
||||
views, and only apply over their image areas. Panning stops at the image edges.
|
||||
|
||||
The camera's focus point ([focus-points.md](focus-points.md)) is `meta.focus` in `photo.inspect`: `{rect: {x0, y0,
|
||||
x1, y1}, mode?, area?, tracking?}`, normalized to the upright photo (absent when the file records none).
|
||||
`view.focusPoint {on?}` shows it over the photo (no params toggles; replies `{on}`), and `view.zoomToFocus {on?}`
|
||||
(on by default) makes `view.zoomToggle` zoom in centred on it, replying `{focus: [x, y]}` (the `pan` it set).
|
||||
`photo.readFocusPoints {ids?, wait?}` reads the point for photos imported before it was read, from a few KB of each
|
||||
file, on a background job (activity kind `focus`); `wait: true` returns the run's counts when done. The app calls
|
||||
`focus.pump {pace}` every frame to drive it.
|
||||
|
||||
The interface theme is `view.appearance {mode?: "auto" | "light" | "dark"}` (no mode: the next one,
|
||||
Auto → Light → Dark → Auto, like the top bar's `icon:appearance` button) and `view.theme {theme:
|
||||
"charcoal" | "midnight" | "silver" | "paper"}`, which picks a theme and fixes the mode to its family.
|
||||
|
||||
+73
-5
@@ -32,10 +32,48 @@ are the public prose descriptions and patents cited in
|
||||
embedded-JPEG fallback and its visible warning when a JPEG is present. So does
|
||||
any other CR3 decode error (a corrupt file, or a body whose CRX stream the
|
||||
decoder misreads): every CR3 opened from its embedded JPEG before this decoder,
|
||||
and only four bodies are verified, so a CR3 never fails to import or load
|
||||
and not every body's variants are known, so a CR3 never fails to import or load
|
||||
where a preview exists. HEVC-only preview tracks are recognized but are not
|
||||
decoded.
|
||||
|
||||
## Variant status
|
||||
|
||||
The supported and rejected CRX coding variants. Every rejection is an explicit `RawError::Unsupported` whose
|
||||
text is part of the contract: `crates/raw/tests/cr3_variants.rs` rebuilds each variant as a synthetic CR3
|
||||
fixture and asserts the exact string, and that header probing (`probe_info`, the import path) and full
|
||||
decoding fail with the same error, because the engine shows that reason when it falls back to the embedded
|
||||
preview. The same tests decode a control fixture at both edges of each accepted range, so a rejection can
|
||||
only come from the gate named here.
|
||||
|
||||
| Variant | Status | Gate | Exact rejection |
|
||||
|---|---|---|---|
|
||||
| Version `0x100`, four Bayer planes, encoding 0, wavelet levels 0 (lossless) or 3 (C-RAW, horizontal tiles) | Supported | `supports()` in `vendor/crx.rs` | none |
|
||||
| Version `0x200`: single-tile 14-bit three-level C-RAW with adaptive quantization, QP map of any height (an odd height leaves the last QP row without a partner and it is used on its own), QP values 131–175 (169–175: EOS R6 Mark II) | Supported | `supports()`, `qp_map()` | none |
|
||||
| Version other than `0x100`/`0x200`, or wavelet levels other than 0 and 3 | Rejected | `supports()` | `Canon CRX version {version:#x}, encoding {encoding}, {planes} planes, {levels} wavelet levels` |
|
||||
| Bit depth outside 8–16 (the `CMP1` parser only accepts 1–16, so 1–7 is what can arrive) | Rejected | `supports()` | `Canon CRX {bits}-bit samples` |
|
||||
| C-RAW with vertical tiles (tile height below the image height, three levels) | Rejected | `supports()` | `Canon CRX C-RAW with vertical tiles` |
|
||||
| Version `0x200` that is not a single-tile 14-bit C-RAW | Rejected | `supports()` | `Canon CRX version 0x200 requires a single-tile 14-bit Bayer C-RAW image` |
|
||||
| Extended `CMP1` header with a median bit depth (used by type-3 burst coding) | Rejected | `supports()` | `Canon CRX extended median-bit-depth header` |
|
||||
| Rounded-plane coding or unexpected plane flags | Rejected | `validate_planes()` | `Canon CRX plane coding flags` |
|
||||
| Partial-subband coding | Rejected | `validate_planes()` | `Canon CRX partial subband coding` |
|
||||
| Adaptive quantization gain on a low-frequency band (bands 0–3) | Rejected | `validate_planes()` | `Canon CRX adaptive quantization subband parameters` |
|
||||
| Uniform quantization value outside 4–44 | Rejected | `quant_step()`, called from `validate_planes()` | `Canon CRX quantization value {value}` |
|
||||
| Adaptive QP value outside 131–175 | Rejected | `qp_map()` | `Canon CRX adaptive QP value {value}` |
|
||||
| `ff11`/`ff12`/`ff13` markers in a `0x100` stream | Rejected | `layout()` | `Canon CRX ff11/ff12/ff13 marker family` |
|
||||
| Marker header of the wrong length (8 bytes expected for `ff01`, `ff02`, `ff03` and `ff12`, 16 for `ff11` and `ff13`) | Rejected | `layout()` | `Canon CRX marker {marker:#x} header length {size}` |
|
||||
| `0x200` tile header with a wrong magic, a nonzero reserved field, an empty QP map or QP padding above 7 | Rejected | `layout()` | `Canon CRX adaptive quantization tile header` |
|
||||
| `0x200` band header with a nonzero reserved field | Rejected | `layout()` | `Canon CRX adaptive subband reserved field` |
|
||||
| Container adapter: a track that is not four planes with encoding 0 | Rejected | `decode()` in `vendor/cr3.rs` | `Canon CR3 encoding {encoding} with {planes} planes` |
|
||||
|
||||
`supports()` also rejects encoding other than 0, a plane count other than 4 and a CFA pattern above 3, but
|
||||
through a CR3 container the adapter rejects the first two before the CRX layer is reached, and the `CMP1`
|
||||
parser rejects the third for four-plane tracks. A descriptor the parser cannot accept at all (a zero
|
||||
dimension, a tile larger than the image, a bit depth outside 1–16, a plane count outside 1–4 or a zero
|
||||
header size) is reported as `Corrupt` (`CR3 raw track has an invalid CMP1 descriptor`), not as unsupported.
|
||||
A gain on a low-frequency band cannot reach `adaptive_step()`, which has its own rejection
|
||||
(`Canon CRX adaptive low-frequency quantization`): `validate_planes()` refuses it first. That gate is defence
|
||||
in depth and is not tested separately.
|
||||
|
||||
## Verified sensor decoding
|
||||
|
||||
CRX version `0x100`, four Bayer planes and `ff01`/`ff02`/`ff03` marker headers
|
||||
@@ -46,7 +84,7 @@ its adaptive quantization map. C-RAW is quantized, so next to clipped highlights
|
||||
its reconstruction can overshoot the sensor range by a few quantization steps
|
||||
(up to 36 codes above 16383 in 17 CC0 files); those samples are clamped to the
|
||||
CMP1 bit depth. A lossless sample outside the bit depth is still corrupt data.
|
||||
Other unverified coding variants return explicit unsupported errors. Header probing validates the same coding variants and
|
||||
Other unverified coding variants return explicit unsupported errors (the table above lists them all). Header probing validates the same coding variants and
|
||||
tile/plane layout as full decoding.
|
||||
|
||||
`crates/raw/tests/cr3_corpus.rs` checks every full-sensor sample against a
|
||||
@@ -92,8 +130,9 @@ files are reported as skipped by the tests.
|
||||
The version `0x200` QP predictor and entropy framing were checked independently.
|
||||
Controlled input mutations establish floor averaging of paired QP rows before
|
||||
the nonlinear integer table, then multiplication, division by eight, addition
|
||||
of the subband base and a minimum step of one. QP values 131–167 are verified;
|
||||
unmeasured values are rejected.
|
||||
of the subband base and a minimum step of one. QP values 131–167 are verified; 168 (quantization
|
||||
value 44, step 102, measured at about 100 on EOS R50 C-RAW files) continues the sequence and is
|
||||
accepted. Other values are rejected.
|
||||
|
||||
The QP map is coded as follows (established on the EOS R5 Mark II). Its first symbol is a 32-bit
|
||||
big-endian literal, mapped like every other symbol and added to a prediction of zero. Every later
|
||||
@@ -132,11 +171,40 @@ and 6400), whose developed images match visually and whose sensor means agree
|
||||
within 0.1% at ISO 6400. Files with even-height maps never reach this rule, so
|
||||
the six verified fixtures are unchanged. Partial-subband and
|
||||
rounded-plane coding, vertical C-RAW tiling and adaptive low-frequency gains
|
||||
remain unsupported. The decoder bounds image dimensions, sample count,
|
||||
remain unsupported (see the variant table above; `cr3_variants.rs` pins each rejection). The decoder bounds image dimensions, sample count,
|
||||
tile count, marker headers and temporary allocations. The full sensor buffer is
|
||||
allocated only after the first plane decodes, and plane buffers grow row by row,
|
||||
so a small crafted file fails before reserving memory for the image it claims.
|
||||
|
||||
## Further bodies: one CC0 file each
|
||||
|
||||
All 110 CR3 files on raw.pixls.us (2026-10-12, every one CC0, 31 folders) decode from sensor data; none
|
||||
falls back to the preview, so none of them uses a CRX variant the decoder refuses (vertical C-RAW tiles,
|
||||
partial-subband or rounded-plane coding, multi-tile 0x200, adaptive low-frequency gains) or a CR3
|
||||
sRAW / mRAW. HEIF stills are separate `.HIF` files, not CR3. One file per body is pinned in
|
||||
`canon_cr3_bodies_decode_like_the_camera_jpeg` (`crates/raw/tests/cr3_corpus.rs`; URLs and SHA-256 in
|
||||
`RAW_SAMPLES`, `xtask/src/main.rs`): EOS-1D X Mark III, 90D, 250D, 850D, M200, M50 Mark II, M6 Mark II,
|
||||
R, R3, R5, R6, R6 Mark II, R6 Mark III, R7, R10, RP, R50, R50 V and PowerShot G5 X Mark II, G7 X Mark III,
|
||||
SX70 HS and V1, C-RAW where the body has a CC0 C-RAW sample. No external decoder was run: the sensor
|
||||
hashes pin LightCraft's own decode, and the check is black-box against the camera:
|
||||
|
||||
- the green sites of the active area, on a 24 × 16 grid, follow the camera's own embedded JPEG
|
||||
(gamma-encoded Pearson r 0.93–0.99; 0.83 for the M6 Mark II and 0.71 for the G7 X Mark III, whose
|
||||
JPEGs are strongly distortion-corrected; a misread stream gives r near 0);
|
||||
- each render was inspected at 100 % for tile seams, band or quantiser artefacts (none);
|
||||
- where raw.pixls.us has RAW and C-RAW shots of one scene, their black-subtracted sensor means correlate
|
||||
on 16 × 16 blocks at 0.99–0.995 (R, R6, 250D, R50, G5 X Mark II, R5 crop mode) and 0.97 (RP); the
|
||||
two R5 full-frame shots correlate at only 0.83, though each follows its own camera JPEG at r 0.98, so
|
||||
the shots differ, not the decodes. The shots differ in exposure, so the means are not compared.
|
||||
|
||||
The EOS R6 Mark III (`ColorData` version 66) reads its as-shot white balance and black level as described at
|
||||
the top of this page; its white level comes from the data.
|
||||
|
||||
Not every C-RAW file of a verified body decodes: the decoder accepts adaptive QP values 131–175 only. The 3 of
|
||||
40 EOS R6 Mark II C-RAW files with QP 172 or 175 a user reported (they opened as their preview with "Canon CRX
|
||||
adaptive QP value 172") now decode (#1694). EOS R7 C-RAW (the odd-height QP map above) has only been checked on six paired RAW /
|
||||
C-RAW captures; the pinned R7 file is lossless, so R7 C-RAW still has no black-box reference.
|
||||
|
||||
## White level
|
||||
|
||||
The white level is Canon's specular white from `ColorData` (the word after the
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ pool. A scalar implementation checks the optimized operators on synthetic networ
|
||||
Tract is not a workspace dependency or a product feature.
|
||||
CPU inference and the GPU model module are feature-gated; ordinary engine/web builds
|
||||
do not compile the faer/GEMM backend. The engine depends on the inference crate only through `denoise = ["dep:lightcraft-denoise", …]`;
|
||||
lightweight `lightcraft-denoise-core` metadata and cache formats remain available without inference. Pictures are capped at 100 megapixels; at most
|
||||
lightweight `lightcraft-denoise-core` metadata and cache formats remain available without inference. Pictures are capped at 110 megapixels; at most
|
||||
four tile calls run together, chosen within the process-wide working-memory budget.
|
||||
One idle CPU workspace is retained, and cache costs reserve room for the blended picture.
|
||||
|
||||
|
||||
+50
-1
@@ -143,6 +143,43 @@ SFace's builtin speed metadata now uses the measured 6.9× ratio. User `catalog.
|
||||
Older published tables for MobileFaceNet/R50/R100 came from a different runtime and are not measurements of this runner; architecture
|
||||
names alone do not guarantee the same speed, and those additional model files were not verified in this task.
|
||||
|
||||
### On the GPU
|
||||
|
||||
On a machine with a usable GPU, the whole detector and recogniser run on it through wgpu (`crates/gpu/src/faces.rs`).
|
||||
The interpreter lowers the graph to a flat program for the input's shape (`crates/faces/src/net/program.rs`): each
|
||||
convolution (`wgsl/faces_conv.wgsl`: an implicit matrix product that gathers the input straight into workgroup memory,
|
||||
cuts K into slices when a map is small, and a direct kernel for depthwise layers) and every other operator (activations,
|
||||
batch norm, PRelu, broadcasting add/sub/mul, max pooling, nearest upscaling, transposes, global pooling and the fully
|
||||
connected layer, `wgsl/faces_ops.wgsl`) is a kernel, every value stays on the device between layers in reused
|
||||
buffers, and a run is one upload, one submission and one read-back. Shape-only operators make no step. A model that
|
||||
needs something the program cannot express runs its convolutions one by one on the GPU instead. Several faces of one
|
||||
photo go together (`Embedder::embed_batch`, up to 16 per submission).
|
||||
|
||||
The CPU interpreter remains the reference. After a model loads, a background check (a row in the activity stack, "Checking
|
||||
the GPU for faces") runs it once on the CPU and twice through the GPU on a fixed test input: the GPU is used only when
|
||||
every output is within 1e-3 of the CPU's (relative to the output's largest value) **and** it was faster; until then,
|
||||
and whenever the GPU is switched off (`LIGHTCRAFT_GPU=0`, `LIGHTCRAFT_GPU_BACKEND=off`, the GPU preference, or **Settings ▸
|
||||
Faces ▸ Run face models on the CPU only**), missing, wrong or slower, the model runs on the CPU. The first GPU error,
|
||||
or a result of the wrong size or with values that are not finite, drops it for that model. Settings ▸ Faces shows
|
||||
which device each model runs on (`faces.gpu`). The weights stay on a device of the scan's own (separate from the
|
||||
editor's) while the model is loaded, at most 768 MB per model.
|
||||
|
||||
The background scan's pace also limits the GPU: paused or light, one model run at a time and the GPU busy at most a
|
||||
quarter of the time (the editor renders on the same GPU); normal, two at once and three quarters; full, as fast as it
|
||||
goes.
|
||||
|
||||
Measured on Linux with a Radeon (Vulkan) and a 32-thread CPU, one call at a time, machine under very heavy load from
|
||||
other jobs (load average 100–250, so the absolute numbers are noisy):
|
||||
|
||||
| Model | CPU | GPU, one layer at a time | GPU, whole network | Batch of 16, per face |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| YuNet (640², one photo) | 58–60 ms | 85–89 ms | 21 ms | – |
|
||||
| SFace 2021dec | 40–42 ms | 47–51 ms | 9.6 ms | 8.1 ms |
|
||||
| AuraFace v1 | 295–308 ms | 165–172 ms | 70–73 ms | 71 ms |
|
||||
|
||||
`LC_FACE_MODELS=<folder> cargo test --release -p lightcraft-gpu faces::tests -- --include-ignored --nocapture` checks
|
||||
agreement on the real models and every operator, and prints these timings.
|
||||
|
||||
### Agreement and regression coverage
|
||||
|
||||
The public-crop embeddings match the reference runtime's outputs:
|
||||
@@ -268,6 +305,13 @@ To name a group: click faces to select them (Shift-click selects a range, **Sele
|
||||
name in the bar that appears (people already named complete as you type), press Enter: all of them are named at once, as
|
||||
one undo step. Selecting names nothing.
|
||||
|
||||
Right-click a person's card, or use **Rename Person…** on their page, to rename every face of that person in the library
|
||||
at once (`faces.renamePerson`). The name is matched the way the cards are grouped (trimmed, ignoring capitalization) and
|
||||
every matching face is stored with the exact new spelling, so a change of capitalization alone updates them all. The
|
||||
dialog says how many faces that is. If the new name is already someone else, it refuses until **Combine with the existing
|
||||
person** is ticked; that makes one person, and Undo separates them again. Cancelling changes nothing. A person filter,
|
||||
the open person page and the way back to it follow the new name. Nothing is written back to the files.
|
||||
|
||||
The thumbnail-size slider in the bottom bar sizes the faces here too, with limits of their own. Every face is shown by the
|
||||
same kind of box: the detector's own box once the scan has looked at it (kept beside its embedding), so a loosely drawn box
|
||||
from another tool does not make one face look farther away than the next; before the scan has looked at a face it is shown
|
||||
@@ -278,6 +322,11 @@ by its own box.
|
||||
In **People**, a click on a person opens their page: **only cropped faces**, never whole photos. First the faces named
|
||||
with their name (a click opens that photo), then **More**: the unnamed faces that look like them, most alike first. Click one
|
||||
to confirm it (that names the face, as one undo step, and it moves up into their faces), or × to hide it for this session.
|
||||
The `↑` control at the top left of a suggested face confirms that face and every currently shown, non-hidden suggestion
|
||||
with an equal or higher similarity score. Its tooltip names the person and shows the number of faces before you act.
|
||||
Hover a suggestion or focus it with the keyboard and press `A` for the same action. The batch is one undo step;
|
||||
suggestions below that score, previously confirmed faces and hidden suggestions stay as they were. Nothing is named
|
||||
without this explicit action.
|
||||
**Show photos** puts their photos in the grid; **‹ People** or Escape goes back. "More" only holds faces the scan has
|
||||
already embedded, so it fills in as the scan goes; it shows faces scoring above four fifths of the model's suggestion bar,
|
||||
since you look at each one before anything is named.
|
||||
@@ -327,7 +376,7 @@ reuses the pictures of its step instead of rendering every face again.
|
||||
|
||||
All of this is reachable from the control channel, the CLI and MCP: `faces.models.list`, `faces.models.inspect {path}`,
|
||||
`faces.models.install {path, acknowledged: true, activate?}`, `faces.models.download {id, acknowledged: true}` (then `faces.models.downloads`, which also installs what has arrived, and `faces.models.downloadCancel {id}`), `faces.models.remove {id}`, `faces.models.select {id}`,
|
||||
`faces.enable {enabled?}`, `faces.detect {ids?, apply?}`, `faces.index {budgetMs?, ids?}`, `faces.pump` (what the app calls every frame), `faces.suggest {ids?, threshold?, margin?}`, `faces.person {name, more?}` (a person's faces and the unnamed faces that look like them), `faces.unnamed {limit?}` (every unnamed face, look-alikes together, with suggested names), `faces.setName {id?, index, name}`, `faces.nameFaces {faces: [{photo, index}], name}` (name many at once, one undo step) and `faces.evaluate`. `acknowledged` must be `true`: the caller has shown the user the terms and the user agreed. Installing makes the model the one in use and switches recognition on unless `activate` is `false`.
|
||||
`faces.enable {enabled?}`, `faces.detect {ids?, apply?}`, `faces.index {budgetMs?, ids?}`, `faces.pump` (what the app calls every frame), `faces.suggest {ids?, threshold?, margin?}`, `faces.person {name, more?}` (a person's faces and the unnamed faces that look like them), `faces.unnamed {limit?}` (every unnamed face, look-alikes together, with suggested names), `faces.setName {id?, index, name}`, `faces.nameFaces {faces: [{photo, index}], name}` (name many at once, one undo step), `faces.renamePerson {from, to, merge?}` (rename every in-library face of one person, or merge two when `merge` is true, one undo step) and `faces.evaluate`. `acknowledged` must be `true`: the caller has shown the user the terms and the user agreed. Installing makes the model the one in use and switches recognition on unless `activate` is `false`.
|
||||
|
||||
## Find Blemishes
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# File format parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Render to DNG as an export format) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (lossy DNG export; Render to DNG as an export format) · **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).
|
||||
@@ -15,7 +15,7 @@ import and export formats. Ours come from `crates/codecs/src/sniff.rs`, `crates/
|
||||
|
||||
| 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 |
|
||||
| JPEG | ✅ | ✅ | ✅ (parallel decoder, ICC, EXIF orientation) | ✅ quality, size limit, ICC, metadata; Huffman tables optimized per image (issue #1373) | `crates/codecs/src/jpeg.rs`, `crates/codecs/src/jpeg_par.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` |
|
||||
@@ -24,7 +24,7 @@ import and export formats. Ours come from `crates/codecs/src/sniff.rs`, `crates/
|
||||
| JPEG XL | ✅ | ✅ | ✅ (`jxl-oxide`) incl. DNG 1.7 JXL tiles | ✅ lossy / lossless, 8/16-bit, PQ HDR (`jixel`, native only; ⬜ web) | `crates/engine/src/tests_export.rs` |
|
||||
| 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` |
|
||||
| DNG (from raw) | ✅ | ✅ incl. lossy, embedded original | ✅ | ✅ uncompressed, LJ92, Deflate or lossy (JPEG tiles, optional long edge); ⬜ embedded original | `crates/raw/src/dngwrite.rs` |
|
||||
| Render to DNG (15.5) | — | ✅ | — | 🟡 export format "Rendered DNG" (linear float DNG, edit baked in); not yet added to the catalog | `crates/raw/src/dngwrite.rs` (`write_rendered_dng`) |
|
||||
| Original + sidecar | — | ✅ | — | ✅ | |
|
||||
| HDR gain map JPEG (ISO 21496-1) | ✅ | ✅ | ✅ (gain map read) | ✅ | `crates/codecs/src/gainmap.rs` |
|
||||
@@ -63,7 +63,7 @@ import and export formats. Ours come from `crates/codecs/src/sniff.rs`, `crates/
|
||||
|
||||
| Part | Weight | Ready for real work | Kind |
|
||||
|---|---:|---:|---|
|
||||
| Standard image import / export | 35% | ~85% | estimated (table above; missing: AVIF read, PSD write, lossy DNG) |
|
||||
| Standard image import / export | 35% | ~85% | estimated (table above; missing: AVIF read, Render to DNG in the catalog) |
|
||||
| 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 |
|
||||
@@ -78,3 +78,5 @@ Remaining: **26–47 h** (AVIF decode 8–15 h if a permissive decoder is writte
|
||||
| 2026-10-10 | major | Created from the code and the installed Lightroom's document types |
|
||||
| 2026-10-10 | minor | JPEG XL export (#247): JXL write ✅ (native only), PQ JPEG XL HDR |
|
||||
| 2026-10-12 | minor | Render to DNG: "Rendered DNG" export format (linear 16-bit float DNG of the rendered photo) |
|
||||
| 2026-10-12 | minor | Lossy DNG export (JPEG tiles, `dngCompression: "lossy"`); PSD write had already landed (#953), so it leaves the remaining hours |
|
||||
| 2026-10-13 | patch | JPEG write (#1373): Huffman tables made for each image, 12–14 % smaller files at the same pixels; statuses unchanged |
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
# Focus points
|
||||
|
||||
Most cameras record where they focused. LightCraft reads that point from the file, draws it over the photo and
|
||||
zooms to it, so checking whether the subject is sharp takes one key while culling. Lightroom shows no focus points
|
||||
(photographers add plug-ins for it); this goes beyond parity (tracker row `LR-VIEW-FOCUSPOINT`).
|
||||
|
||||
## Using it
|
||||
|
||||
- **View ▸ Show Focus Point** (⌥F; `view.focusPoint {on?}`) draws the camera's AF frame as green corner brackets in
|
||||
Detail, Compare and Survey. It follows Rotate, flips and the crop; a point cropped away is not drawn. Off by
|
||||
default; the choice is saved with the app's settings.
|
||||
- **View ▸ Zoom to Focus Point** (`view.zoomToFocus {on?}`, on by default): Toggle Zoom (Z or Space) zooms in
|
||||
centred on the focus point instead of the last position. A click on the photo still zooms where you click, and a
|
||||
photo without a focus point zooms as before. On by default because it changes nothing for photos without a point,
|
||||
and for those with one the focus point is what a 1:1 check is for. In Compare the two panes share one pan, so Z
|
||||
centres on the active photo's point; per-pane focus zoom is a follow-up.
|
||||
- **Info panel**: a *Focus* row says how the camera focused, e.g. `AF-C · Wide · Animal Eye Tracking` (focus mode,
|
||||
the AF area set on the camera, and what it tracked when the camera says).
|
||||
- **Agents**: `photo.inspect` (and the MCP `lightcraft://photo/active` resource) returns it as `meta.focus`:
|
||||
`{rect: {x0, y0, x1, y1}, mode?, area?, tracking?}`, the box normalized to the upright (EXIF-oriented) photo, y down.
|
||||
Photos without one have no `focus` key. `view.zoomToggle` replies `{focus: [x, y]}` (the pan it centred on) when it
|
||||
zoomed to one.
|
||||
|
||||
The point is read when a photo is imported. Photos imported earlier get it in the background (below). It is
|
||||
read-only camera data: never written to XMP, and absent from the catalog JSON when unknown, so older catalogs read
|
||||
unchanged (no catalog format change).
|
||||
|
||||
## Photos imported earlier
|
||||
|
||||
A library imported before focus points were read gets them by itself: when a library opens and some of its photos
|
||||
from a supported body have no point and haven't been looked at, LightCraft reads them in the background, with a
|
||||
**Reading focus points** row in the activity stack (n of N; ✕ stops it). **Photo ▸ Read Focus Points**
|
||||
(`photo.readFocusPoints`) starts the same job by hand. Photo ▸ Reload from Disk still fills a missing point too, but it
|
||||
re-reads and hashes whole files and runs while you wait, so it is for a few photos, not a library.
|
||||
|
||||
- **What is opened**: only photos whose stored camera is a supported body (`SONY ILCE-1`, `SONY ILCE-7SM3`), whose
|
||||
file is an ARW or JPEG, that are in the library and have no point yet. Nothing else is opened.
|
||||
- **What is read**: the few kilobytes that hold the focus data, not the file
|
||||
(`lightcraft_meta::focus::read_header`). It walks the file's structure as the decoder does — the TIFF header and
|
||||
IFD0 (Make, Model), the Exif IFD (the MakerNote entry), the maker note's IFD and the values of the focus tags; in a
|
||||
JPEG, the segments up to the Exif one — asking only for the ranges the bytes read so far point at, and decodes them
|
||||
with the same code as a whole-file read. On the α1 and the A7S III everything sits in the first 16 KB, so one 32 KB
|
||||
read per photo does it (instead of 50–120 MB). Rounds (12), bytes (2 MB) and the file size are bounded; a file that
|
||||
wants more is treated as having no point. On 109 real α1 / A7S III ARWs (83 with a point) the header read gave the
|
||||
same point as the whole-file read for every file.
|
||||
- **Pace**: one file at a time on one worker thread (the drive may be a spinning disk), in path order so neighbouring
|
||||
files are read together. Nothing new is read while you drag, type or scroll, and it rests briefly between files
|
||||
while you are around, so your own previews come first. Measured on a 5400 rpm USB drive, cold cache, 200 α1 / A7S III
|
||||
ARWs: 1.9 s (about 100 photos a second, 32 KB each), so a library of 58,796 raws takes about ten minutes at full
|
||||
pace instead of re-reading 2.25 TB.
|
||||
- **Saving**: what was read is committed every 200 photos (or every 3 seconds) as LightCraft's own bookkeeping: no
|
||||
undo step, no sidecar written, and only `meta.focus` changes, on a photo that still has none and still points at the
|
||||
file that was read (a photo deleted, moved or relinked meanwhile is left for another run). Photos that turned out to
|
||||
have no point (manual focus, a centre-only Wide report) are listed in `focus-scanned.bin` beside the library, so they
|
||||
are not read again at every launch. The list is headed by the decoder's tag (the bodies it knows): when a body is
|
||||
added, the list starts afresh and those photos are looked at again. A file that can't be read (an offline drive, a
|
||||
file gone or replaced during the read) is not listed, and is tried again the next time the library opens.
|
||||
- **Resuming**: quitting mid-run keeps what was committed; the next launch reads the rest.
|
||||
- **Agents**: `photo.readFocusPoints {ids?, wait?}` — without `ids`, every photo not looked at yet; with `ids`, those
|
||||
photos, looked at again even if listed. `wait: true` returns when done with `{last: {total, done, found, none,
|
||||
unavailable, bytesRead, seconds, cancelled}}` (`lightcraft-cli run --library DIR photo.readFocusPoints wait=true`).
|
||||
The app's frame loop calls `focus.pump {pace}`, which also starts the job once per library opening.
|
||||
|
||||
## Cameras
|
||||
|
||||
Sony first, on bodies whose files have been checked: **ILCE-1 (α1)** and **ILCE-7SM3 (A7S III)**
|
||||
(`lightcraft_meta::focus::SONY_MODELS`). Other Sony bodies store the same tags, but a body is added only after its
|
||||
files are checked, so an unchecked one shows nothing rather than a misleading box. Fujifilm, Canon, Nikon, OM System
|
||||
and Panasonic record similar data and are later steps.
|
||||
|
||||
### Sony layout and evidence
|
||||
|
||||
Tag identities and value names come from the public ExifTool tag-name documentation (Sony MakerNotes table). No
|
||||
third-party code was read or ported. Every field was confirmed on real files by comparing LightCraft's decoder with
|
||||
ExifTool's output, run as a black box: 333 ARWs sampled across four years of a photographer's library (180 α1,
|
||||
153 A7S III; 12 portrait or upside-down, 54 in APS-C crop or reduced-size modes), with no mismatch in the point, frame or names.
|
||||
|
||||
| MakerNote tag | Layout | Notes |
|
||||
|---|---|---|
|
||||
| `0x2027` FocusLocation | 4 × int16u: frame width, frame height, focus x, focus y | in the sensor's landscape frame (a portrait shot still says 8640 × 5760); the frame is the image size (5616 × 3744 in α1 APS-C mode) |
|
||||
| `0x2037` FocusFrameSize | 6 bytes: int16u width, int16u height, then 2 bytes that are zero when no frame was shown | zero in manual focus; one AF-C α1 file had no frame (a small box is drawn: 3 % of the short side) |
|
||||
| `0x201b` FocusMode | int8u: 0 Manual, 2 AF-S, 3 AF-C, 4 AF-A, 6 DMF, 7 AF-D | |
|
||||
| `0x201c` AFAreaModeSetting | int8u: 0 Wide, 1 Center, 3 Flexible Spot, 11 Zone, 12 Expanded Flexible Spot, 13 Custom AF Area | |
|
||||
| `0x2021` AFTracking | int8u: 0 Off, 1 Face tracking, 2 Lock On AF | |
|
||||
| `0x9402` bytes 0x16 / 0x17 | enciphered: focus mode (low 7 bits) and the AF area mode used (0 Multi, 2 Spot, 3 Flexible Spot, 11 Zone, 14 Tracking, 15 Face Tracking, 20 Animal Eye Tracking, 21 Human Eye Tracking, 255 Manual…) | read only when its focus mode equals `0x201b`'s |
|
||||
|
||||
The documentation says the `0x94xx` blocks use "a simple substitution cipher". On the files each byte `p < 249` is
|
||||
stored as `p³ mod 249` (bytes 249–255 unchanged): ExifTool's decoded AFAreaMode 20 is stored as `0x20`, a decoded
|
||||
`0x83` as `0x77`. Cubing is a bijection modulo 249 (= 3 × 83), so the inverse is a table lookup.
|
||||
|
||||
On the α1 files the box sits on the subject: drawn on the embedded previews, it lands on the bird's eye in eye-AF
|
||||
shots and follows spot, zone, wide and tracking shots, in portrait and landscape.
|
||||
|
||||
### When there is no real point
|
||||
|
||||
Nothing is stored (so nothing is drawn and Z zooms as before) when:
|
||||
|
||||
- the body is not one of the checked ones, the tags are missing or malformed, the frame size is zero, or the centre
|
||||
lies outside its frame;
|
||||
- **manual focus** (`0x201b` = 0, or the block's area mode is Manual). The camera still records where the AF frame was
|
||||
parked: 83 of the 91 sampled manual-focus files carry an off-centre location that says nothing about focus;
|
||||
- the location is the **exact frame centre while the area used was Multi** (Wide with nothing tracked; without the
|
||||
block, Wide with tracking off). The wide area reports the centre when it picked no particular spot; 7 of the 34
|
||||
sampled autofocus Multi files did. A centred Spot, Zone or Flexible Spot frame is a choice the photographer made, and
|
||||
is kept (49 of the 111 sampled spot and zone files were centred, the camera's default position).
|
||||
|
||||
DMF (AF, then manual touch-up) keeps its point.
|
||||
|
||||
## Code
|
||||
|
||||
- `crates/meta/src/focus.rs`: the decoder (bounded; hostile values give no point, never a panic) and its tests,
|
||||
including an opt-in test over real files (`LIGHTCRAFT_FOCUS_SAMPLES=<photo folder>`).
|
||||
- `crates/meta/src/focus_read.rs`: the header-only read; its tests check it against the whole-file read on intact,
|
||||
truncated and corrupted files and count what it reads.
|
||||
- `crates/engine/src/focus_scan.rs`: the background job (`photo.readFocusPoints`, `focus.pump`) and
|
||||
`crates/engine/src/tests_focus_scan.rs`, with an opt-in comparison over real files
|
||||
(`LIGHTCRAFT_FOCUS_FILES=<a list of paths>`); `crates/ui-egui/src/focus_scan.rs` drives it from the frame loop.
|
||||
- `crates/ui-egui/src/panels/detail.rs` (`focus_box`, `focus_pan`, `draw_focus_point`): mapping through the user's
|
||||
rotation and crop, the overlay, and the zoom target; `crates/ui-egui/src/tests_focus_point.rs`.
|
||||
+46
-14
@@ -1,6 +1,6 @@
|
||||
# Gaps: where LightCraft falls short of Lightroom
|
||||
|
||||
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-14 · **Change:** minor (gap 4 follow-up: diagnostic overlays get zoom windows); previously minor (gap 4 closed: soft proofing gets zoom windows; gap 8: Nikon Z 6II / Z 8 / Z f in-file distortion; gaps 10, 22 and 23 listed once again: merges had left two copies of each, and `cargo xtask parity` now fails on a gap listed twice) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-15 · **Change:** minor (gap 15: Print Page Options — page numbers, page info, crop marks; gap 4 follow-up: diagnostic overlays get zoom windows, soft proofing on the GPU)
|
||||
|
||||
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
|
||||
@@ -15,41 +15,42 @@ Hours are Opus 5.5 agent wall-clock hours (see [target-app-parity.md](target-app
|
||||
|
||||
| # | Gap | Evidence | User impact | Hours | Doc |
|
||||
|---:|---|---|---|---:|---|
|
||||
| 1 B | **Camera colour is estimated, not measured** (LR-PROF-CAMERACOLOR). Raws start from a per-file fit to the camera JPEG, 4 bundled profiles or 52 spectral matrices; others use a neutral matrix (a black-and-white camera JPEG gives its tone curve only, #577; dark JPEG tones also guide the toe, #1307) | Δ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 four verified bodies** (LR-IMP-FORMATS): `crx.rs` refuses vertical-tile C-RAW, partial-subband and other plane coding, multi-tile 0x200 and adaptive low-frequency gains, and those files fall back to the preview; CR3 sRAW / mRAW and HEIF CR3 too. Verified: M50 / R100 / R8 / R5 Mark II. EOS R7 C-RAW (odd-height QP map) decodes since a45c2b66 and R6 Mark II C-RAW is reported working on 0.6.0, but neither is verified yet (no corpus test or recorded check) | measured: Canon is the largest bucket (33% of photographers) and its share whose camera fully works is the lowest of the big four, 73%; 18 of 22 popular Canon bodies write CR3, 4 verified (raw-parity.md); R7 rule checked only on paired RAW / C-RAW captures ([cr3.md](cr3.md)) | +6.2 points of photographers whose camera works, the biggest single raw gain | 25–45 | [raw-parity](raw-parity.md#remaining-work-ranked-by-photographers-unlocked-per-hour) |
|
||||
| 1 B | **Camera colour is estimated, not measured** (LR-PROF-CAMERACOLOR). Raws start from a per-file fit to the camera JPEG, 5 bundled profiles or 52 spectral matrices (plus same-sensor bodies, e.g. the X-T30 through the X-T3); others use a neutral matrix (a black-and-white camera JPEG gives its tone curve only, #577; dark JPEG tones also guide the toe, #1307) | Δ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 variants no public file uses** (LR-IMP-FORMATS): `crx.rs` refuses vertical-tile C-RAW, partial-subband and other plane coding, multi-tile 0x200 and adaptive low-frequency gains, and those files fall back to the preview. All 110 CC0 CR3s on raw.pixls.us (31 folders) decode from sensor data, so none of these variants has a public sample; 26 CR3 bodies are verified (M50 / R100 / R8 exact, R5 Mark II pinned, 22 more pinned on one CC0 file each and checked against the camera JPEG, [cr3.md](cr3.md#further-bodies-one-cc0-file-each)). HEIF stills are `.HIF` files, not CR3; no CR3 sRAW / mRAW sample exists | measured: Canon's share whose camera fully works 73% → 94% (raw-parity.md); 18 of 22 popular Canon bodies write CR3, all 18 now verified | +0.3 points of photographers; the variants surface only as user files that open as a preview | 10–25 | [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 | ~~Original-pixel detail at 100%~~ (LR-VIEW-ZOOM): closed 2026-10-12, see Closed recently | checklist row ✅ | — | 0 | [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#compressed-orf-a-clean-room-starting-point) (the two Olympus patents that describe the method) |
|
||||
| 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, Sony ILCE-7RM4A distortion and Nikon Z 6II / Z 8 / Z f distortion (`docs/nikon-lens-corrections.md`) | Adobe ships 3,635 lens profiles; we never use them | distortion / vignetting correction is a default step for many | 40–80 + calibration shots | [raw-parity](raw-parity.md#lens-profiles) |
|
||||
| 8 B | **No lens profile database** (LR-EDIT-OPTICS-PROFILE): only DNG opcodes, RW2 in-file distortion, Sony ILCE-7RM4A and ILCE-7RM6 distortion (`docs/sony-ilce7rm6-lens-corrections.md`) and Nikon Z 6II / Z 8 / Z f distortion (`docs/nikon-lens-corrections.md`) | Adobe ships 3,635 lens profiles; we never use them | distortion / vignetting correction is a default step for many | 40–80 + calibration shots | [raw-parity](raw-parity.md#lens-profiles) |
|
||||
| 9 B | **Tests don't run in CI on macOS, Windows or Linux x64**: only FreeBSD runs `cargo test`; the others build packages | `.github/workflows/` (freebsd, packaging-lint, release, windows-arm64); the linux-riscv64 release job added in 0.6.0 (#844) runs only `lightcraft-cli --version` under QEMU | regressions reach users on the main platforms; `cargo xtask ci` runs only locally | 6–12 | [target-app-parity](target-app-parity.md#by-dimension) |
|
||||
| 10 B | **Per-model verification thin, plus cheap per-body decode fixes**: 236 of 1,446 Adobe models verified (16%), ~42% of photographers on a verified body; Nikon 5 bodies verified, Canon 12, Leica 14 (the Q3 by a recorded check of 38 private DNGs). Cheap fixes: Z 6II packed 14-bit NEF (#769, PR #671), Sony A100 / F828 regression (#702), DSLR-A200…A390 / A850 12-bit ARW (#535) | measured: [raw/coverage.tsv](raw/coverage.tsv) | per-body bugs (levels, crops, WB) surface only from users | 25–45 | [raw-parity](raw-parity.md#by-maker-measured) |
|
||||
| 10 B | **Per-model verification thin, plus cheap per-body decode fixes**: 545 of 1,446 Adobe models verified (38%), ~85% of photographers on a verified body; Nikon 5 bodies verified, Canon 34, Leica 14 (the Q3 by a recorded check of 38 private DNGs). 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) |
|
||||
| 13 | **Lightroom catalog migration is one-way and approximate**: unsupported Adobe profiles / AI settings archived, history kept as data; offline record counts and destination are now shown in a lasting import result | lightroom-catalog-import.md | switching users lose some looks | 8–12 | [file-format-parity](file-format-parity.md) |
|
||||
| 14 | **HDR display** (EDR / Windows HDR); the headroom limit and SDR rendition from `crs` XMP (the HDR switch, `HDREditMode`, is read). HLG AVIF export done; the display's SDR/HDR decision is tested, blocked on eframe's 8-bit surface | 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) |
|
||||
| 15 | **Print module**: identity plate / watermark / photo info overlays, Cut Guides for the packages, Custom Package Auto Layout, printer-driver Page Setup and direct printing, JPEG file output (the Print dialog writes a colour-managed PDF) | LRC-PRINT rows | Classic users who print | 15–25 | [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) |
|
||||
| 23 | **Accessibility**: AccessKit tree audited by a test (every control named, sliders with range); left: canvas handles, spot and mask placement by keyboard, a session with a real screen reader | LR-BEHAV-ACCESS 🟡 | blind and low-vision users | 4–8 | [ui-parity](ui-parity.md) |
|
||||
| 22 | **Pen pressure**, OS monitor profiles on Windows (Linux reads colord's, macOS the screen's), follow-window colour on Linux / Windows | hardware-parity.md | brush users with tablets; multi-monitor setups | 11–22 | [hardware-parity](hardware-parity.md) |
|
||||
| 21 | **Localization**: 9 of 15 shipped languages partial (de, es, fr, ja, uk now 97–99% of catalog messages, awaiting native review; pt-BR, ru, zh-hans, zh-hant 74–92%), lower-layer errors English; Hindi, Arabic, Indonesian, Korean, Vietnamese absent; no RTL or complex shaping | measured from catalogs | non-English users see mixed English | 40–70 (shipped to full); 145–255 (five new) | [localization-parity](localization-parity.md) |
|
||||
| 23 | **Accessibility**: AccessKit tree audited by a test; canvas handles, spots and mask pins by keyboard; left: brush and red-eye by keyboard, a session with a real screen reader | LR-BEHAV-ACCESS 🟡 | blind and low-vision users | 2–4 | [ui-parity](ui-parity.md) |
|
||||
| 22 | **Pen pressure on macOS / Linux tablets** (brush size and flow follow pressure where winit reports a pen force), OS monitor profiles on Windows (Linux reads colord's, macOS the screen's), follow-window colour on Linux / Windows | hardware-parity.md | brush users with tablets; multi-monitor setups | 11–22 | [hardware-parity](hardware-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**: lossy DNG; AVIF import; Render to DNG as a catalog command (the export format landed) (PSD export landed with Edit in PhotoCraft, #953) | file-format-parity.md | interchange edge cases | 19–34 | [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) |
|
||||
| 25 | **File writes**: AVIF import; Render to DNG as a catalog command (lossy DNG and the Render to DNG export format landed) (PSD export landed with Edit in PhotoCraft, #953) | file-format-parity.md | interchange edge cases | 19–34 | [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; at 100k photos stack and album lookups are indexed (an "In a Stack" or "Album" smart album counts in ~14 ms, was 0.6–2.7 s) | 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 and on one AMD GPU on Linux (Radeon 8060S, Vulkan); NVIDIA, Intel and DX12 unverified; the Linux riscv64 tarball (new in 0.6.0, #844) is cross-compiled and never run beyond a QEMU smoke test | ROADMAP, issues, `release.yml` | non-Mac users find bugs first | 13–27 | [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) |
|
||||
| 29 | **HDR merge leftovers** (LR-MERGE-HDR): AI Denoise doesn't run on merged (linear) DNGs; JPEG brackets are treated as linear (no camera response curve); every frame is held as 32-bit float, ~0.86 GB per 67 MP frame (half-float frames would halve it) | tested on Sony A7R VI brackets 2026-10-14 ([merge.md](merge.md)); Lightroom's Denoise supports HDR DNGs | HDR shooters who denoise their merges, merge JPEGs, or merge 7+ frames of high-resolution raws on 16 GB machines | 10–20 (+ denoise linear-RGB contract, gap 11) | [merge](merge.md) |
|
||||
| 28 | **Small Classic shortcuts and keys**: rating `[` `]`, flag cycling, filter-bar keys, F1 help, panel keys (Tab, F5, F8; F6 and F7 toggle the filmstrip and the left panel) | [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
|
||||
- **Feature:** 5, 8, 11, 12, 13, 15, 16, 18, 19, 29
|
||||
- **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
|
||||
@@ -61,6 +62,8 @@ Beta-blocking gaps (B) total **~230–430 h**; with the stability and platform w
|
||||
|
||||
- 2026-10-12: original-pixel detail at 100% (gap 4, LR-VIEW-ZOOM, #323): soft proofing gets zoom windows like
|
||||
Detail, Before/After, Compare, Reference and mask overlays; 1:1 tested equal to the full-size export.
|
||||
- 2026-10-11: Sony ILCA-99M2 profile.
|
||||
- 2026-10-11: Nikon edge bars on bodies without CropArea (#976, #914): 36 model / size / depth groups measured.
|
||||
- 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), JPEG XL export (#247).
|
||||
- 2026-10-09: EOS R7 C-RAW with an odd-height QP map (a45c2b66; part of gap 2), HEIC in release builds (#609), Samsung uncompressed SRW (#459), contact-sheet PDF (#563),
|
||||
@@ -74,17 +77,40 @@ Beta-blocking gaps (B) total **~230–430 h**; with the stability and platform w
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-18 | patch | Gap 1: six X-Trans CMOS 4 Fujifilm bodies (X-T30 …) take the X-T3's spectral matrices instead of the neutral matrix |
|
||||
| 2026-10-14 | minor | Gap 4 follow-up: the diagnostic overlays (Visualize Spots, Point Color range, HDR range) render zoom windows too; soft proofing runs on the GPU |
|
||||
| 2026-10-15 | minor | Gap 15 shrinks: the Page panel's Page Options (Page Numbers, Page Info, Crop Marks) print on Single Image and Contact Sheet pages; identity plate, watermark, photo info, Cut Guides, direct printing and JPEG output remain |
|
||||
| 2026-10-14 | minor | Gap 26: at 100k photos stack and album lookups are indexed, so an "In a Stack" or "Album" smart album counts in ~14 ms (was 0.6–2.7 s); open time unchanged |
|
||||
| 2026-10-14 | minor | Gap 10: Camera-coverage sweep (#1327): 30 models verified on 40 CC0 files (coverage.py 515 → 545 verified); sensor verification does not establish colour parity (#1277) |
|
||||
| 2026-10-14 | minor | Gap 21: de, es, fr, ja and uk catalogs filled (97–99%); 55–90 h → 40–70 h |
|
||||
| 2026-10-14 | minor | Gap 10: 17 uncompressed Olympus and Samsung models verified on one CC0 file each (254 models) |
|
||||
| 2026-10-14 | minor | Gap 29 added: the HDR merge, tested on real 67 MP brackets, keeps moving clipped highlights and merges in batches now; AI Denoise on merged DNGs, JPEG response curves and per-frame memory remain |
|
||||
| 2026-10-14 | minor | Gap 4 closed: soft proofing at 1:1 renders a window (mask overlays already did); 1:1 pixels tested equal to export; only diagnostic overlays (Visualize Spots, Point Color range, HDR range) stay whole-frame |
|
||||
| 2026-10-13 | patch | Gaps 10, 22 and 23 each had two rows (two branches edited them; the merges kept both): the older copies are removed, and `cargo xtask parity` (in `ci`) now fails when a gap number is listed twice |
|
||||
| 2026-10-13 | minor | Closed recently: Sony ILCA-99M2 profile |
|
||||
| 2026-10-14 | minor | Gap 10: 21 Sony and Leica models verified on one CC0 file each (258 models) |
|
||||
| 2026-10-12 | minor | Gap 20 shrinks: Mamiya MEF decodes (`vendor/mef.rs`) and is imported; gap 10 count 240 → 241 |
|
||||
| 2026-10-12 | minor | Gap 20 shrinks: Epson ERF decodes (`vendor/erf.rs`), 3 bodies verified; gap 10 count 237 → 240 |
|
||||
| 2026-10-13 | minor | Gap 28: F6 (filmstrip) and F7 (left panel) are bound, so the entry no longer lists them as missing; hours unchanged |
|
||||
| 2026-10-11 | minor | Gap 10 shrinks: Leica Q3 verified by a recorded check of 38 private DNGs (236 models verified; Leica 14); gap not closed |
|
||||
| 2026-10-12 | minor | Camera-look deep shadows follow the JPEG toe (#1307); camera calibration remains partial |
|
||||
| 2026-10-12 | minor | Gap 23 (accessibility): crop handles, spots, gradient handles and mask pins by keyboard; 4–8 h → 2–4 h; gap not closed |
|
||||
| 2026-10-12 | minor | Gap 23 (accessibility): the AccessKit tree audit and its fixes landed; what is left is canvas placement by keyboard and a real screen-reader session; 10–20 h → 4–8 h; gap not closed |
|
||||
| 2026-10-12 | minor | Gap 22: Linux previews use the display profile from colord |
|
||||
| 2026-10-12 | minor | Gap 27: the CPU ↔ GPU equivalence suite passes on an AMD Radeon 8060S (Vulkan, Linux), the first non-Apple GPU verified; 15–30 h → 13–27 h; gap not closed |
|
||||
| 2026-10-12 | minor | Gap 25: Render to DNG lands as an export format; lossy DNG and AVIF import remain |
|
||||
| 2026-10-12 | minor | Gap 10 shrinks: the Hasselblad Lunar (a Sony NEX-7 ARW under its own Make) decodes and is verified, 236 models (#1275) |
|
||||
| 2026-10-12 | minor | Gap 14: HLG AVIF export (`hdrTransfer`) and a tested SDR/HDR display decision |
|
||||
| 2026-10-12 | minor | Gap 15: printer colour management lands (printer / paper ICC profiles or Managed by Printer, intent, black point compensation, print adjustment, print sharpening, 16-bit ICC-tagged PDF with an output intent); page overlays and direct printing remain |
|
||||
| 2026-10-12 | minor | Gap 15 shrinks: File → Print… is a Print dialog with the four layout styles, cell editing, image settings, guides, page setup and templates; printer colour management, page overlays and direct printing remain |
|
||||
| 2026-10-12 | minor | Gap 15: the Print module's layout styles, cells, image settings, templates and PDF are `print.*` commands (CLI, control, MCP); the Print view, printer colour management and page overlays remain |
|
||||
| 2026-10-12 | minor | Gap 15: print pages compose in the engine (fit / Zoom to Fill, Rotate to Fit, border, stroke, background) with an interim PDF writer; commands and UI still to land |
|
||||
| 2026-10-12 | minor | Gap 15: the Print layout model (paper sizes, margins, grid, package cells, Auto Layout packer, snapping) is in the engine; commands, composition and UI still to land |
|
||||
| 2026-10-12 | minor | Gap 25: lossy DNG export (DNG compression 34892) lands; AVIF import and Render to DNG as a catalog command remain |
|
||||
| 2026-10-12 | minor | Gap 22: pen pressure scales brush size and flow (Brush ▸ Pen Pressure) where winit reports a pen force |
|
||||
| 2026-10-12 | minor | Gaps 2 and 10 shrink: 22 more CR3 bodies verified on one CC0 file each (every CC0 CR3 on raw.pixls.us decodes), EOS R6 Mark III white balance read; Canon 34 verified, 259 models, ~59% on a verified body; CR3 gain +6.2 → +0.3 points |
|
||||
| 2026-10-12 | minor | Gap 10 shrinks: 117 Nikon and Fujifilm bodies verified on one CC0 file each (354 models, ~58% on a verified body); COOLPIX 5700 / 8400 / 8800 decode wrongly; #702 is fixed |
|
||||
| 2026-10-11 | minor | Nikon edge bars on bodies without CropArea fixed for 36 model / size / depth groups (#976, #914; survey in #1053); gap 10 notes the survey and the pending bodies; gap not closed |
|
||||
| 2026-10-11 | minor | Reviewed against main after 0.6.0: CR3 entry names the CRX variants `crx.rs` still refuses and the R7 / R6 Mark II C-RAW state (decoding, not verified, so the measured numbers don't move); CI and Windows / Linux entries note the riscv64 release build (#844); R7 fix added to Closed recently. Panel docking (UI.9, #869) closes no listed gap |
|
||||
| 2026-10-11 | minor | Camera colour entry: raws with a black-and-white camera JPEG take its tone curve (#577); gap not closed |
|
||||
| 2026-10-11 | minor | Gap 4: Compare and Reference views get zoom windows per pane (1:1 was a 2,560 px render magnified); overlays and soft proofing remain, 8–15 h → 4–8 h |
|
||||
@@ -95,3 +121,9 @@ Beta-blocking gaps (B) total **~230–430 h**; with the stability and platform w
|
||||
| 2026-10-10 | minor | Beta total raised to 340–600 h to include the ~92 open core-path user issues |
|
||||
| 2026-10-10 | major | Created from the checklist's Top gaps (whose items 1–2 had been duplicated by a merge) and ROADMAP's Where we stand; re-ranked; added evidence, impact, hours and beta flags; added platform-CI, lens-database, HE NEF and localization gaps |
|
||||
| 2026-10-13 | minor | Gap 8 narrows: Nikon Z 6II / Z 8 / Z f NEFs use the camera's in-file distortion correction (`docs/nikon-lens-corrections.md`) |
|
||||
| 2026-10-12 | minor | Catalog migration reports offline records as additions, keeps the destination/result readable, skips missing-original probes and stages only masters needed for virtual copies. Approximate rendering and database/table limits remain. |
|
||||
| 2026-10-13 | minor | Catalog import review: offline Local records join All Photos, redundant operation/settings copies removed, and result invalidation across library switches covered. Approximate rendering and database/table limits remain. |
|
||||
| 2026-10-14 | patch | LRC-LIB-CATALOG-IMPORT: reconciled with upstream phased progress, cancellation kinds, WAL-only import, translations and current progress tracking. Status and summary counts unchanged. |
|
||||
| 2026-10-10 | minor | Gap 8: Sony ILCE-7RM6 in-file distortion added next to the ILCE-7RM4A's, its lateral CA parsed but off by default (docs/sony-ilce7rm6-lens-corrections.md); the gap stays open (no lens database), hours unchanged |
|
||||
| 2026-10-14 | minor | Gap 10 shrinks: 97 Canon CR2, Pentax and Ricoh models verified on one CC0 file each (334 models, ~50% on a verified body) |
|
||||
| 2026-10-14 | minor | Gap 10: 515 of 1,446 models verified (36%), ~84% of photographers on a verified body (integration batch 36) |
|
||||
|
||||
@@ -105,6 +105,14 @@ rendering; `set VK_LOADER_DRIVERS_DISABLE=*igvk64*` (Vulkan loader) hides a spec
|
||||
from every program started with it. Help ▸ System Info and `app.gpu` show the adapter and backend in
|
||||
use (e.g. `Intel(R) UHD Graphics 630 (Dx12)`).
|
||||
|
||||
**LightCraft stops during an export or a render; the log says "device lost" (Windows, issue #1337).**
|
||||
When the graphics driver resets the GPU (the Windows watchdog, a driver hang: DXGI `0x887A0005`, "GPU
|
||||
device instance has been suspended"), renders fall back to the CPU, but the window's renderer (egui-wgpu)
|
||||
panics on the lost device and LightCraft stops. It says so ("LightCraft stopped unexpectedly", not "could
|
||||
not open its window") and records it in `gpu-lost.marker` in the settings folder: the next start turns
|
||||
*Use the GPU for rendering* off and says why once. Turn it back on in Settings ▸ Performance after a
|
||||
driver update.
|
||||
|
||||
**Window never appears, "not responding" (Windows, NVIDIA; issue #374).** With *Shader Cache Size*
|
||||
set to **Disabled** in NVIDIA Control Panel (Manage 3D settings → Global Settings), NVIDIA's driver
|
||||
walks the whole system drive while the window's GPU device is created (`D3D12CreateDevice` →
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Hardware parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (monitor profile from colord on Linux); previously major (created from the code, gpu-pipeline.md and the parity checklist) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (pen pressure for brush masks; monitor profile from colord on Linux); previously 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),
|
||||
@@ -14,7 +14,7 @@ What Lightroom does with the machine's hardware, per platform, and what LightCra
|
||||
| HDR (EDR) display | ✅ (macOS EDR, Windows HDR) | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ (LR-VIEW-HDR-DISPLAY) |
|
||||
| Monitor profile | automatic per display, follows the window | ✅ the screen's profile, followed across screens | 🟡 picked by hand (WCS needs FFI) | 🟡 colord's profile (one display, or all sharing one); no follow across monitors | — | 🟡 Windows OS profile not read; Linux per-monitor follow missing |
|
||||
| Second window / second monitor | ✅ (Classic) | ✅ (⌘F11) | ✅ | ✅ | — | ✅ (Classic secondary-window keys missing) |
|
||||
| Pen pressure / tilt (brush masks) | ✅ pressure for size / flow | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| Pen pressure / tilt (brush masks) | ✅ pressure for size / flow | ⬜ winit reports no tablet pressure on macOS | 🟡 pen force from winit touch events (untested on a tablet) | ⬜ winit has no X11 / Wayland tablet input | 🟡 pointer-event force where winit passes it | 🟡 brush size and flow follow pen pressure wherever egui gets a touch force (Brush ▸ Pen Pressure); no tilt; macOS / Linux tablets wait on winit |
|
||||
| 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) | ⬜ | ⬜ | ⬜ | — | ⬜ |
|
||||
@@ -38,7 +38,7 @@ NVIDIA, Intel and Windows DX12 still rely on user reports.
|
||||
|---|---:|---|
|
||||
| HDR display (EDR on macOS, Windows HDR, Linux where possible) | 10–20 | an HDR display to verify (human) |
|
||||
| OS monitor profile: Windows WCS (an FFI helper crate, like `crates/sysmem`), follow the window across displays on Linux | 4–8 | multi-monitor setup |
|
||||
| Pen pressure for brush masks (winit tablet events or a pure-Rust tablet layer) | 6–12 | a tablet |
|
||||
| Pen pressure for brush masks: done where winit reports a touch force; macOS and Linux tablets need winit tablet events (or a pure-Rust tablet layer) | 3–8 | 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) |
|
||||
@@ -51,4 +51,5 @@ NVIDIA, Intel and Windows DX12 still rely on user reports.
|
||||
|---|---|---|
|
||||
| 2026-10-12 | minor | Monitor profile: Linux reads the display profile from colord; macOS row reflects #787 |
|
||||
| 2026-10-12 | minor | CPU ↔ GPU equivalence suite run on an AMD Radeon 8060S (Vulkan, RADV, Linux): 16 tests / 135 cases pass, max 2 LSB, mean ≤ 0.0003; first GPU verified outside Apple |
|
||||
| 2026-10-12 | minor | Pen pressure: strokes record per-point pressure from egui touch force, scaling dab size and flow; per-platform status |
|
||||
| 2026-10-10 | major | Created |
|
||||
|
||||
@@ -4,6 +4,7 @@ Select photos in Photo Grid or Square Grid, then use:
|
||||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| `Enter` | Open the active photo in Detail from Photo Grid or Square Grid |
|
||||
| `Cmd+Shift+D` (macOS) / `Ctrl+Shift+D` (Windows/Linux) | Select only the active photo |
|
||||
| `0` | Clear the star rating |
|
||||
| `1`–`5` | Set the star rating |
|
||||
@@ -12,8 +13,12 @@ Select photos in Photo Grid or Square Grid, then use:
|
||||
| `P` | Flag as a pick |
|
||||
| `X` | Flag as rejected |
|
||||
| `U` | Clear the flag |
|
||||
| `` ` `` (backtick) | Cycle the flag: unflagged → pick → reject → unflagged |
|
||||
| `Cmd`/`Ctrl` + `↑` / `↓` | Raise / lower flag status (reject < unflagged < pick; stops at either end) |
|
||||
| `Shift` + `0`–`9`, `P`, `X` or `U` | Apply the action and select the next photo |
|
||||
|
||||
Enter opens the active photo without changing the selection. Text fields, dialogs and open popups keep the key; a custom Enter binding takes precedence. Enter has no additional action in Detail.
|
||||
|
||||
Select Only Active Photo (Edit menu) narrows the selection to the active photo. It does not change
|
||||
the photo, its edits or the last edit Undo step, and it works in any view that has an active photo.
|
||||
It can be reassigned or disabled in Help → Keyboard Shortcuts; text fields and dialogs keep the key.
|
||||
@@ -34,6 +39,16 @@ step. AutoWrite uses the normal rating metadata path. In Detail, including Maski
|
||||
remapping and disabling the default brush bindings take precedence over their grid bracket actions.
|
||||
The separate Decrease Rating / Increase Rating commands can also be assigned in Help → Keyboard Shortcuts.
|
||||
|
||||
Flag cycling and raise/lower use each photo's own flag, so a mixed selection steps together without being made uniform. Adobe's shortcut list names the backtick "Cycle flag settings" but does not state the order; unflagged → pick → reject is LightCraft's choice. The key is the logical grave key, so it follows the keyboard layout (on layouts where it is a dead accent key, assign another key in Help → Keyboard Shortcuts to `photo.cycleFlag`).
|
||||
|
||||
`Home` and `End` make the first or last photo of the view the active, selected one. `Shift` + `←` /
|
||||
`→` add the previous or next photo of the view to the selection and make the added photo active; the
|
||||
key never removes a photo from the selection, and at either end of the view it does nothing. These
|
||||
four keys work in Photo Grid and Square Grid only. They wait in Detail, Compare and Survey, in the
|
||||
full-screen preview (which covers the grid), while a text field or a dialog has the keyboard, and
|
||||
when you gave the same key to a command in Help → Keyboard Shortcuts, where they are listed under
|
||||
Fixed keys.
|
||||
|
||||
Grid actions apply to all selected photos and support Undo / Redo. In Compare and Survey, culling
|
||||
actions apply to the active photo. Auto Advance moves forward after an action; holding Shift with
|
||||
Auto Advance on still advances only once. The last photo stays selected. Text fields keep their
|
||||
@@ -51,7 +66,17 @@ commit `4e012a59a6d2442ba749f109ea27aadb5c0b11a5` by Gardy, and addresses the ca
|
||||
[issue #283](https://github.com/storytold/lightcraft/issues/283). That PR was open when checked
|
||||
on 2026-10-08; this work extends its fix with library culling bindings and tests.
|
||||
|
||||
Public behaviour references, checked 2026-10-08:
|
||||
## Grid thumbnail size
|
||||
|
||||
`=` makes the grid thumbnails larger and `-` smaller (`+` also enlarges), as in Lightroom Classic. Each
|
||||
press moves the bottom-bar slider by 30 pt within its 90–480 pt range and stops at either end. The keys
|
||||
work in Photo Grid, Square Grid and People (the views with the slider), do nothing in Detail, Compare,
|
||||
Survey and Reference, and leave text fields alone, so the search box still types `-` and `=`. `⌘=` /
|
||||
`⌘−` remain Zoom In / Out. The same steps are the View ▸ Increase / Decrease Grid Thumbnail Size
|
||||
commands (`view.thumbSizeUp`, `view.thumbSizeDown`, reachable from the control channel and MCP, which
|
||||
return `{"size"}`); the size is saved with the other interface settings.
|
||||
|
||||
Public behaviour references, checked 2026-10-08 (thumbnail size: 2026-10-13):
|
||||
|
||||
- [Lightroom Classic keyboard shortcuts](https://helpx.adobe.com/lightroom-classic/help/keyboard-shortcuts.html)
|
||||
- [Lightroom Classic flagging, labelling and rating](https://helpx.adobe.com/lightroom-classic/help/flag-label-rate-photos.html)
|
||||
|
||||
@@ -15,9 +15,21 @@ lightcraft-cli run --library "LightCraft Library" library.inspectLightroom path=
|
||||
lightcraft-cli run --library "LightCraft Library" library.importLightroom path="Lightroom Catalog.lrcat"
|
||||
```
|
||||
|
||||
Import adds records to the currently open LightCraft library; it does not create a separate
|
||||
folder named after the Lightroom catalog. The desktop result stays open until dismissed and
|
||||
shows the destination library, the number of records added, missing originals and warnings.
|
||||
**Show in Library** opens All Photos, clears filters and selects an imported record. Errors stay
|
||||
readable in the same result window. If another dialog is open, the result waits until that dialog closes. The result
|
||||
is also available through `library.importLightroom {"status":true}` during that session.
|
||||
|
||||
Original files are referenced in place. Ratings, picks/rejects, color labels, XMP metadata,
|
||||
hierarchical keywords, regular collections/collection sets, virtual copies and mapped develop
|
||||
settings are imported. Missing originals remain catalogued for relinking. Existing LightCraft
|
||||
settings are imported. Missing originals remain catalogued for relinking, count as added records and are reported
|
||||
separately from failures reading files that are present. Known-missing originals are not probed
|
||||
again. Previously browsed Local records join All Photos even when their originals are offline;
|
||||
their promotion is counted once and undone together with the catalog import.
|
||||
Virtual copies count as added records too; reimport reports zero additions when all
|
||||
records already exist. Existing LightCraft
|
||||
edits are preserved by default; `updateExisting=true` explicitly replaces them. Persistent import
|
||||
identity prevents reimport from duplicating virtual copies and collections. One undo step reverses
|
||||
catalog changes; any saved recovery archives remain available.
|
||||
@@ -32,8 +44,10 @@ retained. Oldest managed archives are retired; legacy `.json` archives remain un
|
||||
`Interop/lightroom-index.json` records imported identities. Source catalogs and originals are
|
||||
never overwritten.
|
||||
|
||||
Native import is bounded to a 1 GiB database/WAL, 16 MiB XMP packets and one million rows per
|
||||
table. The in-tree, read-only Rust SQLite B-tree reader follows SQLite’s public file-format
|
||||
Each native `.lrcat` database and WAL file is independently limited to 1 GiB
|
||||
(1,073,741,824 bytes). This bounds the current whole-file reader; referenced photo sizes and
|
||||
photo counts are not part of that limit. XMP packets are capped at 16 MiB and each table at one million rows.
|
||||
The in-tree, read-only Rust SQLite B-tree reader follows SQLite’s public file-format
|
||||
specification; it introduces no dependency or C runtime. Table payloads are capped at 256 MiB.
|
||||
Optional history, keyword and collection tables that exceed limits are skipped with warnings;
|
||||
required photo tables still report errors. Unrelated unsupported schemas are ignored. A needed
|
||||
@@ -61,6 +75,12 @@ Lightroom's `-999999` deferred-adjustment sentinel is omitted from both catalog
|
||||
it is reported, included in any saved archive, and never clamped into a real slider value. Deferred Adobe Auto Tone
|
||||
is not evaluated by the importer; LightCraft's Auto control remains available after migration.
|
||||
|
||||
New photo records are moved into staged operations; only masters needed for virtual copies
|
||||
retain a second owned record while the import commits.
|
||||
Applying catalog operations collects affected source-cache IDs before consuming the operations,
|
||||
avoiding another full operation copy. Full-strength develop patches reuse their JSON without
|
||||
serializing an unused copy of the current settings.
|
||||
|
||||
Native desktop inspection/import runs on a cancellable background worker with progress. Only
|
||||
prepared catalog operations commit on the owner thread; archive index writing stays on a worker.
|
||||
Late results from a closed or switched library are rejected, including reopening the same path.
|
||||
@@ -77,3 +97,12 @@ the path relative to the catalog that Lightroom records for root folders on the
|
||||
(`relativePathFromCatalog`), when that is a folder, and reports the remapping as a warning. Copying
|
||||
a project folder with its catalog inside it therefore keeps its originals linked. Other moved
|
||||
originals stay missing; use LightCraft's missing-photo relinking tools to update their paths.
|
||||
|
||||
Original and root folder paths are resolved with the catalog as the document and are looked at
|
||||
only when they are on this computer or on the network share the catalog itself is on
|
||||
(`crates/engine/src/doc_path.rs`). An original on another computer (`\\server\share\…`,
|
||||
`//server/…`, `file://server/…`), a device path, or one whose folder or file name in the catalog is
|
||||
an absolute path is not looked at: the import lists it as missing with a warning and leaves the
|
||||
photo and its virtual copies out of the library. To import originals on a share, open the catalog
|
||||
from that share. A path that is not a path on this computer (a Windows drive path read on macOS or
|
||||
Linux) is not looked at either and stays catalogued as missing.
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Čeština
|
||||
|
||||
Češtinu (`cs`, English name **Czech**, native name **Čeština**) zapnete přes **Úpravy → Jazyk →
|
||||
Čeština** nebo **Nastavení → Obecné → Jazyk**. Změna platí ihned a ukládá se pro další spuštění.
|
||||
Příkaz je `app.language.czech`; řídicí kanál přijímá `ui.set {"language":"cs"}` i značky
|
||||
`cs-CZ` a `cs_CZ.UTF-8`. Pro běh bez okna lze nastavit `LIGHTCRAFT_LANGUAGE=cs`.
|
||||
|
||||
Katalogy `crates/ui-egui/locales/cs.json` a `cs-formats.json` vznikly s pomocí AI pro @Losminek,
|
||||
po celých frázích podle významu anglických zdrojových řetězců. Výchozí seznam klíčů vycházel
|
||||
z největšího, ukrajinského katalogu; doplnilo se sjednocení ostatních katalogů a položky
|
||||
používané kódem. Překlad byl porovnán s konvencemi rozhraní aplikace a prošel nezávislou
|
||||
revizí rozsahu a terminologie. Rodilý mluvčí ani profesionální překladatel jej zatím nekorigoval.
|
||||
|
||||
## Konvence a rozsah
|
||||
|
||||
- Nabídky: Soubor, Úpravy, Zobrazení, Fotografie, Okno, Nápověda.
|
||||
- Library = Knihovna, Develop = Vyvolat, Collection = Kolekce, Preset = Přednastavení.
|
||||
- Flag = Příznak, Pick Flag = Příznak Vybráno, Soft Proofing = Měkký nátisk.
|
||||
- Clarity = Zřetelnost, Dehaze = Odstranit opar, Vibrance = Živost, Saturation = Sytost.
|
||||
- Highlights = Světla, Shadows = Stíny, Whites = Bílé, Blacks = Černé.
|
||||
- Filmstrip = Filmový pás, Virtual Copy = Virtuální kopie, Snapshot = Snímek stavu.
|
||||
- Datum má podobu `20. 9. 2026`, čas je 24hodinový (`16:04:05`).
|
||||
- Čísla používají společné formátování aplikace; tento jazyk nepřidává vlastní číselný formatter.
|
||||
- Počty používají neutrální formulace jako „Importováno fotografií: 22“ nebo
|
||||
„Čekající fotografie: 2“. Anglická přípona se podle společných pravidel spotřebuje pomocí
|
||||
`{:.0}`. Stávající mechanismus rozlišuje pouze jednotné a množné číslo; samostatné české
|
||||
plurálové pravidlo se nepřidává.
|
||||
- Písmo Inter dodávané s aplikací obsahuje české znaky i uvozovky „…“. Další font není potřeba.
|
||||
|
||||
Katalog obsahuje 2 056 běžných položek a 246 formátových šablon. Každý běžný klíč existuje
|
||||
v jiném katalogu nebo je používán kódem. Oproti německému katalogu má 108 dalších klíčů,
|
||||
všechny s doloženým použitím: popisky příkazů, menu, ovládacích prvků a nastavení,
|
||||
texty HDR/exportu a obličejů a kontextové hodnoty Ano/Ne. Z toho 41 klíčů již existuje
|
||||
v dalších katalozích a 67 doplňuje současné překladové lookupy.
|
||||
|
||||
Řádkové fragmenty poznámek k vydáním byly odstraněny, včetně 163 fragmentů převzatých
|
||||
ze sdílených katalogů; text poznámek v dialogu Co je nového používá anglický fallback.
|
||||
Společné nadpisy používané také v UI (například Library nebo Masking) zůstávají přeložené.
|
||||
|
||||
Úplné pokrytí katalogů neznamená úplnou jazykovou paritu: technické chyby nižších vrstev
|
||||
a některá hlášení mimo překladové rozhraní zůstávají anglicky. Překlad nemění data knihovny
|
||||
ani anglické zdrojové řetězce. Rozložení panelů a seznamu jazyků je beze změny.
|
||||
|
||||
## Ověření a revize
|
||||
|
||||
Testy `i18n::tests` ověřují registraci příkazu, přepínání přes nabídku a řídicí kanál,
|
||||
uložení jazyka, pokrytí katalogů, placeholdery, neutrální formulace počtů, datum, čas
|
||||
a české glyfy. Překladové šablony kontroluje také Rust při sestavení.
|
||||
|
||||
Při jazykové korektuře doporučujeme zkontrolovat „asistované třídění“, „sada“ pro Stack,
|
||||
„bodová barva“, „měkký nátisk“ a názvy kreativních přednastavení.
|
||||
Postup přidávání jazyků je v [localization.md](localization.md).
|
||||
|
||||
V této změně se doplnilo volání překladu u jednoduchých popisků v panelech osob a obličejů,
|
||||
volbě souboru modelu a podmínkách jeho instalace, výběru nepojmenovaných obličejů,
|
||||
pojmenování obličeje v detailu, instrukce tisku PDF a upozornění na PNG PQ,
|
||||
včetně textů barevného prostoru HDR. Anglické zdrojové texty zůstaly stejné.
|
||||
@@ -0,0 +1,77 @@
|
||||
# LightCraft in Georgian
|
||||
|
||||
Choose **Edit → Language → ქართული** or **Settings → General → Language**. The choice applies at once
|
||||
and is saved for the next launch (`language: "ka"` in `ui.json`); the control command is
|
||||
`app.language.georgian`. `LIGHTCRAFT_LANGUAGE` selects it for headless runs and accepts `ka`, `ka-GE`
|
||||
and `ka_GE.UTF-8`; the saved value is always `ka`. LightCraft does not follow the system language,
|
||||
for Georgian as for every other language.
|
||||
|
||||
The Georgian catalogs cover every key of the other catalogs plus all command and slider labels:
|
||||
menus, shortcuts, library, editing, crop, masks, people, import/export, settings, built-in presets and
|
||||
profiles, history, versions, date headings, status messages, the smart-album rule editor and the
|
||||
unsaved-changes dialog. The embedded release notes are translated too. Technical errors from lower
|
||||
layers stay in English, as in the other languages. They were written from the meaning of the English
|
||||
labels; no proprietary translation resources were consulted.
|
||||
|
||||
File names, command ids, template placeholders and albums, presets or metadata you named yourself are
|
||||
not translated. Descriptions for SAM 3 go to the model unchanged.
|
||||
|
||||
## Georgian script
|
||||
|
||||
Mkhedruli has no upper and lower case: `i18n::upper_first` leaves Georgian letters alone, and the
|
||||
interface never uses Mtavruli (a test checks the whole catalog). Commands are verbal nouns. Counts
|
||||
are count-neutral, noun first (`იმპორტირებულია ფოტო: 3`); English plural endings are dropped with
|
||||
`{:.0}`. Dates read `კვირა, 20.09.2026` (`{weekday}, {day:02}.{month:02}.{year}`), months `09.2026`.
|
||||
|
||||
Inter has no Georgian letters and craft-fonts has no Georgian face yet, so Georgian text shows boxes
|
||||
until a Georgian face is available to the UI.
|
||||
|
||||
## Terminology
|
||||
|
||||
| Source | Georgian |
|
||||
|---|---|
|
||||
| Library / Develop | ბიბლიოთეკა / დამუშავება |
|
||||
| File / Edit / View | ფაილი / რედაქტირება / ხედი |
|
||||
| Settings / General / Language | პარამეტრები / ზოგადი / ენა |
|
||||
| Import / Export | იმპორტი / ექსპორტი |
|
||||
| Photos / Albums / Folders | ფოტოები / ალბომები / საქაღალდეები |
|
||||
| Smart Album | სმარტ-ალბომი |
|
||||
| Crop | ჩამოჭრა |
|
||||
| Masks / Masking | ნიღბები / ნიღბვა |
|
||||
| Heal / Remove | აღდგენა / მოშორება |
|
||||
| Presets / Profile | პრესეტები / პროფილი |
|
||||
| History / Versions | ისტორია / ვერსიები |
|
||||
| Light / Color / Effects / Detail | სინათლე / ფერი / ეფექტები / დეტალი |
|
||||
| Exposure / Contrast | ექსპოზიცია / კონტრასტი |
|
||||
| Highlights / Shadows | ღია ტონები / ჩრდილები |
|
||||
| Whites / Blacks | თეთრები / შავები |
|
||||
| Texture / Clarity / Dehaze | ტექსტურა / სიცხადე / ბურუსის მოცილება |
|
||||
| Vibrance / Saturation | სიხალასე / გაჯერება |
|
||||
| Hue / Luminance | ფერის ტონი / სიკაშკაშე |
|
||||
| Tint | ტონირება |
|
||||
| Tone Curve / Color Grading | ტონალური მრუდი / ფერის გრადაცია |
|
||||
| Sharpening / Noise Reduction | გამკვეთრება / ხმაურის შემცირება |
|
||||
| Lens Corrections / Geometry | ობიექტივის კორექციები / გეომეტრია |
|
||||
| Vignette / Grain | ვინიეტი / მარცვლოვნება |
|
||||
| Feather / Threshold | კიდეების შერბილება / ზღვარი |
|
||||
| Rating / Flag / Keywords | შეფასება / დროშა / საკვანძო სიტყვები |
|
||||
| Reset / Revert | ჩამოყრა / წინა ვერსიაზე დაბრუნება |
|
||||
| Undo / Redo | დაბრუნება / გამეორება |
|
||||
|
||||
Please follow this table and the shared ArtCraft Georgian glossary when you add strings.
|
||||
|
||||
## Maintenance and checks
|
||||
|
||||
Fixed texts: `crates/ui-egui/locales/ka.json` (2,719 entries). Messages with values:
|
||||
`crates/ui-egui/locales/ka-formats.json` (249 entries). The English keys stay unchanged; Rust checks
|
||||
the placeholders at build time. Strings not yet in the plain catalog show in English.
|
||||
|
||||
```sh
|
||||
cargo test -p lightcraft-ui-egui i18n::tests -- --nocapture
|
||||
LIGHTCRAFT_LANGUAGE=ka lightcraft-cli snapshot --demo -o georgian.png --size 1600x1000
|
||||
```
|
||||
|
||||
The tests check catalog coverage, placeholders, switching language by menu and control channel,
|
||||
saving, the `ka` locale tags, dates, count wording, the absence of Mtavruli and that sentence case
|
||||
keeps Georgian lowercase. More notes are in
|
||||
[localization.md](localization.md).
|
||||
+16
-11
@@ -1,12 +1,12 @@
|
||||
# Localization parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (the interface no longer decides on error text, a prerequisite for translating lower-layer errors) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (de, es, fr, ja, uk catalogs filled; re-measured; Italian and Georgian interface catalogs added) · **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)).
|
||||
[ru](localization-ru.md), [ka](localization-ka.md)).
|
||||
|
||||
## The target
|
||||
|
||||
@@ -47,26 +47,28 @@ that is promising but is not recorded as review, so the column says `no (communi
|
||||
|---|---|---|---:|---|---|---|---|---:|
|
||||
| 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 |
|
||||
| 3 | Spanish | `es` | 2,362 / 2,398 (98%; 2026-10-12) | as zh-hans | Latin | no (community edits) | partial | 2–4 h (native review, lower-layer errors) |
|
||||
| 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 |
|
||||
| 6 | French | `fr` | 2,315 / 2,398 (97%; 2026-10-12, the rest are words spelled the same) | as zh-hans | Latin | no (community edits) | partial | 2–4 h (native review, lower-layer errors) |
|
||||
| 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 |
|
||||
| 9 | Japanese | `ja` | 2,383 / 2,398 (99%; 2026-10-12) | as zh-hans; vertical export watermarks | Jpan via craft-fonts (BIZ UDPGothic / UDMincho); IME through winit | no (community edits) | partial | 2–4 h (native review, lower-layer errors) |
|
||||
| 10 | German | `de` | 2,338 / 2,398 (97%; 2026-10-12, the rest are words spelled the same) | as zh-hans; What's New translated line by line | Latin | no (community edits) | partial | 2–4 h (native review, lower-layer errors) |
|
||||
| 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)
|
||||
## Other languages LightCraft ships (4)
|
||||
|
||||
| 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 |
|
||||
| Ukrainian | `uk` | 2,383 / 2,398 (99%; 2026-10-12) | Cyrillic (Inter) | no (community edits) | partial (lower-layer errors English) | 2–4 h |
|
||||
| Italian | `it` | 2,201 / 2,398 (92%, measured 2026-10-12; the rest is What's New) | Latin (Inter) | no (written with an agent; native-speaker pass pending) | partial (lower-layer errors English) | 3–5 h |
|
||||
| Georgian | `ka` | 2,398 / 2,398 (100%: every plain and formats message any catalog has on 2026-10-12, plus the 27 display labels and 397 What's New lines no other catalog translates) | Geor: no craft-fonts face yet (boxes until one is available) | yes (native speaker) | partial (lower-layer errors English) | 2–4 h (+ a Georgian face) |
|
||||
|
||||
Target languages LightCraft lacks: Italian, Korean, Dutch, Polish, Swedish, Norwegian Bokmål, Thai
|
||||
Target languages LightCraft lacks: 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.
|
||||
|
||||
@@ -83,13 +85,16 @@ Target languages LightCraft lacks: Italian, Korean, Dutch, Polish, Swedish, Norw
|
||||
|
||||
## Totals
|
||||
|
||||
- Bring the 9 shipped non-English catalogs to `full`: ~55–90 h (incl. the shared work).
|
||||
- Bring the 10 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).
|
||||
- Reach the target's 16 languages: + ~50–85 h (Dutch, Polish, Swedish, Norwegian, Thai).
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-12 | minor | Italian interface catalog (`it`): 2,201 of 2,398 messages, What's New left in English |
|
||||
| 2026-10-11 | minor | Shared work: the interface decides on error kinds, not English error text (#1046) |
|
||||
| 2026-10-12 | minor | Georgian (`ka`) row: every catalog message |
|
||||
| 2026-10-10 | major | Created: per-language counts measured from the catalogs, the twelve key languages, script support, estimates |
|
||||
| 2026-10-12 | minor | de, es, fr, ja and uk catalogs filled to every message another catalog knows (agent translations, native review welcome); those rows re-measured against the current 2,398 messages. Other rows keep their 2026-10-10 counts (open PRs for pt-BR, ru, zh) |
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
The interface ships in the language it is written in (English) plus every language in the table in
|
||||
`crates/ui-egui/src/i18n.rs`. Today that is English, Simplified Chinese (`zh-hans`), Traditional
|
||||
Chinese (`zh-hant`, Taiwan), Japanese (`ja`), Brazilian Portuguese (`pt-br`), Spanish (`es`), German (`de`), Russian (`ru`) and French (`fr`). This file is the reference for **adding or maintaining a language**; the per-language notes
|
||||
Chinese (`zh-hant`, Taiwan), Japanese (`ja`), Brazilian Portuguese (`pt-br`), Spanish (`es`), German (`de`), Russian (`ru`), French (`fr`), Ukrainian (`uk`), Czech (`cs`) and Georgian (`ka`). This file is the reference for **adding or maintaining a language**; the per-language notes
|
||||
are in [`localization-zh-hans.md`](localization-zh-hans.md), [`localization-zh-hant.md`](localization-zh-hant.md),
|
||||
[`localization-ja.md`](localization-ja.md), [`localization-pt-br.md`](localization-pt-br.md), [`localization-es.md`](localization-es.md),
|
||||
[`localization-de.md`](localization-de.md) and [`localization-ru.md`](localization-ru.md).
|
||||
[`localization-de.md`](localization-de.md), [`localization-ru.md`](localization-ru.md),
|
||||
[`localization-cs.md`](localization-cs.md) and [`localization-ka.md`](localization-ka.md).
|
||||
|
||||
## Adding a language
|
||||
|
||||
@@ -30,6 +31,9 @@ are in [`localization-zh-hans.md`](localization-zh-hans.md), [`localization-zh-h
|
||||
De, "de", "Deutsch", "Latn", include_str!("../locales/de.json");
|
||||
Ru, "ru", "Русский", "Cyrl", include_str!("../locales/ru.json");
|
||||
Uk, "uk", "Українська", "Cyrl", include_str!("../locales/uk.json");
|
||||
Cs, "cs", "Čeština", "Latn", include_str!("../locales/cs.json");
|
||||
It, "it", "Italiano", "Latn", include_str!("../locales/it.json");
|
||||
Ka, "ka", "ქართული", "Geor", include_str!("../locales/ka.json");
|
||||
}
|
||||
```
|
||||
|
||||
@@ -43,7 +47,9 @@ are in [`localization-zh-hans.md`](localization-zh-hans.md), [`localization-zh-h
|
||||
3. **Make sure the glyphs exist.** The script drives which craft-fonts faces the UI installs: a
|
||||
language whose script has no face in the build shows boxes (the test says so instead of failing).
|
||||
Fonts live in [storytold/craft-fonts](https://github.com/storytold/craft-fonts), never here; a
|
||||
missing face is added there, not worked around in this repository.
|
||||
missing face is added there, not worked around in this repository. Sentence-cased messages go
|
||||
through `i18n::upper_first`, which leaves Georgian lowercase (upper-casing Mkhedruli would make
|
||||
Mtavruli).
|
||||
4. Run `cargo xtask ci` (it includes `fmt`, `clippy`, the tests, `parity` and the wasm check).
|
||||
|
||||
## How a message is found
|
||||
|
||||
+48
-2
@@ -24,7 +24,12 @@ it open, `--library` on the same folder fails with "This library is already open
|
||||
the app is not running yet and connects on the first call (and reconnects if the app restarts).
|
||||
A request is sent again only when it never reached the app. If the connection drops after a request
|
||||
was sent but before its reply, the tool fails with "the outcome is unknown" and nothing is resent, so a
|
||||
command such as undo can't run twice: check the app's state before retrying.
|
||||
command such as undo can't run twice: check the app's state before retrying. Replies must be
|
||||
newline-terminated, at most 64 MiB before the newline (including encoded previews/screenshots),
|
||||
and carry the request's integer `id`, a boolean `ok`, and either a `result` or a string `error`.
|
||||
A malformed, incomplete, oversized or mismatched reply also closes the connection and reports
|
||||
an unknown outcome without resending. An idless `ok: false` with a string `error` is preserved
|
||||
as a pre-dispatch refusal (for example, too many control connections); the next call reconnects.
|
||||
|
||||
Logs go to stderr; stdout carries only protocol messages.
|
||||
|
||||
@@ -203,6 +208,37 @@ JSON params (documented in each tool's description and by `list_commands`). Pass
|
||||
leave these per-command tools out when a client struggles with a large tool list; `run_command`
|
||||
still reaches every command.
|
||||
|
||||
Slideshow slides, for example: `cmd_slideshow_layout` reads or changes the slide layout (margins,
|
||||
zoom to fill, stroke border, cast shadow, backdrop colour, colour wash, background image; saved with
|
||||
the library) and `cmd_slideshow_preview {id?, width?, height?, path?}` composes one slide with it —
|
||||
written as a PNG to `path`, or returned as base64 PNG in `png` — so an agent can look at a layout
|
||||
before playing it. `cmd_slideshow_playback` sets the timing and fades. `cmd_slideshow_overlays` sets the
|
||||
overlays drawn on every slide (identity plate text or image, rating stars, text overlays with tokens such as
|
||||
`{caption}` or `{exposure}`, the export watermark); its reply lists `warnings` (an unreadable plate image, tags that
|
||||
aren't tokens), and `cmd_slideshow_preview` returns each overlay's box. `cmd_slideshow_titles` sets the intro and ending
|
||||
screens (colour, the identity plate or a line of text, scale, duration), and `cmd_slideshow_preview {title: "intro"}`
|
||||
renders one. Templates bundle all four: `cmd_slideshow_templates_list` lists the built-in and user templates (and files
|
||||
it skipped), `cmd_slideshow_templates_apply {id}` replaces the settings with one (the replaced ones stay available as
|
||||
`{id: "previous"}` for the session), `cmd_slideshow_preview {template: id}` previews one without applying it, and
|
||||
`cmd_slideshow_templates_save` / `update` / `rename` / `delete` / `import` / `export` manage the user's own (JSON files
|
||||
in `<settings>/slideshow-templates`).
|
||||
`cmd_slideshow_export {format: "pdf"|"jpeg"|"video", path, size?, quality?, fps?, container?: "mp4"|"webm",
|
||||
fullScreen?, name?, ids?, wait?}` writes the slideshow (titles included) as a PDF (a page per slide), a numbered JPEG
|
||||
sequence in a folder, or an AV1 video (no audio). It runs in the background and returns `{taskId, total, …}`:
|
||||
`cmd_activity_list` shows its progress, `cmd_activity_cancel {id: taskId}` stops it (nothing is left on disk) and
|
||||
`cmd_slideshow_exportStatus` gives the result (`pages`, `files`, or `frames` / `samples` / `seconds` for video) or the
|
||||
error. With `wait: true` the call blocks and replies with the result.
|
||||
|
||||
### Preview-only raws after an update
|
||||
|
||||
A raw LightCraft couldn't decode when it was imported is shown from its embedded preview
|
||||
(`previewOnly` in `catalog.query`). The desktop app rechecks such photos in the background when a
|
||||
library opens in a newer (or older) LightCraft version, so a raw the new decoder handles develops
|
||||
from its raw data without a manual Reload. Headless sessions don't do this on their own: call
|
||||
`cmd_library_recheckPreviewOnly` (`{all: true}` ignores the version stamps, e.g. to test a decoder
|
||||
build) → `{checked, updated, cleared}`. Like the app's recheck, it isn't an undo step and keeps
|
||||
develop settings and history.
|
||||
|
||||
## Resources
|
||||
|
||||
`resources/list` / `resources/read` serve JSON snapshots:
|
||||
@@ -211,7 +247,7 @@ still reaches every command.
|
||||
|---|---|
|
||||
| `lightcraft://library` | Source, filter, sort, selection, undo/redo labels (`library.state`) |
|
||||
| `lightcraft://photos` | Photos in the current view (`catalog.query`) |
|
||||
| `lightcraft://photo/active` | Everything about the active photo (`photo.inspect`) |
|
||||
| `lightcraft://photo/active` | Everything about the active photo (`photo.inspect`), including the camera's focus point as `meta.focus` when the file records one ([focus-points.md](focus-points.md); `run_command photo.readFocusPoints {wait: true}` reads it for photos imported before it was read, a few KB per file) |
|
||||
| `lightcraft://develop/active` | The active photo's develop settings (`develop.get`) |
|
||||
| `lightcraft://controls` | Every develop control with its current value (`develop.controls`) |
|
||||
|
||||
@@ -314,5 +350,15 @@ being processed finishes first: completed photos remain, each written with the e
|
||||
file writer, and there are no partial files to delete. Unrelated outputs and earlier exports
|
||||
are untouched. A failed export is an `isError` tool result. Transport mutexes recover poisoning.
|
||||
|
||||
If a protocol write or flush fails, the CLI reports the output error and shuts down without
|
||||
waiting for stdin to close. Output failures are observable only when writing. An active direct
|
||||
headless export stops at the next photo boundary; a synchronous command and normal backend
|
||||
cleanup must finish first. Completed exports and library cleanup retain their usual guarantees.
|
||||
|
||||
Library callers serving process stdin use `Server::serve_stdio(stdout())` once per process and
|
||||
exit after it returns. Its single stdin worker may remain blocked until process exit. The generic
|
||||
`Server::serve(input, output)` keeps borrowed input scoped: its caller must arrange input EOF or
|
||||
an input error, even when output fails.
|
||||
|
||||
Connect mode and exports inside `command_batch` remain synchronous and do not report MCP
|
||||
progress or cancellation. Use a direct headless export call for this behavior.
|
||||
|
||||
+24
-6
@@ -10,12 +10,17 @@ All algorithms are our own implementations from published papers (cited in the m
|
||||
*HDR Panorama…* from the photo context menu (or the `dialog.merge*` commands). The dialog previews
|
||||
the merge at ≤ 1024 px and re-runs the preview when an option changes; *Merge* runs the full merge
|
||||
in the background (a row in the activity stack shows its progress, with ✕ to stop it). The result is written next to the first photo as
|
||||
`<name>-HDR.dng`, `-Pano.dng` or `-HDR-Pano.dng`, imported and selected.
|
||||
`<name>-HDR.dng`, `-Pano.dng` or `-HDR-Pano.dng`, imported and selected. *Photo Merge ▸ HDR for Each Bracket Set*
|
||||
merges many brackets in one go with the last HDR options: one HDR per stack among the selected photos, then per
|
||||
bracket (photos taken less than a second apart, after the shutter time, at exposures at least ½ EV apart; a burst at
|
||||
one exposure is skipped), one after the other in the activity stack.
|
||||
- **Commands** (CLI, MCP, control channel):
|
||||
- `merge.hdr {ids?, align=true, deghost=none|low|medium|high, autoSettings=true, stack=false, preview=false, showOverlay=false, previewPath?}`
|
||||
- `merge.panorama {ids?, projection=auto|spherical|cylindrical|perspective, boundaryWarp=0..100, autoCrop=false, fillEdges=false, autoSettings=true, maxMegapixels=40, preview, previewPath?}`
|
||||
- `merge.panorama {ids?, projection=auto|spherical|cylindrical|perspective, boundaryWarp=0..100, autoCrop=false, fillEdges=false, autoSettings=true, maxMegapixels (default: the photos' own resolution), preview, previewPath?}`
|
||||
- `merge.hdrPanorama {ids?, bracket=0 (from EXIF), …both sets of options}`
|
||||
- **CLI:** `lightcraft-cli merge hdr|panorama|hdr-panorama [options] FILES…`;
|
||||
- `merge.hdrBatch {ids?, align, deghost, autoSettings, stack}` → `{merged: [{id, path, …}], failed: [{photos, error}]}`
|
||||
- **CLI:** `lightcraft-cli merge hdr|panorama|hdr-panorama|hdr-batch [options] FILES…` (`hdr-batch` finds the brackets
|
||||
among the files, e.g. a whole folder);
|
||||
`lightcraft-cli synth-merge hdr|panorama -o DIR` writes synthetic inputs (procedural scene).
|
||||
|
||||
## What it does
|
||||
@@ -25,8 +30,14 @@ reference. Auto Align: features on exposure-normalised luminance, RANSAC transla
|
||||
homography (the simplest model that explains ≥ 97 % of the matches). Exposure ratios are measured
|
||||
(median log ratio of well-exposed pixels between brightness neighbours), EXIF is the fallback.
|
||||
Radiance is a weighted mean in linear light, weight `k · (1 − smoothstep(0.8·clip, 0.96·clip, max
|
||||
channel))`. Deghost: a per-pixel consistency test against the reference radiance (with a noise
|
||||
floor), dilated and feathered masks; the union is the deghost overlay. Output: 16-bit float DNG.
|
||||
channel within 1 px))`: a pixel next to clipped photosites was demosaiced from them and reads low in the clipped
|
||||
channel, so it goes with them (on real ARW brackets the brightest frame's green was 3–5 % low there, and bright
|
||||
windows took a magenta tinge). The frames are taken in brightness order (ties by content), so the result doesn't
|
||||
depend on the order they come in. Where the reference is at or near its clip the scene is at least that bright, so a frame that reads far
|
||||
darker there (an object moved: a star, the moon, a passing light) is left out and the clipped highlight stays (always
|
||||
on: a moving star otherwise left a black hole). Deghost: a per-pixel consistency test on ≤ 2048 px versions against the
|
||||
reference radiance (with a noise floor; the reference predicts down to 0.1 % of its clip, so a brighter frame's ghost in
|
||||
a night sky is caught), dilated and feathered masks; the union is the deghost overlay. Output: 16-bit float DNG.
|
||||
Lens corrections: frames are merged uncorrected, and the DNG's `OpcodeList3` carries the reference frame's
|
||||
(`WarpRectilinear`, `WarpRectilinear2`, `FixVignetteRadial`: a DNG's own, or a camera's correction a raw reader
|
||||
converts, e.g. Sony, Panasonic), re-expressed for its default crop (`Opcode::cropped`). So Optics ▸ Enable Lens
|
||||
@@ -52,7 +63,10 @@ scale in `BaselineExposure`; raw sources keep their DNG colour tags (camera RGB)
|
||||
|
||||
- HDR, 3 brackets ±2 EV with 14-bit noise and handheld shifts: alignment error < 0.3 px, exposure
|
||||
error < 0.02 EV, radiance median log error < 0.03 (noise-limited, bias < 0.01), recovered
|
||||
highlights < 0.05; moving object: ghost error 0.2–2.0 without deghosting, < 0.06 with High.
|
||||
highlights < 0.05; moving object: ghost error 0.2–2.0 without deghosting, < 0.06 with High; a star that moves
|
||||
across a night sky keeps its clipped core and, with High, leaves no ghost of the brightest frame.
|
||||
- Real brackets (Sony A7R VI, 67 MP, 2026-10-14): frames agree with the merged radiance within ~1 % from 3 to 90 % of
|
||||
their clip in all three channels; measured exposure steps match EXIF within 0.03 EV.
|
||||
- Panorama, 5 views over 182° with a 1.3× exposure drift: relative rotations < 0.1°, focal < 1 %,
|
||||
BA RMS ≈ 0.35 px; median log error vs ground truth < 0.02; no seam steps.
|
||||
|
||||
@@ -63,9 +77,13 @@ scale in `BaselineExposure`; raw sources keep their DNG colour tags (camera RGB)
|
||||
panoramas carry no lens corrections, nor does an HDR whose frames don't share an orientation (they are turned
|
||||
before merging).
|
||||
- No camera response calibration for JPEG brackets (sRGB decoding is taken as linear light).
|
||||
- AI Denoise doesn't run on merged DNGs (they are linear RGB; the denoiser takes Bayer raws), unlike Lightroom's.
|
||||
- Boundary Warp is a separable stretch, not a content-preserving mesh warp; Fill Edges is diffusion,
|
||||
not patch synthesis.
|
||||
- *Create Stack*: the result goes on top of a collapsed stack of its sources (`Catalog::stack_with_ops`); its
|
||||
caption also lists them.
|
||||
- Panorama output is limited to `maxMegapixels` (default 40) — blending memory is ~25 bytes/pixel.
|
||||
- HDR memory: every frame is held as 32-bit float RGB (~0.86 GB per 67 MP frame at the peak, plus ~1.2 GB); full-size
|
||||
photos are decoded one at a time. Measured on 67 MP raws: 3 frames 3.8 GB, 4 frames 4.7 GB, 5 frames 5.5 GB (was
|
||||
4.8 / 6.3 GB for 3 / 4). Half-float frames would halve the per-frame share.
|
||||
- The browser build has no file access for merges yet.
|
||||
|
||||
+149
-82
File diff suppressed because one or more lines are too long
+87
-57
@@ -1,12 +1,13 @@
|
||||
# RAW parity: cameras, formats, demosaic, colour and lens profiles
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (Nikon Z 6II / Z 8 / Z f in-file distortion correction; Leica Q3 verified by a recorded check of 38 private DNGs; EOS R5 Mark II decoded and verified: CRX QP-map escape, odd-height planes) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6 (Camera Raw 18.7)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-18 · **Change:** patch (X-Trans CMOS 4 bodies take the X-T3's spectral matrices) · **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), [nikon-lens-corrections.md](nikon-lens-corrections.md),
|
||||
[raf-compression.md](raf-compression.md), [sony-lens-corrections.md](sony-lens-corrections.md),
|
||||
[sony-ilce7rm6-lens-corrections.md](sony-ilce7rm6-lens-corrections.md), [nikon-lens-corrections.md](nikon-lens-corrections.md),
|
||||
[camera-preview-colour.md](camera-preview-colour.md), [denoise.md](denoise.md).
|
||||
|
||||
## Headline
|
||||
@@ -14,18 +15,16 @@ ranked in [gaps.md](gaps.md). Details per format: [cr3.md](cr3.md),
|
||||
| Measure | Value | Kind |
|
||||
|---|---:|---|
|
||||
| Adobe-listed camera models | **1,446** | measured: [raw/adobe-cameras.tsv](raw/adobe-cameras.tsv) |
|
||||
| Decoded from sensor data and **verified** on a real file | **236** (16%) | measured: [raw/evidence.tsv](raw/evidence.tsv) |
|
||||
| Decoder path should handle it, **unverified** | **941** (65%) | measured from the format rules (631 of them DNG, mostly phones) |
|
||||
| **Preview-only** (embedded JPEG) | **233** (16%) | measured |
|
||||
| Decoder path should handle it, **unverified** | **942** (65%) | measured from the format rules (632 of them DNG, mostly phones) |
|
||||
| **Preview-only** (embedded JPEG) | **232** (16%) | measured |
|
||||
| **Unsupported** (not imported, refused or decodes wrongly) | **36** (2%) | measured |
|
||||
| Models added since 2017 (Camera Raw 10+): verified / unverified / preview / unsupported | 83 / 639 / 24 / 8 of 754 | measured |
|
||||
| **Share of photographers whose camera fully works** (decodes from sensor data), use-weighted | **~85%** | estimated: measured classes × written usage weights × per-format confidence |
|
||||
| …of which on a body we have verified | **~42%** | estimated, same weights |
|
||||
| Camera colour: Adobe profiles vs ours | 1,500 Adobe Standard profiles, 481 models with Camera Matching profiles vs **4 bundled profiles** + per-file fits + 52 spectral matrices | measured (bundle listing, Adobe list, `assets/camera-profiles`) |
|
||||
| Decoded from sensor data and **verified** on a real file | **545** (38%) | measured: [raw/evidence.tsv](raw/evidence.tsv) |
|
||||
| Decoder path should handle it, **unverified** | **651** (45%) | measured from the format rules (631 of them DNG, mostly phones) |
|
||||
| **Preview-only** (embedded JPEG) | **212** (15%) | measured |
|
||||
| **Unsupported** (not imported, refused or decodes wrongly) | **38** (3%) | measured |
|
||||
| Models added since 2017 (Camera Raw 10+): verified / unverified / preview / unsupported | 182 / 542 / 22 / 8 of 754 | measured |
|
||||
| **Share of photographers whose camera fully works** (decodes from sensor data), use-weighted | **~94%** | estimated: measured classes × written usage weights × per-format confidence |
|
||||
| …of which on a body we have verified | **~85%** | estimated, same weights |
|
||||
| Camera colour: Adobe profiles vs ours | 1,500 Adobe Standard profiles, 481 models with Camera Matching profiles vs **5 bundled profiles** + per-file fits + 52 spectral matrices (plus same-sensor aliases) | 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) |
|
||||
| **RAW readiness** (decoding 60%, colour 25%, lens 15%) | **~60%** (range 54–64%) | 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,
|
||||
@@ -43,9 +42,10 @@ committed table is stale.
|
||||
`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
|
||||
`RAW_SAMPLES` manifest (`xtask/src/main.rs`, 105 CC0 files; bodies whose sample is in
|
||||
`KNOWN_UNSUPPORTED` excluded), `crates/raw/tests/cr3_corpus.rs` (3 bodies exact against an external decoder;
|
||||
the EOS R5 Mark II pinned, with a QP-map check of 33,665 private files), the RAF reference
|
||||
the EOS R5 Mark II pinned, with a QP-map check of 33,665 private files; 22 more bodies pinned on one CC0
|
||||
file each and checked against the camera JPEG, [cr3.md](cr3.md#further-bodies-one-cc0-file-each)), 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), and a recorded check of 38 private Leica Q3 DNGs (2026-10-11: every file
|
||||
@@ -53,6 +53,17 @@ committed table is stale.
|
||||
at 400 px; the files are not committed). 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.
|
||||
- **2026-10-12 public sweep:** 30 further models on 40 CC0 files, independently downloaded and
|
||||
decoded on main `25ef65c8`; [raw/coverage-sweep.tsv](raw/coverage-sweep.tsv) records the URLs,
|
||||
SHA-256, dimensions, FNV-1a sensor hashes and render/reference luminance correlations (0.6801
|
||||
to 0.9998). The hashes pin LightCraft's own output. The regression test is
|
||||
`crates/raw/tests/coverage_sweep_corpus.rs`; downloads are in `RAW_SAMPLES`. Ten references are
|
||||
embedded TIFF images; the rest are JPEGs. FFF TIFF previews are not display-ready and check
|
||||
image structure only. Eleven candidate models were excluded for identity, provenance or
|
||||
missing/mismatched reference images. D6 / Z 6 / Z 7 verification covers compressed NEF only;
|
||||
uncompressed remains preview-only (#671), as do Z 8 HE / HE* files. Own-matrix phone, drone
|
||||
and other DNGs can decode correctly while rendering darker than their camera JPEG (#1277).
|
||||
Verified means sensor data decoded, not colour parity.
|
||||
- **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
|
||||
@@ -61,51 +72,51 @@ committed table is stale.
|
||||
~8 years (listed in the file), 20% to the bucket's other Adobe models.
|
||||
- **Per-format confidence** for unverified bodies (the chance their files decode correctly): DNG, CR2,
|
||||
RAF, RW2 0.95; NEF, ARW, PEF 0.9; ORF, SRW, SR2 0.8; **CR3 0.6** (the CRX decoder refuses several
|
||||
coding variants and only four bodies are verified; maintainers report the R7 working).
|
||||
coding variants; 26 bodies are verified, every CC0 CR3 on raw.pixls.us decodes).
|
||||
|
||||
## 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 | 12 | 99 | 21 | 2 | CRW (2000–2004 bodies) preview; EOS-1D / 1Ds TIFF raws not imported |
|
||||
| Samsung | 128 | 1 | 118 | 9 | 0 | compressed SRW (NX1, NX30, NX300, NX500, NX2000, NX3000, NX3300, NX mini, Galaxy NX) |
|
||||
| Apple | 113 | 1 | 112 | 0 | 0 | — (DNG / ProRAW) |
|
||||
| Sony | 149 | 94 | 43 | 9 | 3 | DSLR-A200…A390 and A850 12-bit compressed ARW (preview, #535); A100 preview-only and DSC-F828 refused (#702 fixed the regression; their raws aren't decoded); SRF not imported |
|
||||
| Canon | 134 | 95 | 16 | 21 | 2 | CRW (2000–2004 bodies) preview; EOS-1D / 1Ds TIFF raws not imported |
|
||||
| Samsung | 128 | 10 | 109 | 9 | 0 | compressed SRW (NX1, NX30, NX300, NX500, NX2000, NX3000, NX3300, NX mini, Galaxy NX) |
|
||||
| Apple | 113 | 4 | 109 | 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 | 14 | 47 | 0 | 0 | — |
|
||||
| Nikon | 99 | 77 | 19 | 0 | 3 | COOLPIX 5700 / 8400 / 8800 decode wrongly (two stacked half-height fields, CMYG read as RGB); HE / HE★ is a per-shot setting, preview-only |
|
||||
| Fujifilm | 97 | 65 | 9 | 23 | 0 | pre-X FinePix RAF without a raw IFD (estimated split) |
|
||||
| Google | 88 | 5 | 83 | 0 | 0 | — |
|
||||
| Olympus | 71 | 17 | 3 | 51 | 0 | **compressed ORF** |
|
||||
| Leica | 61 | 27 | 34 | 0 | 0 | — |
|
||||
| Xiaomi, Oppo, LG, Huawei, OnePlus, Motorola, Nokia | 139 | 0 | 139 | 0 | 0 | — (DNG) |
|
||||
| Pentax / Ricoh | 60 | 4 | 56 | 0 | 0 | — |
|
||||
| Hasselblad | 34 | 1 | 2 | 31 | 0 | Hasselblad-compressed 3FR / FFF |
|
||||
| Phase One / Leaf / Mamiya | 59 | 0 | 0 | 43 | 16 | IIQ, MOS preview; TIFF raws and MEF not imported |
|
||||
| Pentax / Ricoh | 60 | 40 | 20 | 0 | 0 | — |
|
||||
| Hasselblad | 34 | 7 | 2 | 25 | 0 | Hasselblad-compressed 3FR / FFF |
|
||||
| Phase One / Leaf / Mamiya | 59 | 1 | 0 | 43 | 15 | IIQ, MOS preview; TIFF raws not imported (MEF decodes) |
|
||||
| Casio | 26 | 0 | 26 | 0 | 0 | — (DNG) |
|
||||
| DJI | 21 | 0 | 21 | 0 | 0 | — (DNG) |
|
||||
| DJI | 21 | 4 | 17 | 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** | **236 (16%)** | **941 (65%)** | **233 (16%)** | **36 (2%)** | |
|
||||
| Kodak, Konica Minolta, Epson, Sigma, GoPro, Contax, others | 56 | 6 | 11 | 24 | 15 | DCR, GPR not imported; KDC, MRW, X3F preview (Epson ERF decodes) |
|
||||
| **All** | **1,446** | **545 (38%)** | **651 (45%)** | **212 (15%)** | **38 (3%)** | |
|
||||
|
||||
## By use (estimated)
|
||||
|
||||
| Bucket | Weight | Camera fully works | On a verified body | Why |
|
||||
|---|---:|---:|---:|---|
|
||||
| Canon | 33% | 73% | 19% | 18 of the 22 popular bodies write CR3; 4 of them verified (M50, R8, R100, R5 Mark II), the rest at 0.6 |
|
||||
| Sony | 27% | 98% | 91% | bulk-checked |
|
||||
| Nikon | 16% | 91% | 12% | decoders cover every NEF coding but HE; few bodies verified |
|
||||
| Fujifilm | 10% | 91% | 45% | |
|
||||
| Canon | 33% | 95% | 93% | 18 of the 22 popular bodies write CR3; 26 CR3 bodies verified (raw.pixls.us has a CC0 file for each), the rest at 0.6 |
|
||||
| Sony | 27% | 98% | 92% | bulk-checked |
|
||||
| Nikon | 16% | 98% | 89% | decoders cover every NEF coding but HE; 77 bodies verified |
|
||||
| Fujifilm | 10% | 94% | 92% | |
|
||||
| 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% | 96% | 21% | the Q3 verified |
|
||||
| DJI | 1% | 95% | 0% | |
|
||||
| Medium format and others | 0.5% | 23% | 1% | IIQ, 3FR, X3F |
|
||||
| **Weighted** | 100% | **85%** | **42%** | |
|
||||
| OM / Olympus | 3% | 6% | 5% | compressed ORF |
|
||||
| Phones | 3% | 93% | 4% | DNG |
|
||||
| Pentax / Ricoh | 1.5% | 99% | 80% | |
|
||||
| Leica | 1% | 99% | 72% | the Q3 verified, 13 more bodies pinned on CC0 files |
|
||||
| DJI | 1% | 96% | 19% | |
|
||||
| Medium format and others | 0.5% | 29% | 8% | IIQ, 3FR, X3F |
|
||||
| **Weighted** | 100% | **94%** | **85%** | |
|
||||
|
||||
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.
|
||||
About 19 in 20 raw photographers' cameras decode, and about 5 in 6 use a body we have actually
|
||||
checked (the per-model CC0 sweeps of October 2026); compressed ORF (OM / Olympus) is the largest gap left.
|
||||
|
||||
## Variant matrix (depth per format)
|
||||
|
||||
@@ -113,6 +124,8 @@ checked, and Canon, the largest bucket, is the weakest of the big four.
|
||||
|
||||
| Format | Variant | Status | Evidence |
|
||||
|---|---|---|---|
|
||||
| 2026-10-12 | minor | Mamiya MEF decoded (`vendor/mef.rs`): ZD verified; 241 verified, 35 unsupported |
|
||||
| 2026-10-12 | minor | Epson ERF decoded (`vendor/erf.rs`): R-D1, R-D1s, R-D1x verified; 240 verified, 229 preview (merged after the Leica Q3 and Hasselblad Lunar; duplicated summary rows removed) |
|
||||
| CR2 | lossless JPEG slices | ✅ | 8 corpus bodies; CFA phase from `CR2CFAPattern` (#85, 35 bodies); masked-column black level; white level from the active area only (#1272: masked rows at 16383 hid the image plateau on the EOS 50D, 60D, 450D (Rebel XSi), 500D (Rebel T1i), 550D (Rebel T2i), 1200D (Rebel T5) and 100D (Rebel SL1), clipped highlights at 81–98%) |
|
||||
| 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; R5 Mark II (odd-height planes) pinned |
|
||||
@@ -122,7 +135,7 @@ checked, and Canon, the largest bucket, is the weakest of the big four.
|
||||
| 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; D4 and D90 image area and white level measured against the camera JPEG |
|
||||
| NEF | uncompressed, lossless, lossy type 1 / 2, lossy after split | ✅ | D5100, D7000, D7500, Z f corpus; ~60 NEFs by hand; #633; D4, D90, D5000, D600 and D610 image area measured against the camera JPEG (white level too for the D4, D90 and D5000) |
|
||||
| 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; the Hasselblad Lunar, a NEX-7 under Make HASSELBLAD, routed by Sony's raw coding (#1275) |
|
||||
@@ -144,12 +157,14 @@ checked, and Canon, the largest bucket, is the weakest of the big four.
|
||||
| DNG | uncompressed, LJ92, lossy JPEG / Smart Preview, Deflate incl. float, LinearRaw, tiles / strips, row / column interleave | ✅ | 6 corpus DNGs; 4 ILCE-6400 JXL DNGs; 38 Leica Q3 DNGs (lossless JPEG, 14-bit, private check) |
|
||||
| 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 | phone DNGs (Pixel, Galaxy, Xiaomi…) | 🟡 | Pixel 2 XL corpus; 13 further Apple, Google and Samsung models in the pinned sweep; white-level pile-up fix #548 |
|
||||
| DNG | GoPro GPR (VC-5) | ⬜ | refused |
|
||||
| 3FR / FFF | DNG-like layouts | 🟡 | decoded when uncompressed or LJ92 |
|
||||
| 3FR / FFF | DNG-like layouts | 🟡 | six Hasselblad models verified on nine files; read by `vendor::hasselblad`: an FFF has no colour matrix of its own and now takes the camera's from the original 3FR header it embeds in tag `0xC51B` (it used to develop with the neutral matrix); RGGB checked against the camera preview on the CC0 H4D-40 FFF and CFV 3FR; the embedded preview is the uncompressed 8-bit RGB image (no JPEG in these files), handed on as a baseline TIFF |
|
||||
| 3FR / FFF | Hasselblad compression | ⬜ | preview |
|
||||
| IIQ, MOS, MRW, ERF, KDC, X3F | all | ⬜ | preview; an uncompressed MOS, whose IFD0 is the mosaic itself with no Make tag, is recognised by Leaf's data block `0x8606` (#1275) |
|
||||
| DCR, MEF, MFW, DXO, GPR, TIFF raws | all | ⬜ | not imported |
|
||||
| ERF | 12-bit in 16-byte blocks (R-D1, R-D1s, R-D1x) | ✅ | 3 CC0 corpus files; crop registered and WB measured against the embedded preview (no WB tag found); `vendor/erf.rs` |
|
||||
| IIQ, MOS, MRW, KDC, X3F | all | ⬜ | preview; an uncompressed MOS, whose IFD0 is the mosaic itself with no Make tag, is recognised by Leaf's data block `0x8606` (#1275) |
|
||||
| MEF | uncompressed 12-bit (Mamiya ZD) | ✅ | 1 CC0 corpus file; crop and WB from its uncompressed RGB preview (no JPEG, no WB tag); `vendor/mef.rs` |
|
||||
| DCR, MFW, DXO, GPR, TIFF raws | all | ⬜ | not imported |
|
||||
|
||||
### Compressed ORF: a clean-room starting point
|
||||
|
||||
@@ -178,7 +193,7 @@ sample files. A pointer for contributors, not legal advice.
|
||||
| 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); CR2 white level taken from saturated masked rows (#1272, 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) |
|
||||
| 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, measured Nikon bodies without it (D4, D90) | 🟡 7RM3 / 7RM4 crop origin 8–32 px off (cosmetic) |
|
||||
| Crop masks and aspect | ✅ | DefaultCrop, Sony recorded size, Canon AspectInfo, Panasonic in-camera crops, Nikon CropArea, measured Nikon bodies without it (D4, D90, D5000, D600, D610) | 🟡 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 |
|
||||
@@ -190,7 +205,7 @@ sample files. A pointer for contributors, not legal advice.
|
||||
|
||||
| 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 |
|
||||
| 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 (**5 bundled**: ILCA-99M2, 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, and the bodies sharing their sensors: 6 X-Trans CMOS 4 Fujifilm bodies take the X-T3's); 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) |
|
||||
@@ -219,7 +234,7 @@ essentials user (the default look is what they keep).
|
||||
| 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); Nikon NikonNEFInfo distortion (tag `0xc7d5`, about the sensor-shifted optical centre) for the Z 6II and Z f: F-mount lenses on the FTZ within 0.2 px of the camera JPEG, Z lenses within 0.5–1.5 px except the 24-70's wide end (7 px median; `docs/nikon-lens-corrections.md`) |
|
||||
| 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) and the ILCE-7RM6 (3 lenses, 54 photos; `sony-ilce7rm6-lens-corrections.md`); Nikon NikonNEFInfo distortion (tag `0xc7d5`, about the sensor-shifted optical centre) for the Z 6II and Z f: F-mount lenses on the FTZ within 0.2 px of the camera JPEG, Z lenses within 0.5–1.5 px except the 24-70's wide end (7 px median; `docs/nikon-lens-corrections.md`) |
|
||||
| Vignetting / lateral CA from maker notes | ✅ | ⬜ |
|
||||
| Manual distortion, vignetting, CA, defringe | ✅ | ✅ |
|
||||
|
||||
@@ -230,10 +245,10 @@ drone DNG users (~9% of photographers by the weights above); Adobe reaches nearl
|
||||
|
||||
| Part | Weight | Score | Basis |
|
||||
|---|---:|---:|---|
|
||||
| Decoding | 60% | **77%** | use-weighted 85% × 0.9 (76.5%) for per-body decode bugs still surfacing (levels, crops, WB: #535, #455, #461, #702) |
|
||||
| Decoding | 60% | **83%** | use-weighted 92% × 0.9 (82.8%) 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.9 + 8.75 + 1.5; demosaic and highlight quality unmeasured |
|
||||
| **RAW readiness** | 100% | **~60%** (range 54–64%) | 49.7 + 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
|
||||
@@ -249,15 +264,15 @@ 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 other 14 popular CR3 bodies | +6.2 | 25–45 | ~0.19 | samples per body (raw.pixls.us has most) |
|
||||
| 3 | Verify popular Nikon, Fujifilm, Canon CR2 and Pentax bodies (one CC0 file each, fix what breaks) | +2.0 | 8–15 | ~0.17 | public samples |
|
||||
| 2 | CR3: remaining CRX variants (no public file uses them) | +0.3 | 10–25 | ~0.02 | files that open as a preview, from users |
|
||||
| 3 | ~~Verify popular Nikon, Fujifilm, Canon CR2 and Pentax bodies (one CC0 file each, fix what breaks)~~ done (#1045, #1081) | (+2.0, taken) | — | — | 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 |
|
||||
| 10 | Compressed SRW, Hasselblad 3FR, IIQ, X3F, MRW, KDC, DCR, GPR (ERF, MEF done) | +0.6 together | 45–85 | ~0.01 | samples; low use |
|
||||
|
||||
Beyond decoding:
|
||||
|
||||
@@ -272,15 +287,30 @@ Beyond decoding:
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-18 | patch | X-T30, X-T30 II, X-Pro3, X100V, X-S10 and X-E4 take the X-T3's spectral matrices (same 26.1 MP X-Trans CMOS 4 sensor): an X-T30 raw with a black-and-white (Acros) camera JPEG no longer opens in the muted neutral fallback |
|
||||
| 2026-10-15 | minor | Hasselblad 3FR / FFF embedded previews: the uncompressed 8-bit RGB image, handed on as a baseline TIFF (checked on the CC0 H4D-40 FFF, 1217 × 913, and CFV 3FR, 218 × 218, upright through the file's orientation); counts unchanged |
|
||||
| 2026-10-15 | minor | Hasselblad 3FR / FFF get their own reader (`crates/raw/src/vendor/hasselblad.rs`): an FFF takes its colour matrix from the original 3FR header in tag `0xC51B` instead of developing with the neutral matrix; RGGB checked against the camera preview on the CC0 H4D-40 FFF and CFV 3FR; counts unchanged |
|
||||
| 2026-10-14 | minor | Camera-coverage sweep (#1327): 30 models verified on 40 CC0 files (`coverage_sweep_corpus.rs`, `coverage-sweep.tsv`; `docs/raw/coverage.py` 515 → 545 verified rows); the counts above are not re-measured here. Sensor verification does not establish colour parity (#1277) |
|
||||
| 2026-10-13 | minor | Bundled camera profiles 4 → 5 (ILCA-99M2) |
|
||||
| 2026-10-14 | minor | 21 Sony and Leica models verified (one CC0 raw.pixls.us file each, pinned; `sony_leica_corpus.rs`): 258 verified, 920 unverified; Leica on a verified body 21% → 72%, Sony 91% → 92%, use-weighted 85% and 43% |
|
||||
| 2026-10-14 | minor | 17 uncompressed Olympus and Samsung models verified on one CC0 file each (`olympus_samsung_corpus.rs`): 254 verified, 932 unverified, 224 preview; OM / Olympus 3% → 6% (5% on verified bodies); use-weighted 85% and 42% unchanged; duplicated summary rows from a merge removed |
|
||||
| 2026-10-14 | minor | Nikon D600 and D610 image area (6016 × 4016 at 8, 6) measured on 4 CC0 NEFs of each, and the D90's area and white level applied to the D5000 (same sensor and filler, 2 CC0 NEFs): the filler and noise columns on the right no longer develop as a band, and for these bodies the white level is measured inside the image area, issue #1627 |
|
||||
| 2026-10-11 | minor | Leica Q3 verified by a recorded check of 38 private DNGs (no decode failure; mean ΔE to the camera JPEG 6.3–13.9): 236 verified, 941 unverified, Leica bucket on a verified body 5% → 21%, weighted shares unchanged |
|
||||
| 2026-10-12 | patch | CR2 white level from the active area, not the saturated masked rows above it (#1272: EOS 50D, 60D, 450D (Rebel XSi), 500D (Rebel T1i), 550D (Rebel T2i), 1200D (Rebel T5) and 100D (Rebel SL1)); scores unchanged |
|
||||
| 2026-10-12 | minor | Canon PowerShot G9: as-shot white balance from WBInfo (`0x0029`, the row of the preset in ShotInfo), issue #1273; render unchanged (the camera-look fit already absorbed it), As Shot now the camera's; counts unchanged |
|
||||
| 2026-10-12 | minor | Olympus E-10: as-shot white balance (`0x1017`/`0x1018`) and black level (`0x1012` in `0x102c` ValidBits units) from the main maker note, issue #1273; ΔE76 against its thumbnail 18.5 → 11.5, camera-look fit now accepted; counts unchanged |
|
||||
| 2026-10-13 | minor | Nikon D90 image area (4288 × 2848 at 10, 10) and white level (3830) measured on 10 of 550 NEFs from one body: its 42 filler columns no longer develop as a pink band |
|
||||
| 2026-10-12 | minor | Hasselblad Lunar verified (a Sony NEX-7 ARW under Make HASSELBLAD, now decoded): 236 verified, 232 preview; an uncompressed Leaf MOS is recognised as a raw (preview only) instead of opening as a greyscale image of its mosaic (#1275) |
|
||||
| 2026-10-12 | minor | 22 more CR3 bodies verified (one CC0 raw.pixls.us file each, pinned, checked against the camera JPEG; all 110 CC0 CR3s decode); EOS R6 Mark III ColorData 66 white balance: 259 verified, 919 unverified; use-weighted 92% (59% on verified bodies); Canon 73% → 94%; decoding 83%, RAW readiness ~56% → ~60%; CR3 gain +6.2 → +0.3 |
|
||||
| 2026-10-12 | minor | 117 Nikon and Fujifilm bodies verified (one CC0 raw.pixls.us file each, pinned, checked against the camera JPEG; `body_corpus.rs`); COOLPIX 5700 / 8400 / 8800 decode wrongly (now unsupported); #702 fixed, A100 preview-only: 354 verified, 824 unverified, 230 preview, 38 unsupported; use-weighted 86% (58% on verified bodies); decoding 77% unchanged |
|
||||
| 2026-10-11 | minor | Nikon: every body without `CropArea` surveyed (#1053); 36 model / size / depth groups cropped to their measured camera frame (#976, #914), 6 pending; NEF row no longer claims every coding but HE decodes (compressed NEFs without a linearization table listed) |
|
||||
| 2026-10-10 | minor | Compressed ORF: pointer to the two Olympus patents that describe the method, as a clean-room starting point |
|
||||
| 2026-10-12 | minor | PEF without area tags: masked border rows and columns trimmed against the BlackPoint (issue #1271; KP, KF, K-3 Mark III, K-70, K-1, K-1 Mark II, K-S1, K-S2, 645Z); counts unchanged |
|
||||
| 2026-10-13 | minor | Lens profiles: Nikon in-file distortion (NikonNEFInfo `0xc7d5`) for the Z 6II, Z 8 and Z f, validated on 83 frames from three lenses and the CC0 Z f sample (`docs/nikon-lens-corrections.md`); lens score unchanged |
|
||||
| 2026-10-11 | minor | EOS R5 Mark II verified (CRX QP-map first literal and limited-length escape, odd-height Bayer planes; 4 CC0 files pinned, QP maps of 33,665 private files): 235 verified, 942 unverified; use-weighted 85% (42% on verified bodies); decoding 77%, RAW readiness unchanged at ~56% |
|
||||
| 2026-10-10 (later) | major | Model-by-model measurement against Adobe's published list (1,446 models: 234 verified, 943 unverified, 233 preview, 36 unsupported); `docs/raw/` data and re-measure script; use-weighted share 84% (40% on verified bodies); variant matrix; colour and lens sections with scores; ranked next cameras; RAW readiness ~56% from written parts |
|
||||
| 2026-10-10 | major | Created: formats, makers, demosaic, colour and lens checklists; target counts from the installed Lightroom 9.6 bundle listing |
|
||||
| 2026-10-10 (later) | minor | Lens profiles: Sony ILCE-7RM6 in-file distortion next to the ILCE-7RM4A's (its lateral CA parsed, off by default); lens score unchanged (~10%: one more body) |
|
||||
| 2026-10-14 | minor | 97 Canon CR2, Pentax and Ricoh models verified (one CC0 raw.pixls.us file each, pinned, checked against the camera JPEG; `canon_pentax_corpus.rs`): 334 verified, 844 unverified, 232 preview; 50% of photographers on a verified body; use-weighted 85% unchanged |
|
||||
| 2026-10-14 | minor | Integration batch 36: CC0 per-model verification for 117 Nikon/Fujifilm, 97 Canon CR2/Pentax/Ricoh, 21 Sony/Leica and 23 Olympus/Samsung bodies, 22 more CR3 bodies and 30 more models; Epson ERF and Mamiya MEF decode; measured Nikon image areas (#1053, #1770): 515 verified, 675 unverified, 218 preview, 38 unsupported (re-measured with `coverage.py`) |
|
||||
| 2026-10-15 | minor | By-maker and by-use tables re-measured with `coverage.py` after batches 36–39 (545 verified, 651 unverified, 212 preview, 38 unsupported; ~94% of photographers' cameras fully work, ~85% on a verified body); rows the per-model PRs had updated are current again |
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# CC0 raw.pixls.us camera-coverage check, 2026-10-12; main 25ef65c8. File SHA-256 matches the public listing.
|
||||
# FNV-1a-64 pins LightCraft's own complete decoded samples, row-major little-endian, including masked borders.
|
||||
# Default renders at up to 1200 px; Pearson r on Lab L* at 200 px after orientation/aspect alignment, threshold 0.6.
|
||||
# Hasselblad PreviewTIFF references check image structure only. Own-matrix DNG tone remains subject to issue #1277.
|
||||
maker camera id file url sha256 width height cpp samples fnv1a64 luma_r reference notes
|
||||
Apple iPhone 6s Plus 915 coverage-915.dng https://raw.pixls.us/getfile.php/915/nice/Apple%20-%20iPhone%206s%20Plus%20-%2016bit%20%284:3%29.DNG 845fee4f09c832af3728778737f5ae9b99124debb821b6e2066b94aed1daa91c 4032 3024 1 u16 17e4d3c620d593c9 0.9712 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -10.109
|
||||
Apple iPhone 7 Plus 939 coverage-939.dng https://raw.pixls.us/getfile.php/939/nice/Apple%20-%20iPhone%207%20Plus%20-%2016bit%20%284:3%29.DNG e8c7ebd8f22f7281d165496b91c8fea8a8e79c8113172fb499e1d66d6045332e 4032 3024 1 u16 d0095a8b553f0f8a 0.9904 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -11.913
|
||||
Apple iPhone XS 3372 coverage-3372.dng https://raw.pixls.us/getfile.php/3372/nice/Apple%20-%20iPhone%20XS%20-%2016bit%20%284:3%29.dng 50bc64ee8cfbbfb6c0531e29ab428ff985506a16fe2d1d2e74656f21b54505f6 4032 3024 1 u16 a8e819ac4e5beb2a 0.9805 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -14.751
|
||||
DJI DJI Mavic 2 Pro (Hasselblad L1D-20c) 3009 coverage-3009.dng https://raw.pixls.us/getfile.php/3009/nice/Hasselblad%20-%20L1D-20c%20-%2016bit%20%283:2%29.DNG 7afecae0db80d832941eeeb3c0eb2dc03f5696637b6e78b3c592e8c002dce4ec 5568 3648 1 u16 b207313fa7dee601 0.9781 embedded JPEG 16bit (3:2); comparison Normal/crop-render; mean dL -8.41
|
||||
DJI DJI Mavic 3 (Hasselblad L2D-20c) 5140 coverage-5140.dng https://raw.pixls.us/getfile.php/5140/nice/Hasselblad%20-%20L2D-20c%20-%2016bit%20%284:3%29.DNG dbe98cb202f884ff11e0144899613b26d33cf9cddd9f1a62226f4352397f18e4 5376 3956 1 u16 2c78ceb8cb893ff1 0.8618 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL 0.418
|
||||
DJI DJI Mavic 4 Pro (DJI FC9287) 8041 coverage-8041.dng https://raw.pixls.us/getfile.php/8041/nice/DJI%20-%20FC9287%20-%2016bit%20%2816:9%29.DNG 901b7970f02f7197c782f111363feef02108f75811342d8cc4a2b66757bb7af0 8192 4608 1 u16 d1babb4646097d6f 0.6801 embedded JPEG 16bit (16:9); reference has a different distortion/crop; comparison Normal/crop-render; mean dL 2.583
|
||||
DJI DJI Mini 2 4785 coverage-4785.dng https://raw.pixls.us/getfile.php/4785/nice/DJI%20-%20FC7303%20-%2016bit%20%284:3%29.DNG 21a49e63966f82391ca1188c7559c3acc01a35a89a70194fda4bf44cbd64a851 4000 3000 1 u16 d1e66e08f335b55b 0.9328 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -9.016
|
||||
DJI DJI Mini 2 4898 coverage-4898.dng https://raw.pixls.us/getfile.php/4898/nice/DJI%20-%20FC7303%20-%2016bit%20%2816:9%29.DNG fb4f294e12cab7b507fd0b7c07f24e5d13e7c0dd127b534ce12c48d644c9363d 4000 2250 1 u16 acaab4fe42d3dc58 0.9716 embedded JPEG 16bit (16:9); comparison Normal/crop-render; mean dL -8.153
|
||||
Google Pixel 4 XL 3502 coverage-3502.dng https://raw.pixls.us/getfile.php/3502/nice/Google%20-%20Pixel%204%20XL%20-%2016bit%20%284:3%29.dng 0c03a6c93b4b8593cd0e4426166e6389710007238b82eb23861ef191322f0c54 3700 2774 1 u16 d121f233fdbaff2c 0.9143 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -0.351
|
||||
Google Pixel 4a Rear Wide Camera 4176 coverage-4176.dng https://raw.pixls.us/getfile.php/4176/nice/Google%20-%20Pixel%204a%20-%2016bit%20%284:3%29.dng 11b38186ee3455376291bcdb3049728a3f9dcd94b9e82ff76855d9f3430e44be 4032 3024 1 u16 ac056154d440cb2d 0.9515 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -2.361
|
||||
Google Pixel 6 Pro Rear Main Camera 5961 coverage-5961.dng https://raw.pixls.us/getfile.php/5961/nice/Google%20-%20Pixel%206%20Pro%20-%2016bit%20%284:3%29.dng 3a859e917a91698a3e15ce3b3721a48a1fb1296873e0697d3bf7c2793297200d 4080 3072 1 u16 96631250f12729ad 0.944 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -0.402
|
||||
Google Pixel 8 Pro Wide Camera* 7751 coverage-7751.dng https://raw.pixls.us/getfile.php/7751/nice/Google%20-%20Pixel%208%20Pro%20-%2016bit%20%284:3%29.dng 45420c595401547cca950ae58d552bc82b32d31ce1d58c082df33004016197f5 8160 6144 1 u16 5e30a4d3bfc914b3 0.9485 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -5.099
|
||||
Hasselblad CFV-50c 7217 coverage-7217.3fr https://raw.pixls.us/getfile.php/7217/nice/Hasselblad%20-%20CFV-50c%20-%2016bit%20%284:3%29.3FR e27ff177519298fe7bae64506b975190789dc0e6ad70bea58be7c78fd094eae0 8374 6304 1 u16 14e60b95775930f2 0.9984 exiftool:PreviewTIFF 16bit (4:3); comparison Normal/crop-render; mean dL -14.199
|
||||
Hasselblad CFV-50c 7218 coverage-7218.fff https://raw.pixls.us/getfile.php/7218/nice/Hasselblad%20-%20CFV-50c%20-%2016bit%20%284:3%29.fff c8d78912ae725a59acff42a4b4731350bbddd4a600423f319579261bd41da932 8374 6304 1 u16 db63ffcd176381ee 0.9443 exiftool:PreviewTIFF 16bit (4:3); TIFF preview is not display-ready; neutral-matrix colour remains unverified; comparison Normal/crop-render; mean dL 28.828
|
||||
Hasselblad H5D-40 1640 coverage-1640.fff https://raw.pixls.us/getfile.php/1640/nice/Hasselblad%20-%20H5D-40%20-%2016bit%20%284:3%29.fff 209d464e13702de5f4fdb830ac26ac140c98a8d0dc3e81c5ba61d93677330832 7410 5586 1 u16 1d34f6f4e45b5eab 0.9574 exiftool:PreviewTIFF 16bit (4:3); TIFF preview is not display-ready; neutral-matrix colour remains unverified; comparison Normal/crop-render; mean dL 29.541
|
||||
Hasselblad H5D-50c 1639 coverage-1639.fff https://raw.pixls.us/getfile.php/1639/nice/Hasselblad%20-%20H5D-50c%20-%2016bit%20%284:3%29.fff 1aad9319fcbab81b851a74c3eeaa2a07fc5013bf2c4e272fd31d6419b6b9adb0 8374 6304 1 u16 02a189d2a6b78d4e 0.9453 exiftool:PreviewTIFF 16bit (4:3); TIFF preview is not display-ready; neutral-matrix colour remains unverified; comparison Normal/crop-render; mean dL 28.943
|
||||
Hasselblad X1D 2058 coverage-2058.3fr https://raw.pixls.us/getfile.php/2058/nice/Hasselblad%20-%20X1D%20-%2016bit%20%284:3%29.3FR 395acb2c706dc10270c58ec261e42a5e36f6ac8c39d2a767e86e83648aa318a3 8384 6304 1 u16 0b480efe4d2ed7c2 0.9753 exiftool:PreviewTIFF 16bit (4:3); comparison Normal/crop-render; mean dL -9.059
|
||||
Hasselblad X1D II 50C 3874 coverage-3874.fff https://raw.pixls.us/getfile.php/3874/nice/Hasselblad%20-%20X1D%20II%2050C%20-%2016bit%20%284:3%29.fff 8c2451b3478fb529b4e9bd51ed3267999ce26eb1fcb5c3b93c3ae7bc56267794 8384 6304 1 u16 c7372897d70da8a8 0.9436 exiftool:PreviewTIFF 16bit (4:3); TIFF preview is not display-ready; neutral-matrix colour remains unverified; comparison Normal/crop-render; mean dL 22.474
|
||||
Hasselblad X1D II 50C 3941 coverage-3941.3fr https://raw.pixls.us/getfile.php/3941/nice/Hasselblad%20-%20X1D%20II%2050C%20-%2016bit%20%284:3%29.3FR 809d498263d6f07cbaa4b9a5be97933057b4ab21e7243bb7afbe3862f3b48b47 8384 6304 1 u16 3c3a77bf67197196 0.9982 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -11.176
|
||||
Hasselblad X2D 100C 6568 coverage-6568.fff https://raw.pixls.us/getfile.php/6568/nice/Hasselblad%20-%20X2D%20100C%20-%2016bit%20%284:3%29.fff 44977fdaa3063eacbb2ac416dfb531bb4e3b96f3745d073dc49fb1ebcd78bedc 11904 8842 1 u16 849906d491fba55a 0.9196 exiftool:PreviewTIFF 16bit (4:3); TIFF preview is not display-ready; neutral-matrix colour remains unverified; comparison Normal/crop-render; mean dL 26.781
|
||||
Hasselblad X2D 100C 6565 coverage-6565.3fr https://raw.pixls.us/getfile.php/6565/nice/Hasselblad%20-%20X2D%20100C%20-%2016bit%20%284:3%29.3FR dcc5a4abe3498e6f25e89bb491995fd12c3b669d9277c71b45b49210d3e56280 11904 8842 1 u16 c07a267c0bc60a5f 0.9962 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -2.632
|
||||
Nikon D6 4726 coverage-4726.nef https://raw.pixls.us/getfile.php/4726/nice/Nikon%20-%20D6%20-%2012bit%2012bit%20compressed%20%28Lossy%20%28type%202%29%29%20%283:2%29.NEF 3a098e704d0e1af97efc37541b43a37e5b3457d2f4e7828c0d8d9af37332f233 5584 3728 1 u16 272425c271bb0d76 0.9557 embedded JPEG 12bit 12bit compressed (Lossy (type 2)) (3:2); comparison Normal/crop-render; mean dL 0.037
|
||||
Nikon D6 4720 coverage-4720.nef https://raw.pixls.us/getfile.php/4720/nice/Nikon%20-%20D6%20-%2014bit%2014bit%20compressed%20%28Lossless%29%20%283:2%29.NEF 827bcfff8a3cd86278382c353e4542faab52cf12c365540f30753bb4c6fabc0f 5584 3728 1 u16 1d6a9f10a502fb14 0.9581 embedded JPEG 14bit 14bit compressed (Lossless) (3:2); comparison Normal/crop-render; mean dL 0.048
|
||||
Nikon D6 4721 coverage-4721.nef https://raw.pixls.us/getfile.php/4721/nice/Nikon%20-%20D6%20-%2014bit%2014bit%20compressed%20%28Lossy%20%28type%202%29%29%20%283:2%29.NEF 081d5dbc1d6c97935020d33ffa486dcaa8d4564cbde280cfadcf26ff61da2838 5584 3728 1 u16 2d6c8af38e4a0ed4 0.9592 embedded JPEG 14bit 14bit compressed (Lossy (type 2)) (3:2); comparison Normal/crop-render; mean dL 0.043
|
||||
Nikon Z 6 3584 coverage-3584.nef https://raw.pixls.us/getfile.php/3584/nice/Nikon%20-%20Z%206%20-%2012bit%2012bit%20compressed%20%283:2%29.NEF 3cbd9acf9e9bfd7d0c62c46436109556a101f7535c5fd25f86dad6ea61bf3886 6064 4040 1 u16 a63b22e83bb7c82f 0.8749 embedded JPEG 12bit 12bit compressed (3:2); comparison Normal/crop-render; mean dL 0.327
|
||||
Nikon Z 6 3581 coverage-3581.nef https://raw.pixls.us/getfile.php/3581/nice/Nikon%20-%20Z%206%20-%2014bit%2014bit%20compressed%20%283:2%29.NEF 8ca94584578b35a422744c1a610174ce37df0691588edfdecaec3111b3fbbb02 6064 4040 1 u16 1e23d74a11c01a97 0.8752 embedded JPEG 14bit 14bit compressed (3:2); comparison Normal/crop-render; mean dL 0.353
|
||||
Nikon Z 6 3582 coverage-3582.nef https://raw.pixls.us/getfile.php/3582/nice/Nikon%20-%20Z%206%20-%2014bit%2014bit%20lossless%20compressed%20%283:2%29.NEF c079345fc93f53a4f0d322f8ddaae505f920c36015f25b58befccaa61db1af31 6064 4040 1 u16 0a0bc73568e125e0 0.8755 embedded JPEG 14bit 14bit lossless compressed (3:2); comparison Normal/crop-render; mean dL 0.464
|
||||
Nikon Z 7 2792 coverage-2792.nef https://raw.pixls.us/getfile.php/2792/nice/Nikon%20-%20Z%207%20-%2012bit%2012bit%20compressed%20%283:2%29.NEF c861546fbcf5826d5eb26d223e2143fa32968e89f7edbc5bb10c283ea5461ded 8288 5520 1 u16 c989690cb3e19ef9 0.7417 embedded JPEG 12bit 12bit compressed (3:2); comparison Normal/crop-render; mean dL 2.417
|
||||
Nikon Z 7 2789 coverage-2789.nef https://raw.pixls.us/getfile.php/2789/nice/Nikon%20-%20Z%207%20-%2012bit%2012bit%20compressed%20%283:2%29.NEF e54a6c4264bf685214f538036fd9d39088e510b2bfedf288e568f0db1897880e 8288 5520 1 u16 627867ac6a8dd4ad 0.7412 embedded JPEG 12bit 12bit compressed (3:2); comparison Normal/crop-render; mean dL 2.299
|
||||
Nikon Z 7 2790 coverage-2790.nef https://raw.pixls.us/getfile.php/2790/nice/Nikon%20-%20Z%207%20-%2012bit%2012bit%20compressed%20%283:2%29.NEF f0e756dbfd00f3b71cb3d8aa5b9e2e1be32f1052a6c4380e09ebc7c5e7748114 8288 5520 1 u16 8a52e6f3d8ff64dd 0.7389 embedded JPEG 12bit 12bit compressed (3:2); comparison Normal/crop-render; mean dL 2.585
|
||||
Nikon Z 8 6617 coverage-6617.nef https://raw.pixls.us/getfile.php/6617/nice/Nikon%20-%20Z%208%20-%208bit%208bit%20compressed%20%283:2%29.NEF c13a8675294456b9c979e6c1e556951654f35377b2870af2874bfb556f21ce40 8280 5520 1 u16 716e1158bab28b76 0.9563 embedded JPEG 8bit 8bit compressed (3:2); comparison Normal/crop-render; mean dL 2.044
|
||||
Parrot Anafi 2912 coverage-2912.dng https://raw.pixls.us/getfile.php/2912/nice/Parrot%20-%20Anafi%20-%2016bit%20%284:3%29.DNG a257a296047ff2d396109fd2e6947fa36aa7986695b6815f83979d59e98a84e6 5344 4016 1 u16 07a188c932a25a31 0.9895 embedded JPEG 16bit (4:3); comparison Normal/crop-render; mean dL -3.924
|
||||
Samsung Galaxy S21 Ultra Rear Main Camera 6728 coverage-6728.dng https://raw.pixls.us/getfile.php/6728/nice/Samsung%20-%20Galaxy%20S21%20Ultra%20-%204:3.dng 5baeb5f0c4a125647df03b82c2d38b0f02784393bd39eff1a5b23d8f5308dc5e 4000 3000 3 u16 16c5d6faed83390d 0.9912 embedded JPEG 4:3; comparison Rotate180/crop-render; mean dL -10.83
|
||||
Samsung Galaxy S22 Ultra Rear Wide Camera 6261 coverage-6261.dng https://raw.pixls.us/getfile.php/6261/nice/Samsung%20-%20Galaxy%20S22%20Ulra%20-%204:3.dng 53e7f83a94c965495ba32d3ea6021ef08ed02244ce64d111d1329bbd01fd5581 4000 3000 3 u16 7cbe612adc5575b4 0.9739 embedded JPEG 4:3; comparison Normal/crop-render; mean dL -20.487
|
||||
Samsung Galaxy S23 Rear Wide Camera 6697 coverage-6697.dng https://raw.pixls.us/getfile.php/6697/nice/Samsung%20-%20Galaxy%20S23%20-%204:3.dng 1c04574f32b5a139922f075291c52018b89d9981ee155a16958a231c1fdbb067 8160 6120 3 u16 b3da1535e2e31e9f 0.9418 embedded JPEG 4:3; comparison Normal/crop-render; mean dL -6.585
|
||||
Samsung Galaxy S7 Edge 1297 coverage-1297.dng https://raw.pixls.us/getfile.php/1297/nice/Samsung%20-%20G935F%20-%2016bit%20%2816:9%29.dng 843617c8b572320b7badfb4ac2eda19479f5804a1dabb909c861bde23ed30561 4032 2268 1 u16 7e99d7da67022e5a 0.8677 exiftool:PreviewTIFF 16bit (16:9); comparison Normal/crop-render; mean dL 5.772
|
||||
Samsung Galaxy S8 2645 coverage-2645.dng https://raw.pixls.us/getfile.php/2645/nice/Samsung%20-%20SM-G950F%20-%2016bit%20%284:3%29.dng 6abdd353094964eaadddf69bba3a0d551ecce1bc0ed013a434691df4f64dcbf2 4032 3024 1 u16 b70ca9a743283754 0.9884 exiftool:PreviewTIFF 16bit (4:3); comparison Normal/crop-render; mean dL -4.112
|
||||
Samsung Galaxy S8+ 2310 coverage-2310.dng https://raw.pixls.us/getfile.php/2310/nice/Samsung%20-%20SM-G955F%20-%2016bit%20%284:3%29.dng 3cf5da4331d062bc6b31e0e8f5b7ff2cd21107de4262d79a2667f670516e8e8c 4032 3024 1 u16 c3a20523ad3b18cf 0.986 exiftool:PreviewTIFF 16bit (4:3); comparison Normal/crop-render; mean dL 2.437
|
||||
Sigma fp 7273 coverage-7273.dng https://raw.pixls.us/getfile.php/7273/nice/Sigma%20-%20fp%20-%2014bit%20%283:2%29.DNG 0844bcf23a49e21b5c2f8489de55ce38fb7b594e3ed337d6b9af2dd9341354e9 6064 4042 1 u16 f7b92f1904d6cc31 0.9754 embedded JPEG 14bit (3:2); comparison Normal/crop-render; mean dL 7.1
|
||||
Sigma fp L 6949 coverage-6949.dng https://raw.pixls.us/getfile.php/6949/nice/Sigma%20-%20fp%20L%20-%2014bit%20%283:2%29.DNG 8e7229f28be30bfa45289940eac04194af2b3474f6db286e4fa4070c145a0a70 9536 6344 1 u16 6896f73ec6b49231 0.9998 embedded JPEG 14bit (3:2); comparison Normal/crop-render; mean dL 1.597
|
||||
|
@@ -83,7 +83,11 @@ def classify(maker, camera, ext_field):
|
||||
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"):
|
||||
if e == "MEF":
|
||||
return "unverified", "MEF", "MEF decoder (uncompressed 12-bit)"
|
||||
if e == "ERF":
|
||||
return "unverified", "ERF", "ERF decoder (12-bit 16-byte blocks)"
|
||||
if e in ("CRW", "3FR", "FFF", "IIQ", "MOS", "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"
|
||||
|
||||
|
||||
+311
-311
@@ -97,16 +97,16 @@ Apple iPad Pro 12.9-inch (2018 model) DNG 2018 unverified DNG decoder (uncompres
|
||||
Apple iPad Pro 13-inch M4 (2024 version) Wide Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPad mini (6th Generation) Rear Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone 6s DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone 6s Plus DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone 6s Plus DNG 2015 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Apple iPhone 7 DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone 7 Plus DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone 7 Plus DNG 2015 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Apple iPhone 8 DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone 8 Plus DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone SE (2020 version) DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone SE DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone X DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone XR DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone XS DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone XS DNG 2018 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Apple iPhone XS Max DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPad Air (5th generation) Rear Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Apple iPhone SE (3rd generation) Front Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -116,117 +116,117 @@ Apple iPad mini (A17 Pro) Rear Camera DNG 2024 unverified DNG decoder (uncompres
|
||||
Canon EOS-1D TIF 2003 unsupported TIF is not imported
|
||||
Canon EOS-1D C CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D Mark II CR2 2003 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D Mark II N CR2 2005 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D Mark III CR2 2007 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D Mark IV CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D Mark II N CR2 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1D Mark III CR2 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1D Mark IV CR2 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1Ds TIF 2003 unsupported TIF is not imported
|
||||
Canon EOS-1Ds Mark II CR2 2005 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1Ds Mark III CR2 2007 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D X CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D X Mark II CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D X Mark III CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS 5D CR2 2005 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-1D X Mark II CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1D X Mark III CR3 2019 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS 5D CR2 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 5D Mark II CR2 2008 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS-5D Mark III CR2 2012 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS-5D Mark IV (** see note) CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 5DS CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS-5D Mark IV (** see note) CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 5DS CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 5DS R CR2 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 6D CR2 2012 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 6D Mark II CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 6D Mark II CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 7D CR2 2008 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 7D Mark II CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 7D Mark II CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 10D CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon EOS 20D CR2 2003 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 20D CR2 2003 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 20Da CR2 2005 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 30D CR2 2005 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 30D CR2 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 40D CR2 2007 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 50D CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 60D CR2 2010 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 50D CR2 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 60D CR2 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 60Da CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 70D CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 77D (EOS 9000D) CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 70D CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 77D (EOS 9000D) CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 80D CR2 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 90D CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS 200D (EOS Kiss X9, EOS Rebel SL2) CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 250D (EOS Rebel SL3, EOS 200D II, EOS Kiss X10) CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS 90D CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS 200D (EOS Kiss X9, EOS Rebel SL2) CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 250D (EOS Rebel SL3, EOS 200D II, EOS Kiss X10) CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS D30 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon EOS D60 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon EOS 300D (EOS Digital Rebel, EOS Kiss Digital) CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon EOS 100D (EOS Digital Rebel SL1, EOS Kiss X7) CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 500D (EOS Digital Rebel T1i, EOS Kiss X3 Digital) CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 100D (EOS Digital Rebel SL1, EOS Kiss X7) CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 500D (EOS Digital Rebel T1i, EOS Kiss X3 Digital) CR2 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 550D (EOS Digital Rebel T2i, EOS Kiss X4 Digital) CR2 2010 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 1100D (EOS Digital Rebel T3, EOS Kiss X50 Digital) CR2 2010 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 600D (EOS Digital Rebel T3i, EOS Kiss X5 Digital) CR2 2010 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 650D (EOS Digital Rebel T4i, EOS Kiss X4i) CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 700D (EOS Digital Rebel T5i, EOS Kiss X7i) CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 1200D (EOS Digital Rebel T5, EOS Kiss X70) CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 1300D (EOS Digital Rebel T6, EOS Kiss X80) CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 1500D (EOS Rebel T7, EOS Kiss X90, EOS 2000D) CR2 2017 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 3000D (EOS Rebel T100, EOS 4000D) CR2 2017 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 750D (EOS Digital Rebel T6i, EOS Kiss X8i) CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 760D (EOS Digital Rebel T6s, EOS Kiss 8000D) CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 800D (EOS Digital Rebel T7i, EOS Kiss X9i) CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 850D (EOS Kiss X10i, EOS Rebel T8i) CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS 1000D (EOS Digital Rebel XS, EOS Kiss F) CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 450D (EOS Digital Rebel XSi, EOS Kiss Digital X2) CR2 2007 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 350D (EOS Digital Rebel XT, EOS Kiss Digital N) CR2 2005 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 400D (EOS Digital Rebel XTi, EOS Kiss Digital X) CR2 2005 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS 1100D (EOS Digital Rebel T3, EOS Kiss X50 Digital) CR2 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 600D (EOS Digital Rebel T3i, EOS Kiss X5 Digital) CR2 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 650D (EOS Digital Rebel T4i, EOS Kiss X4i) CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 700D (EOS Digital Rebel T5i, EOS Kiss X7i) CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1200D (EOS Digital Rebel T5, EOS Kiss X70) CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1300D (EOS Digital Rebel T6, EOS Kiss X80) CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1500D (EOS Rebel T7, EOS Kiss X90, EOS 2000D) CR2 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 3000D (EOS Rebel T100, EOS 4000D) CR2 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 750D (EOS Digital Rebel T6i, EOS Kiss X8i) CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 760D (EOS Digital Rebel T6s, EOS Kiss 8000D) CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 800D (EOS Digital Rebel T7i, EOS Kiss X9i) CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 850D (EOS Kiss X10i, EOS Rebel T8i) CR3 2019 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS 1000D (EOS Digital Rebel XS, EOS Kiss F) CR2 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 450D (EOS Digital Rebel XSi, EOS Kiss Digital X2) CR2 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 350D (EOS Digital Rebel XT, EOS Kiss Digital N) CR2 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 400D (EOS Digital Rebel XTi, EOS Kiss Digital X) CR2 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS C50 CR3 2025 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS M CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS M2 CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS M200 CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS M3 CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS M5 CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS M50 Mark II CR3 2020 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS M6 CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS M6 Mark II CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS M10 CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS M CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M2 CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M200 CR3 2019 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS M3 CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M5 CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M50 Mark II CR3 2020 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS M6 CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M6 Mark II CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS M10 CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M50 (EOS Kiss M) CR3 2017 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||
Canon EOS M100 CR2 2017 unverified CR2 lossless JPEG decoder
|
||||
Canon EOS R (** see note) CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS M100 CR2 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS R (** see note) CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R1 CR3 2023 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R3 CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R5 CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R3 CR3 2021 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R5 CR3 2019 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R5 C CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R5 Mark II CR3 2023 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hashes, docs/cr3.md); bulk: QP maps of 33,665 C-RAW files
|
||||
Canon EOS R6 CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R6 CR3 2019 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R6 V CR3 2025 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R6 Mark II CR3 2022 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R6 Mark III CR3 2025 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R7 CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R6 Mark II CR3 2022 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md; C-RAW with adaptive QP above 168 still opens as the preview)
|
||||
Canon EOS R6 Mark III CR3 2025 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R7 CR3 2021 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md; lossless only, C-RAW unverified)
|
||||
Canon EOS R8 Mark II CR3 2025 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R10 CR3 2021 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R10 CR3 2021 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS Ra CR3 2019 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS RP CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS RP CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R8 CR3 2022 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||
Canon EOS R50 CR3 2022 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R50 V CR3 2024 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon EOS R50 CR3 2022 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R50 V CR3 2024 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R100 CR3 2022 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||
Canon PowerShot 600 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot A5 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot A50 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot G1 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot G1 X CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G1 X Mark II CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G1 X Mark III CR2 2017 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G1 X CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G1 X Mark II CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G1 X Mark III CR2 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G2 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot G3 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot G3 X CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G3 X CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G5 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot G5 X CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G5 X Mark II CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon PowerShot G5 X CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G5 X Mark II CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon PowerShot G6 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot G7 X CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G7 X Mark II CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G7 X Mark III CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon PowerShot G9 CR2 2007 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G9X CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G9 X Mark II CR2 2015 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G7 X CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G7 X Mark II CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G7 X Mark III CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon PowerShot G9 CR2 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G9X CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G9 X Mark II CR2 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G10 CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G11 CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G12 CR2 2010 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G15 CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G16 CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot G11 CR2 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G12 CR2 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G15 CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G16 CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot Pro 1 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot Pro70 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot Pro90 IS CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
@@ -236,17 +236,17 @@ Canon PowerShot S45 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot S50 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot S60 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot S90 CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot S95 CR2 2010 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot S95 CR2 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S70 CRW 2003 preview CRW is opened from its embedded JPEG only
|
||||
Canon PowerShot S100 CR2 2010 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot S100V CR2 2010 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot S110 CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot S120 CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot S100 CR2 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S100V CR2 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S110 CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S120 CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot SX1 IS CR2 2008 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot SX50 CR2 2012 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot SX60 HS CR2 2013 unverified CR2 lossless JPEG decoder
|
||||
Canon PowerShot SX70 HS CR3 2018 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon PowerShot V1 CR3 2024 unverified CRX decoder: lossless and C-RAW 0x100 / 0x200 single-tile; other variants fall back to the preview
|
||||
Canon PowerShot SX50 CR2 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot SX60 HS CR2 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot SX70 HS CR3 2018 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon PowerShot V1 CR3 2024 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Casio EXILIM EX-10 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Casio EXILIM EX-100 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Casio EXILIM EX-100F DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -274,9 +274,9 @@ Casio EXILIM EX-ZR4100 DNG 2017 unverified DNG decoder (uncompressed, LJ92, loss
|
||||
Casio EXILIM EX-ZR5000 DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Casio EXILIM EX-ZR5100 DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Contax N Digital RAW 2003 preview RAW is opened from its embedded JPEG only
|
||||
DJI DJI Mavic 2 Pro (Hasselblad L1D-20c) DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 2 Pro (Hasselblad L1D-20c) DNG 2020 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI AIR 2S DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mini 2 DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mini 2 DNG 2020 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI Air 3 Wide Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Air 3 Telephoto Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mini 3 Pro DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -287,48 +287,48 @@ DJI DJI Mavic 3 Cine (Hasselblad L2D-20c) DNG 2023 unverified DNG decoder (uncom
|
||||
DJI DJI Mavic 3 Pro Super Telephoto Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 3 Pro Telephoto Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 3 Pro (Hasselblad L2D-20c) DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 3 (Hasselblad L2D-20c) DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 3 (Hasselblad L2D-20c) DNG 2023 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI Osmo Pocket 3 D DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Air 3S Telephoto Camera DNG 2024 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Air 3S Wide Camera DNG 2024 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Osmo Action 5 Pro DNG 2024 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 4 Pro (DJI FC9284) DNG 2025 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 4 Pro (DJI FC9287) DNG 2025 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DJI DJI Mavic 4 Pro (DJI FC9287) DNG 2025 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI Mavic 4 Pro (Hasselblad L3D-100c) DNG 2025 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
DxO DxO ONE DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Epson R-D1 ERF 2003 preview ERF is opened from its embedded JPEG only
|
||||
Epson R-D1s ERF 2005 preview ERF is opened from its embedded JPEG only
|
||||
Epson R-D1x ERF 2008 preview ERF is opened from its embedded JPEG only
|
||||
Fujifilm GFX 50R RAF 2017 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Epson R-D1 ERF 2003 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Epson R-D1s ERF 2005 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Epson R-D1x ERF 2008 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm GFX 50R RAF 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 50S RAF 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm GFX 50S II RAF 2020 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm GFX 50S II RAF 2020 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 100 RAF 2018 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm GFX 100 II RAF 2022 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm GFX 100 II RAF 2022 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 100 II IR RAF 2024 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm GFX 100 IR RAF 2020 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm GFX 100S RAF 2020 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm GFX 100S II RAF 2023 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm GFX 100S II RAF 2023 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 100RF (Final Support) RAF 2024 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm FinePix E900 RAF 2005 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F505 EXR RAF 2012 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F550 EXR RAF 2010 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F550 EXR RAF 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix F600 EXR RAF 2010 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F605 EXR RAF 2012 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F700 RAF 2003 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F770 EXR RAF 2012 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F770 EXR RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix F775 EXR RAF 2012 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F800 EXR RAF 2012 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix F900 EXR RAF 2012 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix HS10 RAF 2010 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix HS20 EXR RAF 2010 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix HS22 EXR RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix HS30 EXR RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix HS33 EXR RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix HS30 EXR RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix HS33 EXR RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix HS35 EXR RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix HS50 EXR RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix HS50 EXR RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix IS-1 RAF 2007 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix IS Pro RAF 2008 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix S1 RAF 2013 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix S1 RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix S100fs RAF 2007 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix S2 Pro RAF 2003 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix S20 Pro RAF 2003 preview pre-X FinePix RAF without a raw IFD
|
||||
@@ -342,59 +342,59 @@ Fujifilm FinePix S6000fd (FinePix S6500fd) RAF 2005 preview pre-X FinePix RAF wi
|
||||
Fujifilm FinePix S7000 Z RAF 2003 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix S9000 (FinePix S9500) RAF 2005 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix S9100 (FinePix S9600) RAF 2005 preview pre-X FinePix RAF without a raw IFD
|
||||
Fujifilm FinePix SL1000 RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix X10 RAF 2010 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix X100 RAF 2010 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix X-M1 RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix X-S1 RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X100F RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X100S RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X100T RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X100V** RAF 2019 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X100VI RAF 2023 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X20 RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X30 RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X70 RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-A1 RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm FinePix SL1000 RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X10 RAF 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X100 RAF 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X-M1 RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X-S1 RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100F RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100S RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100T RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100V** RAF 2019 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100VI RAF 2023 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X20 RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X30 RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X70 RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A1 RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A2 RAF 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-A3 RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-A3 RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A5 RAF 2017 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-A7 RAF 2018 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-A10 RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-A7 RAF 2018 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A10 RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A20 RAF 2017 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-E1 RAF 2012 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-E2 RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-E2S RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-E3 RAF 2017 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-E4 RAF 2020 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-E2 RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E2S RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E3 RAF 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E4 RAF 2020 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E5 RAF 2024 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-H1 RAF 2017 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-H1 RAF 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-H2 IR RAF 2024 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-H2S RAF 2021 verified docs/raf-compression.md (supplied files, exact sensor arrays)
|
||||
Fujifilm X-M5 RAF 2024 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-Pro1 RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-Pro2 RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-Pro3** RAF 2019 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-S10 RAF 2020 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-S20 RAF 2022 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T1 RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-Pro1 RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-Pro2 RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-Pro3** RAF 2019 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-S10 RAF 2020 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-S20 RAF 2022 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T1 RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T1 IR RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T2 RAF 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T3 RAF 2018 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T3 RAF 2018 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T4** RAF 2019 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T5 RAF 2022 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T10 RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T10 RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T20 RAF 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T30 RAF 2018 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T30 II RAF 2021 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T30 III RAF 2022 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T30 RAF 2018 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T30 II RAF 2021 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T30 III RAF 2022 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T50 RAF 2023 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Fujifilm X-T100 RAF 2017 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T200 RAF 2019 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm XF1 RAF 2012 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm XF10 RAF 2017 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm XQ1 RAF 2013 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm XQ2 RAF 2015 unverified RAF decoder (uncompressed, lossless / lossy compressed, Bayer and X-Trans)
|
||||
Fujifilm X-T100 RAF 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T200 RAF 2019 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XF1 RAF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XF10 RAF 2017 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XQ1 RAF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XQ2 RAF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-H2 RAF 2021 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Google Pixel DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel XL DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -407,7 +407,7 @@ Google Pixel 3 XL DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, De
|
||||
Google Pixel 3 XL Front Standard Camera DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 3 XL Front Wide Camera DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 4 DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 4 XL DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 4 XL DNG 2019 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 5 Front Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 5 Rear Main Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 5 Rear Ultra Wide Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -415,7 +415,7 @@ Google Pixel 6 Front Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92,
|
||||
Google Pixel 6 Rear Main Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 6 Rear Ultrawide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 6 Pro Front Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 6 Pro Rear Main Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 6 Pro Rear Main Camera DNG 2021 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 6 Pro Rear Telephoto Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 6 Pro Rear Ultrawide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 7 Front Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -426,7 +426,7 @@ Google Pixel 7 Pro Telephoto Camera DNG 2022 unverified DNG decoder (uncompresse
|
||||
Google Pixel 7 Pro Ultrawide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 7 Pro Wide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 4a Front Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 4a Rear Wide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 4a Rear Wide Camera DNG 2022 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 5a Front Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 5a Rear Main Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 5a Rear Ultra Wide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -442,7 +442,7 @@ Google Pixel 8 Wide Camera* DNG 2023 unverified DNG decoder (uncompressed, LJ92,
|
||||
Google Pixel 8 Pro Front Camera* DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 8 Pro Telephoto Camera* DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 8 Pro Ultrawide Camera* DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 8 Pro Wide Camera* DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 8 Pro Wide Camera* DNG 2023 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 8a Front Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 8a Ultrawide Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Google Pixel 8a Wide Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -502,7 +502,7 @@ Hasselblad CF-39MS 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad CFH-22 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad CFH-39 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad CFV 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad CFV-50c 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad CFV-50c 3FR 2008 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad H2D DNG 2003 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Hasselblad H2D-22 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H2D-39 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
@@ -515,18 +515,18 @@ Hasselblad H3DII-39MS 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H3DII-50 3FR 2008 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H4D-40 3FR 2010 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H4D-60 3FR 2010 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H5D-40 3FR 2012 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H5D-40 3FR 2012 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad H5D-50 3FR 2012 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H5D-50c 3FR 2013 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H5D-50c 3FR 2013 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad H5D-60 3FR 2013 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad H6D-100c 3FR 2015 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad HV ARW 2013 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Hasselblad Lunar 3FR 2012 verified issue #1275: raw.pixls.us 4051 (a Sony NEX-7 ARW under Make HASSELBLAD) decodes from sensor data; black 512 and SR2SubIFD WB as on a NEX-7
|
||||
Hasselblad Stellar II 3FR 2015 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad X1D 3FR 2015 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad X1D 3FR 2015 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad X2D II 100C (**) 3FR 2024 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad X1D II 50C 3FR 2018 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad X2D 100C 3FR 2021 preview 3FR is opened from its embedded JPEG only
|
||||
Hasselblad X1D II 50C 3FR 2018 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad X2D 100C 3FR 2021 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Huawei Honor 20 Pro Rear Main Camera DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Huawei Honor 20 Pro Rear Telephoto Camera DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Huawei Honor 20 Pro Rear Wide Camera DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -586,8 +586,8 @@ Leaf Credo 50 IIQ 2013 preview IIQ is opened from its embedded JPEG only
|
||||
Leaf Credo 60 IIQ 2012 preview IIQ is opened from its embedded JPEG only
|
||||
Leaf Credo 80 IIQ 2012 preview IIQ is opened from its embedded JPEG only
|
||||
Leica C (Typ 112) RWL 2013 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica CL DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica C-Lux DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica CL DNG 2017 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica C-Lux DNG 2017 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica D-Lux 2 RAW 2005 unverified Panasonic decoder, every raw format
|
||||
Leica D-Lux 3 RAW 2005 verified PR #215: raw.pixls.us bulk check of every RW2 / RWL / RAW body
|
||||
Leica D-Lux 4 RWL 2008 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
@@ -601,26 +601,26 @@ Leica Digilux 2 RAW 2003 verified PR #215: raw.pixls.us bulk check of every RW2
|
||||
Leica Digilux 3 RAW 2005 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica Digital-Modul-R DNG 2003 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica Leitz Phone 3 DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M8 DNG 2003 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M9 DNG 2008 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M10 DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M8 DNG 2003 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica M9 DNG 2008 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica M10 DNG 2015 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica M10-D DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M10-P DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M10-R DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M10-R DNG 2019 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica M11-D DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M (Typ 262) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M-D (Typ 262) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M-E DNG 2012 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M-EV1 DNG 2024 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M-P DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M Monochrom DNG 2012 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M Monochrom (Typ 246) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M Monochrom DNG 2012 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica M Monochrom (Typ 246) DNG 2015 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica M10 Monochrom DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M11 DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M11 MONOCHROM DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica M11-P DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica Q (Typ 116) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica Q2 DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica Q (Typ 116) DNG 2015 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica Q2 DNG 2018 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica Q2 Monochrom DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica Q3 DNG 2022 verified recorded check 2026-10-11: 38 private Q3 DNGs (landscape and portrait) decoded from sensor data and developed at full size without error, mean CIE76 dE to the camera JPEG 6.3-13.9 at 400 px (not committed; docs/raw-parity.md)
|
||||
Leica Q3 43 DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -628,8 +628,8 @@ Leica Q3 Monochrom DNG 2025 unverified DNG decoder (uncompressed, LJ92, lossy, D
|
||||
Leica S2 DNG 2010 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica S (Typ 007) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica S3 DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica SL (Typ 601) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica SL2 DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica SL (Typ 601) DNG 2015 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica SL2 DNG 2019 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica SL2-S DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica SL3 DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica SL3-P DNG 2025 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -643,7 +643,7 @@ Leica V-LUX 3 RAW 2010 unverified Panasonic decoder, every raw format
|
||||
Leica V-LUX 4 RWL 2012 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica V-LUX 5 RWL 2018 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica V-LUX (Typ 114) RWL 2013 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Leica X2 RWL 2012 unverified Panasonic decoder, every raw format
|
||||
Leica X2 RWL 2012 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica X (Typ 113) DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Leica X-U (Typ 113) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
LG G7 ThinQ DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -673,107 +673,107 @@ Mamiya Mamiya M18 TIF 2008 unsupported TIF is not imported
|
||||
Mamiya Mamiya M22 TIF 2008 unsupported TIF is not imported
|
||||
Mamiya Mamiya M31 TIF 2008 unsupported TIF is not imported
|
||||
Mamiya Mamiya DM40 MOS 2010 preview MOS is opened from its embedded JPEG only
|
||||
Mamiya ZD MEF 2005 unsupported MEF is not imported
|
||||
Mamiya ZD MEF 2005 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Motorola Moto G Power (2021) Front Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Motorola Moto G Power (2021) Rear Macro Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Motorola Moto G Power (2021) Rear Wide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Nikon 1 J1 NEF 2010 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 J2 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 J3 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 J4 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 J5 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 S1 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 J1 NEF 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J2 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J3 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J4 NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J5 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 S1 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 S2 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 V1 NEF 2010 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 V2 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 V3 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon 1 V1 NEF 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 V2 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 V3 NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX 5000 NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX 5400 NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX 5700 NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX 8400 NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX 5700 NEF 2003 unsupported bulk: raw.pixls.us CC0 file decodes wrongly (two stacked half-height fields, CMYG mosaic read as RGB; green vs camera JPEG r 0.12-0.36)
|
||||
Nikon COOLPIX 8400 NEF 2005 unsupported bulk: raw.pixls.us CC0 file decodes wrongly (two stacked half-height fields, CMYG mosaic read as RGB; green vs camera JPEG r 0.12-0.36)
|
||||
Nikon COOLPIX 8700 NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX 8800 NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX A NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX A1000 NRW 2018 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX 8800 NEF 2005 unsupported bulk: raw.pixls.us CC0 file decodes wrongly (two stacked half-height fields, CMYG mosaic read as RGB; green vs camera JPEG r 0.12-0.36)
|
||||
Nikon COOLPIX A NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX A1000 NRW 2018 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX B700 NRW 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon COOLPIX P330 NRW 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P340 NRW 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P1000 NRW 2018 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P1100 NRW 2024 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P1000 NRW 2018 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX P1100 NRW 2024 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX P6000 NRW 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P7000 NRW 2010 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P7100 NRW 2010 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P7700 NRW 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P7800 NRW 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P950 NEF 2019 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon COOLPIX P950 NEF 2019 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D1 NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D1H NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D1H NEF 2003 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D1X NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D2H NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D2Hs NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D2X NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D2Xs NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3 NEF 2007 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3s NEF 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3X NEF 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D4 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D4S NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D5 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D40 NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D40x NEF 2007 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D50 NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D60 NEF 2007 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D6 NEF 2019 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D70 NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D70S NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D80 NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D90 NEF 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D2H NEF 2003 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D2Hs NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D2X NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D2Xs NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3 NEF 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3s NEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3X NEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D4 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D4S NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D40 NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D40x NEF 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D50 NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D60 NEF 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D6 NEF 2019 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); checked compressed NEF only; uncompressed remains preview-only (#671)
|
||||
Nikon D70 NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D70S NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D80 NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D90 NEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D100 NEF 2003 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D200 NEF 2005 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D300 NEF 2007 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D300s NEF 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D500 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D600 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D610 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D700 NEF 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D750 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D780 NEF 2019 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D800 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D800E NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D810 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D200 NEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D300 NEF 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D300s NEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D500 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D600 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D610 NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D700 NEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D750 NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D780 NEF 2019 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D800 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D800E NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D810 NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D810A NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D850 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3000 NEF 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3100 NEF 2010 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3200 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3300 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3400 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D3500 NEF 2018 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D5000 NEF 2008 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D850 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3000 NEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3100 NEF 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3200 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3300 NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3400 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3500 NEF 2018 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5000 NEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5100 NEF 2010 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon D5200 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D5300 NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D5500 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D5600 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D5200 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5300 NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5500 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5600 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D7000 NEF 2010 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon D7100 NEF 2012 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D7200 NEF 2015 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon D7100 NEF 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D7200 NEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D7500 NEF 2015 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon Df NEF 2013 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 30 NEF 2021 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 50 NEF 2019 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 50 II NEF 2024 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 5 NEF 2019 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Df NEF 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 30 NEF 2021 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 50 NEF 2019 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 50 II NEF 2024 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 5 NEF 2019 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 5 2 NEF 2024 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 5 2C NEF 2025 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 6 NEF 2018 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 6 II NEF 2020 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 6 NEF 2018 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); checked compressed NEF only; uncompressed remains preview-only (#671)
|
||||
Nikon Z 6 II NEF 2020 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 6 III NEF 2023 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 7 NEF 2018 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 7 II NEF 2020 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 8 NEF 2022 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 9 (*See note) NEF 2021 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z fc NEF 2020 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nikon Z 7 NEF 2018 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); checked compressed NEF only; uncompressed remains preview-only (#671)
|
||||
Nikon Z 7 II NEF 2020 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 8 NEF 2022 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); HE / HE* remain preview-only
|
||||
Nikon Z 9 (*See note) NEF 2021 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z fc NEF 2020 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z f NEF 2022 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Nikon ZR NEF 2024 unverified NEF decoder (uncompressed, lossless, lossy, lossy after split); HE / HE* setting preview-only
|
||||
Nokia Lumia 1020 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -788,13 +788,13 @@ OM Digital Solutions OM-5 Mark II ORF 2024 preview compressed ORF is not decoded
|
||||
OM Digital Solutions OM-3 Astro ORF 2025 preview compressed ORF is not decoded
|
||||
Olympus AIR A01 ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus Camedia C-5050 Zoom ORF 2003 unverified uncompressed / packed ORF
|
||||
Olympus Camedia C-5060 Zoom ORF 2003 unverified uncompressed / packed ORF
|
||||
Olympus Camedia C-7070 Wide Zoom ORF 2005 unverified uncompressed / packed ORF
|
||||
Olympus Camedia C-5060 Zoom ORF 2003 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus Camedia C-7070 Wide Zoom ORF 2005 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus Camedia C-8080 Wide Zoom ORF 2003 unverified uncompressed / packed ORF
|
||||
Olympus E-1 ORF 2003 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Olympus E-3 ORF 2007 preview compressed ORF is not decoded
|
||||
Olympus E-5 ORF 2010 preview compressed ORF is not decoded
|
||||
Olympus E-10 ORF 2003 unverified uncompressed / packed ORF
|
||||
Olympus E-10 ORF 2003 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash)
|
||||
Olympus E-20 ORF 2003 unverified uncompressed / packed ORF
|
||||
Olympus E-30 ORF 2008 preview compressed ORF is not decoded
|
||||
Olympus E-420 ORF 2008 preview compressed ORF is not decoded
|
||||
@@ -802,18 +802,18 @@ Olympus E-450 ORF 2008 preview compressed ORF is not decoded
|
||||
Olympus E-520 ORF 2008 preview compressed ORF is not decoded
|
||||
Olympus E-600 ORF 2010 preview compressed ORF is not decoded
|
||||
Olympus E-620 ORF 2008 preview compressed ORF is not decoded
|
||||
Olympus EVOLT E-300 ORF 2005 unverified uncompressed / packed ORF
|
||||
Olympus EVOLT E-330 ORF 2005 unverified uncompressed / packed ORF
|
||||
Olympus EVOLT E-300 ORF 2005 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus EVOLT E-330 ORF 2005 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus EVOLT E-400 ORF 2005 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Olympus EVOLT E-410 ORF 2007 preview compressed ORF is not decoded
|
||||
Olympus EVOLT E-500 ORF 2005 unverified uncompressed / packed ORF
|
||||
Olympus EVOLT E-500 ORF 2005 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus EVOLT E-510 ORF 2007 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M1 ORF 2013 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M1X ORF 2018 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M1 Mark II ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M1 Mark III ORF 2019 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M5 ORF 2012 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M5 Mark II ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M5 Mark II ORF 2015 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus OM-D E-M5 Mark III ORF 2019 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M10 ORF 2013 preview compressed ORF is not decoded
|
||||
Olympus OM-D E-M10 Mark II ORF 2015 preview compressed ORF is not decoded
|
||||
@@ -837,25 +837,25 @@ Olympus PEN E-PL8 ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus PEN E-PL9 ORF 2017 preview compressed ORF is not decoded
|
||||
Olympus PEN E-PM1 ORF 2010 preview compressed ORF is not decoded
|
||||
Olympus PEN E-PM2 ORF 2012 preview compressed ORF is not decoded
|
||||
Olympus PEN-F ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus PEN-F ORF 2015 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-310 ORF 2005 preview compressed ORF is not decoded
|
||||
Olympus SP-320 ORF 2005 preview compressed ORF is not decoded
|
||||
Olympus SP-350 ORF 2005 preview compressed ORF is not decoded
|
||||
Olympus SP-500 UZ ORF 2005 preview compressed ORF is not decoded
|
||||
Olympus SP-510 UZ ORF 2005 preview compressed ORF is not decoded
|
||||
Olympus SP-550 UZ ORF 2007 preview compressed ORF is not decoded
|
||||
Olympus SP-510 UZ ORF 2005 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-550 UZ ORF 2007 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-560 UZ ORF 2007 preview compressed ORF is not decoded
|
||||
Olympus SP-565 UZ ORF 2008 preview compressed ORF is not decoded
|
||||
Olympus SP-570 UZ ORF 2007 preview compressed ORF is not decoded
|
||||
Olympus SP-565 UZ ORF 2008 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-570 UZ ORF 2007 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus Stylus 1 ORF 2013 preview compressed ORF is not decoded
|
||||
Olympus Stylus 1s ORF 2013 preview compressed ORF is not decoded
|
||||
Olympus Stylus SH-2 ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus Stylus SH-2 ORF 2015 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus Stylus SH-3 ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus Stylus Tough TG-4 ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus Stylus Tough TG-5 ORF 2015 preview compressed ORF is not decoded
|
||||
Olympus Stylus Tough TG-6 ORF 2018 preview compressed ORF is not decoded
|
||||
Olympus Stylus XZ-2 iHS ORF 2012 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Olympus Stylus XZ-10 ORF 2012 preview compressed ORF is not decoded
|
||||
Olympus Stylus XZ-10 ORF 2012 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus XZ-1 ORF 2010 preview compressed ORF is not decoded
|
||||
OnePlus 7T Front Camera DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
OnePlus 7T Rear Main Camera DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -1007,46 +1007,46 @@ Panasonic LUMIX DC-S1M2ES (Final Support) RW2 2024 verified PR #215: 178 raw.pix
|
||||
Panasonic LUMIX DC-S1M2 RW2 2024 verified PR #215: 178 raw.pixls.us files from 118 Panasonic / Leica bodies, every RW2 format
|
||||
Panasonic LUMIX DC-ZS300 (DC-TZ300, DC-TX3) RW2 2025 unverified Panasonic decoder, every raw format
|
||||
Panasonic LUMIX DC-L10 RW2 2025 unverified Panasonic decoder, every raw format
|
||||
Parrot Anafi DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Parrot Anafi DNG 2017 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Parrot ANAFI Ai DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax 645D DNG 2010 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax 645Z DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax *ist D PEF 2003 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax *ist DL PEF 2005 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax 645D DNG 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax 645Z DNG 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax *ist D PEF 2003 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax *ist DL PEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax *ist DL2 PEF 2005 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax *ist DS PEF 2005 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax *ist DS PEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax *ist DS2 PEF 2005 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K-01 DNG 2012 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-1 DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-01 DNG 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-1 DNG 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-1 II (* see note) DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-3 DNG 2013 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Pentax K-3 II († see note) DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-5 DNG 2010 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-5 II DNG 2012 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-3 II († see note) DNG 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-5 DNG 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-5 II DNG 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-5 IIs DNG 2012 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Pentax K-7 PEF 2008 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K-3 Mark III DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-3 Mark III Monochrome DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-30 DNG 2012 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-50 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-70 PEF 2015 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K-500 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax KP DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-r PEF 2010 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K-S1 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-S2 DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K-x PEF 2008 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K-7 PEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-3 Mark III DNG 2020 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-3 Mark III Monochrome DNG 2022 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash)
|
||||
Pentax K-30 DNG 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-50 DNG 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-70 PEF 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-500 DNG 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax KP DNG 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-r PEF 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-S1 DNG 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-S2 DNG 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-x PEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K10D DNG 2005 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Pentax K20D DNG 2007 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K100D PEF 2005 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K100D Super PEF 2007 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K110D PEF 2005 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax K200D DNG 2007 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K2000 K-m PEF 2008 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax KF PEF 2022 unverified PEF decoder (uncompressed, Huffman, packed 12-bit)
|
||||
Pentax MX-1 DNG 2012 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax Q DNG 2010 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax Q7 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax K20D DNG 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K100D PEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K100D Super PEF 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K110D PEF 2005 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K200D DNG 2007 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K2000 K-m PEF 2008 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax KF PEF 2022 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax MX-1 DNG 2012 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax Q DNG 2010 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax Q7 DNG 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax Q10 DNG 2012 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pentax QS-1 DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Pixii PIXII Camera (A1571) DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -1078,10 +1078,10 @@ Phase One P 40+ IIQ 2010 preview IIQ is opened from its embedded JPEG only
|
||||
Phase One P 45 TIF 2007 unsupported TIF is not imported
|
||||
Phase One P 45+ TIF 2007 unsupported TIF is not imported
|
||||
Phase One P 65+ IIQ 2010 preview IIQ is opened from its embedded JPEG only
|
||||
Ricoh GR DNG 2013 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GR II DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GR DNG 2013 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Ricoh GR II DNG 2015 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Ricoh GR III DNG 2018 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Ricoh GR IIIx DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GR IIIx DNG 2021 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Ricoh GR III HDF DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GR IIIx HDF DNG 2023 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GR IV DNG 2024 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -1091,7 +1091,7 @@ Ricoh GR Digital II DNG 2003 unverified DNG decoder (uncompressed, LJ92, lossy,
|
||||
Ricoh GR Digital III DNG 2008 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GR Digital IV DNG 2010 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GX100 DNG 2003 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GX200 DNG 2003 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GX200 DNG 2003 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash)
|
||||
Ricoh GXR with GR LENS A12 28mm F2.5 DNG 2010 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GXR with GR LENS A12 50mm F2.5 MACRO DNG 2008 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Ricoh GXR with GR LENS A16 24-85 F3.5-5.5 DNG 2010 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -1105,14 +1105,14 @@ Samsung EK-KN120 SRW 2012 preview compressed SRW is not decoded
|
||||
Samsung EX2F SRW 2012 unverified uncompressed / packed SRW
|
||||
Samsung NX300 SRW 2012 preview compressed SRW is not decoded
|
||||
Samsung NX500 SRW 2015 preview compressed SRW is not decoded
|
||||
Samsung NX1000 SRW 2012 unverified uncompressed / packed SRW
|
||||
Samsung NX1100 SRW 2012 unverified uncompressed / packed SRW
|
||||
Samsung NX1000 SRW 2012 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Samsung NX1100 SRW 2012 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Samsung NX2000 SRW 2012 preview compressed SRW is not decoded
|
||||
Samsung NX3000 SRW 2013 preview compressed SRW is not decoded
|
||||
Samsung NX3300 SRW 2015 preview compressed SRW is not decoded
|
||||
Samsung NX U SRW 2012 unverified uncompressed / packed SRW
|
||||
Samsung Pro 815 DNG 2003 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung TL350 (WB2000) SRW 2010 unverified uncompressed / packed SRW
|
||||
Samsung TL350 (WB2000) SRW 2010 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Samsung TL500 (EX1) SRW 2010 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Samsung Galaxy Note 9 DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy Note 20 Rear Main Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -1127,16 +1127,16 @@ Samsung Galaxy S21 Rear Main Camera DNG 2020 unverified DNG decoder (uncompresse
|
||||
Samsung Galaxy S21 Rear Wide Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S21+ Rear Main Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S21+ Rear Wide Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S21 Ultra Rear Main Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S21 Ultra Rear Main Camera DNG 2020 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S21 Ultra Rear Wide Camera DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S21 Ultra Super Telephoto Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S21 Ultra Telephoto Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S6 DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S6 Edge DNG 2018 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S7 DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S7 Edge DNG 2015 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S8 DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S8+ DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S7 Edge DNG 2015 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S8 DNG 2017 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S8+ DNG 2017 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S9 DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S9+ DNG 2017 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy Z Fold3 Rear Main Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -1154,11 +1154,11 @@ Samsung Galaxy S22 Ultra Front Camera DNG 2021 unverified DNG decoder (uncompres
|
||||
Samsung Galaxy S22 Ultra Rear Super Telephoto Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S22 Ultra Rear Telephoto Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S22 Ultra Rear Ultrawide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S22 Ultra Rear Wide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S22 Ultra Rear Wide Camera DNG 2021 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S23 Front Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S23 Rear Telephoto Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S23 Rear Ultrawide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S23 Rear Wide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S23 Rear Wide Camera DNG 2022 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S23+ Front Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S23+ Rear Telephoto Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Samsung Galaxy S23+ Rear Ultrawide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
@@ -1230,8 +1230,8 @@ Sigma BF DNG 2024 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JP
|
||||
Sigma DP1 X3F 2007 preview X3F is opened from its embedded JPEG only
|
||||
Sigma DP1s X3F 2008 preview X3F is opened from its embedded JPEG only
|
||||
Sigma DP2 X3F 2008 preview X3F is opened from its embedded JPEG only
|
||||
Sigma fp DNG 2019 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Sigma fp L DNG 2020 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Sigma fp DNG 2019 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Sigma fp L DNG 2020 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Sigma SD9 X3F 2003 preview X3F is opened from its embedded JPEG only
|
||||
Sigma SD10 X3F 2003 preview X3F is opened from its embedded JPEG only
|
||||
Sigma SD14 X3F 2007 preview X3F is opened from its embedded JPEG only
|
||||
@@ -1243,12 +1243,12 @@ Sony Xperia 1 V Front Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92
|
||||
Sony Xperia 1 V Ultrawide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Sony Xperia 1 V Wide Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Sony Xperia 1 V Zoom Camera DNG 2022 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Sony A1 II (ILCE-1M2) (** see note) ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony A1 II (ILCE-1M2) (** see note) ARW 2024 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony A7 (ILCE-7) ARW 2013 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) ARW 2013 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies
|
||||
Sony A7 III (ILCE-7M3) ARW 2017 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) ARW 2021 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7 V (ILCE-7M5) (** see note) ARW 2025 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony A7 V (ILCE-7M5) (** see note) ARW 2025 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony A7C (ILCE-7C) ARW 2020 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) ARW 2023 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony A7CR (ILCE-7CR) ARW 2023 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
@@ -1310,7 +1310,7 @@ Sony DSC-F828 SRF 2003 unsupported issue #702 (SRF refused); SRF not in the impo
|
||||
Sony DSC-HX95 ARW 2018 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony DSC-HX99 ARW 2018 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony DSC-V3 SRF 2005 unsupported SRF not in the import list
|
||||
Sony DSC-RX100M7A ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony DSC-RX100M7A ARW 2024 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony FX3 (ILME-FX3) ARW 2020 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony FX30 (ILME-FX30) ARW 2022 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony NEX-3 ARW 2010 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
@@ -1375,16 +1375,16 @@ Sony Xperia 5 V Wide Camera DNG 2023 unverified DNG decoder (uncompressed, LJ92,
|
||||
Sony Xperia Pro-I Rear Wide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Sony ZV-E10 ARW 2021 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony ZV-E1 ARW 2022 verified issue #535: raw.pixls.us bulk check of all 100 Sony bodies (decodes; BL/WL/crop/WB vs ExifTool)
|
||||
Sony ZV-E10M2 ARW unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony ZV-1M2 ARW 2022 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony ZV-E10M2 ARW verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony ZV-1M2 ARW 2022 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony ZV-1A ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony ILX-LR1 ARW 2023 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony ILCE - 1M2 (Final Support) ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony ILCE - 6100A ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony ILCE - 6400A ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony FX2 (ILMEFX2) (** see note) ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony ILCE - 6400A ARW 2024 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony FX2 (ILMEFX2) (** see note) ARW 2024 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony FX3A (ILMEFX3A) ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony RX1R III (DSC-RX1RM3) ARW 2024 unverified ARW decoder (uncompressed, cRAW, packed 12-bit, lossless, downsized YCbCr)
|
||||
Sony RX1R III (DSC-RX1RM3) ARW 2024 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Xiaomi Mi 11 Lite Front Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Xiaomi Mi 11 Lite Rear Ultrawide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
Xiaomi Mi 11 Lite Rear Wide Camera DNG 2021 unverified DNG decoder (uncompressed, LJ92, lossy, Deflate, JPEG XL, LinearRaw)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 86 and column 19.
|
+315
-2
@@ -13,7 +13,90 @@ Canon EOS M50 (EOS Kiss M) verified corpus: crates/raw/tests/cr3_corpus.rs (exac
|
||||
Canon EOS R100 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||
Canon EOS R5 Mark II verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hashes, docs/cr3.md); bulk: QP maps of 33,665 C-RAW files
|
||||
Canon EOS R8 verified corpus: crates/raw/tests/cr3_corpus.rs (exact sensor hashes, docs/cr3.md)
|
||||
Canon EOS-1D X Mark III verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS 90D verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS 250D (EOS Rebel SL3, EOS 200D II, EOS Kiss X10) verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS 850D (EOS Kiss X10i, EOS Rebel T8i) verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS M200 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS M50 Mark II verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS M6 Mark II verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R (** see note) verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R3 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R5 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R6 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R6 Mark II verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md; C-RAW with adaptive QP above 168 still opens as the preview)
|
||||
Canon EOS R6 Mark III verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R7 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md; lossless only, C-RAW unverified)
|
||||
Canon EOS R10 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS RP verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R50 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS R50 V verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon PowerShot G5 X Mark II verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon PowerShot G7 X Mark III verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon PowerShot SX70 HS verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon PowerShot V1 verified corpus: crates/raw/tests/cr3_corpus.rs (pinned sensor hash, camera-JPEG check, docs/cr3.md)
|
||||
Canon EOS-5D Mark III verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Canon EOS 70D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 800D (EOS Digital Rebel T7i, EOS Kiss X9i) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G9X verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 3000D (EOS Rebel T100, EOS 4000D) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1000D (EOS Digital Rebel XS, EOS Kiss F) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G1 X Mark II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 500D (EOS Digital Rebel T1i, EOS Kiss X3 Digital) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 400D (EOS Digital Rebel XTi, EOS Kiss Digital X) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S110 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1300D (EOS Digital Rebel T6, EOS Kiss X80) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 600D (EOS Digital Rebel T3i, EOS Kiss X5 Digital) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G1 X verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G16 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G3 X verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1D X Mark II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 750D (EOS Digital Rebel T6i, EOS Kiss X8i) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 5DS verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S100V verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 350D (EOS Digital Rebel XT, EOS Kiss Digital N) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1200D (EOS Digital Rebel T5, EOS Kiss X70) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G11 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 100D (EOS Digital Rebel SL1, EOS Kiss X7) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G15 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1D Mark IV verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M5 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S100 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 650D (EOS Digital Rebel T4i, EOS Kiss X4i) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot SX50 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M2 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M3 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G12 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 6D Mark II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M10 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 700D (EOS Digital Rebel T5i, EOS Kiss X7i) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1100D (EOS Digital Rebel T3, EOS Kiss X50 Digital) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 77D (EOS 9000D) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 1500D (EOS Rebel T7, EOS Kiss X90, EOS 2000D) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-5D Mark IV (** see note) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1D Mark III verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 60D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS-1D Mark II N verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M100 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G5 X verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G9 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 5D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS M6 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G7 X Mark II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 7D Mark II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S120 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot S95 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G1 X Mark III verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 50D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 20D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G7 X verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 450D (EOS Digital Rebel XSi, EOS Kiss Digital X2) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot SX60 HS verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 200D (EOS Kiss X9, EOS Rebel SL2) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon PowerShot G9 X Mark II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 760D (EOS Digital Rebel T6s, EOS Kiss 8000D) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Canon EOS 30D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
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)
|
||||
@@ -46,11 +129,144 @@ Leica V-LUX (Typ 114) verified PR #215: 178 raw.pixls.us files from 118 Panasoni
|
||||
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
|
||||
Leica M Monochrom verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica CL verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica M10 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica C-Lux verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica M Monochrom (Typ 246) verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica M8 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica X2 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica Q2 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica SL (Typ 601) verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica M10-R verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica SL2 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Leica M9 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash)
|
||||
Leica Q (Typ 116) verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
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)
|
||||
Nikon D700 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XF10 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A10 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5300 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T100 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-Pro1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 V1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J4 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 100S II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D610 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D2H verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 6 II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX P1000 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X100 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X30 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X10 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D2Xs verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D4 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D800 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D780 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D850 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E2S verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D500 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 50R verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Df verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-S10 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 V2 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 V3 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3s verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z fc verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D810 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A3 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D40 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D800E verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3X verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100V** verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D4S verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T30 III verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XQ2 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T10 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D2X verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X70 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D80 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-H1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J5 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D7200 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T30 II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 50 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5000 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XQ1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix HS30 EXR verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D70S verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5200 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX P1100 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-S20 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 30 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E2 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D60 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J2 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5600 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D300 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix SL1000 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-Pro3** verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-Pro2 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 S1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100VI verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T200 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3200 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T3 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix F550 EXR verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D5500 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A7 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3300 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 5 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon 1 J3 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 9 (*See note) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX A1000 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100S verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D2Hs verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D90 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D50 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3000 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100T verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 50 II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D600 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm XF1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D7100 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E3 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-A1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3500 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix HS50 EXR verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 100 II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X100F verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D40x verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX A verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X20 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-E4 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm GFX 50S II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D1H verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D200 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix HS33 EXR verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix S1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon Z 7 II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D70 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D300s verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X-S1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D750 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3100 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon D3400 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix X-M1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm X-T30 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX P950 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Fujifilm FinePix F770 EXR verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Nikon COOLPIX 5700 unsupported bulk: raw.pixls.us CC0 file decodes wrongly (two stacked half-height fields, CMYG mosaic read as RGB; green vs camera JPEG r 0.12-0.36)
|
||||
Nikon COOLPIX 8400 unsupported bulk: raw.pixls.us CC0 file decodes wrongly (two stacked half-height fields, CMYG mosaic read as RGB; green vs camera JPEG r 0.12-0.36)
|
||||
Nikon COOLPIX 8800 unsupported bulk: raw.pixls.us CC0 file decodes wrongly (two stacked half-height fields, CMYG mosaic read as RGB; green vs camera JPEG r 0.12-0.36)
|
||||
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)
|
||||
@@ -151,8 +367,44 @@ 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)
|
||||
Pentax K-1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax *ist DL verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Ricoh GX200 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash)
|
||||
Pentax KP verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-3 Mark III Monochrome verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash)
|
||||
Pentax K-70 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Ricoh GR IIIx verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K20D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax *ist DS verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-3 Mark III verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-01 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K110D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax Q7 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-S1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax *ist D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-30 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K200D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-5 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-x verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Ricoh GR verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax 645D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K100D verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-500 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K2000 K-m verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-50 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax 645Z verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-5 II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax Q verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax MX-1 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K100D Super verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Ricoh GR II verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-S2 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-r verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax KF verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-3 II († see note) verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Pentax K-7 verified corpus: crates/raw/tests/body_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
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 A100 (DSLR-A100) preview issue #702 fixed (#774): opens from its embedded JPEG; its raw (no CFA image IFD) is not decoded
|
||||
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
|
||||
@@ -213,7 +465,7 @@ Sony A900 (DSLR-A900) verified issue #535: raw.pixls.us bulk check of all 100 So
|
||||
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-F828 unsupported SRF not in the import list (the probe accepts it again since #774, issue #702); raw not decoded
|
||||
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
|
||||
@@ -250,3 +502,64 @@ Sony RX1R II (DSC-RX1RM2) verified issue #535: raw.pixls.us bulk check of all 10
|
||||
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)
|
||||
Sony ZV-1M2 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony ZV-E10M2 verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony RX1R III (DSC-RX1RM3) verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony A1 II (ILCE-1M2) (** see note) verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony DSC-RX100M7A verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony A7 V (ILCE-7M5) (** see note) verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony FX2 (ILMEFX2) (** see note) verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony ILCE - 6400A verified corpus: crates/raw/tests/sony_leica_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-550 UZ verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus E-10 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash)
|
||||
Olympus Camedia C-5060 Zoom verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-565 UZ verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus OM-D E-M5 Mark II verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus EVOLT E-300 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus Stylus SH-2 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus Camedia C-7070 Wide Zoom verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus Stylus XZ-10 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus EVOLT E-330 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-570 UZ verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus SP-510 UZ verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus PEN-F verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Olympus EVOLT E-500 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Samsung TL350 (WB2000) verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Samsung NX1000 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Samsung NX1100 verified corpus: crates/raw/tests/olympus_samsung_corpus.rs (pinned sensor hash, camera-JPEG check)
|
||||
Sony A100 (DSLR-A100) unsupported issue #702: regression, refused as not a readable photo
|
||||
Sony DSC-F828 unsupported issue #702 (SRF refused); SRF not in the import list
|
||||
Epson R-D1 verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Epson R-D1s verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Epson R-D1x verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Mamiya ZD verified corpus: crates/raw/tests/corpus.rs (xtask RAW_SAMPLES)
|
||||
Apple iPhone 6s Plus verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Apple iPhone 7 Plus verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Apple iPhone XS verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI Mavic 2 Pro (Hasselblad L1D-20c) verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI Mavic 3 (Hasselblad L2D-20c) verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI Mavic 4 Pro (DJI FC9287) verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
DJI DJI Mini 2 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 4 XL verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 4a Rear Wide Camera verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 6 Pro Rear Main Camera verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Google Pixel 8 Pro Wide Camera* verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Hasselblad CFV-50c verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad H5D-40 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad H5D-50c verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad X1D verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad X1D II 50C verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Hasselblad X2D 100C verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); decode verified, not colour calibration
|
||||
Nikon D6 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); checked compressed NEF only; uncompressed remains preview-only (#671)
|
||||
Nikon Z 6 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); checked compressed NEF only; uncompressed remains preview-only (#671)
|
||||
Nikon Z 7 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); checked compressed NEF only; uncompressed remains preview-only (#671)
|
||||
Nikon Z 8 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check); HE / HE* remain preview-only
|
||||
Parrot Anafi verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S21 Ultra Rear Main Camera verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S22 Ultra Rear Wide Camera verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S23 Rear Wide Camera verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S7 Edge verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S8 verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Samsung Galaxy S8+ verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Sigma fp verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
Sigma fp L verified corpus: crates/raw/tests/coverage_sweep_corpus.rs (pinned sensor hashes); bulk: docs/raw/coverage-sweep.tsv (CC0, SHA-256, camera-image check)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 3.
|
@@ -64,6 +64,16 @@ whose glyph-coverage test checks the characters in available faces. `CRAFT_FONTS
|
||||
the native build fail if the pinned manifest lacks Noto Sans CJK SC Regular (`Hans`) or BIZ UDPGothic Regular;
|
||||
the web build requires BIZ UDPGothic Regular and packages Noto Sans CJK SC as a separate asset.
|
||||
|
||||
Local macOS, Linux and Windows packaging scripts automatically use the sibling `../craft-fonts`
|
||||
checkout. If it is absent, they clone it at revision
|
||||
`3d9ab3a132ed0eff457e424226a435a901da30d3` (keep the pins in `packaging/fonts.sh` and
|
||||
`packaging/windows/fonts.ps1` in sync with the release workflow). Existing checkouts are left untouched.
|
||||
Set `CRAFT_FONTS_DIR` to use another
|
||||
checkout; relative paths resolve from the workspace root. The script requires the Chinese and Japanese
|
||||
UI faces and includes their OFL licences in the package. Download failures or incomplete checkouts
|
||||
stop packaging with an error. `--skip-build` (`-SkipBuild` on Windows) packages existing binaries without downloading fonts or
|
||||
changing what they embed; pass the same `CRAFT_FONTS_DIR` used to compile them so their licences ship.
|
||||
|
||||
## Signing credentials
|
||||
|
||||
All credentials are stored as secrets in the GitHub `release` environment. Signing is optional:
|
||||
|
||||
+2
-2
@@ -72,12 +72,12 @@ calibration: M0–M13 took ≈ 25 active hours against an estimate of ≈ 110–
|
||||
| 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 ⬜) |
|
||||
| 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, 5 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 ⬜) |
|
||||
| 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/Georgian localisation 🟡; accessibility and further locales ⬜) |
|
||||
|
||||
## Risks that coding hours alone don't retire
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# Slideshow
|
||||
|
||||
LightCraft's slideshow follows Lightroom Classic's Slideshow module (no Adobe assets, templates or designs): the photos
|
||||
in view played full screen with a layout, overlays, intro and ending screens and fades, and exported as PDF, JPEG or
|
||||
video. There is no Slideshow module view yet: the settings live in Settings ▸ Slideshow (View ▸ Slideshow Options…)
|
||||
next to a live preview of the selected photo's slide, and View ▸ Slideshow (⌥⌘↩) plays.
|
||||
|
||||
| Part | Commands | Code |
|
||||
|---|---|---|
|
||||
| Playback: slide and fade durations, fade colour, random order, repeat, preparing slides ahead | `slideshow.playback`, `view.slideshow` | `crates/engine/src/slideshow.rs` (the timeline), `crates/ui-egui/src/panels/slideshow.rs` |
|
||||
| Layout, options, backdrop: margins, aspect preview, zoom to fill, stroke, shadow, colour, colour wash, background photo | `slideshow.layout` | `crates/slideshow` (the composer, no UI), `crates/engine/src/slide.rs` |
|
||||
| Overlays: identity plate, rating stars, text with tokens, watermark | `slideshow.overlays` | `crates/engine/src/slide_overlay.rs` |
|
||||
| Intro and ending screens | `slideshow.titles` | `crates/engine/src/slide_title.rs` |
|
||||
| Templates: built-ins of our own and the user's (`<settings>/slideshow-templates/*.json`) | `slideshow.templates.*` | `crates/engine/src/slide_template.rs` |
|
||||
| One slide or screen as a PNG | `slideshow.preview` | `crates/engine/src/cmd/slideshow.rs` |
|
||||
| Export: PDF, JPEG sequence, AV1 video | `slideshow.export`, `slideshow.exportStatus` | `crates/engine/src/slideshow_export.rs`, `crates/codecs/src/video.rs` |
|
||||
|
||||
All settings are library preferences (`prefs.json`); sizes and offsets are fractions of the slide's shorter side, so a
|
||||
slide looks the same on any screen and at any export size. Playback, the preview, `slideshow.preview` and export draw
|
||||
the same pixels through the same composer.
|
||||
|
||||
## Export
|
||||
|
||||
View ▸ Export Slideshow… (or Export PDF / JPEG / Video at the end of Settings ▸ Slideshow) chooses a format and size,
|
||||
then asks where to write. The slides are the photos in view, in view order, between the intro and ending screens that
|
||||
are on; random order and repeat are playback choices and don't apply. The slide aspect is the Layout's aspect preview
|
||||
(Screen exports 16:9).
|
||||
|
||||
- **PDF** — one page per slide, its picture a JPEG at the chosen quality, the page as many points as the slide has
|
||||
pixels (1024 / 1920 / 3840 on the long side; 64–8192 by command). Each page has the slide duration (`/Dur`) and,
|
||||
after the first, a fade transition (`/Trans`), which PDF viewers use in presentation mode; "Automatically show full
|
||||
screen" sets `/PageMode /FullScreen`. Written by `crates/engine/src/pdf.rs` (shared with the contact sheet), streamed
|
||||
to disk.
|
||||
- **JPEG** — `<name>-001.jpg`, `-002.jpg`… in the chosen folder (created; `name` defaults to the folder's name).
|
||||
- **Video** — AV1 in MP4 (default) or WebM, 720p or 1080p (64–2160 by command), 24 or 30 fps (25 / 60 by command), no
|
||||
audio (music is a later item, LRC-SS-MUSIC). The timeline is sampled at the frame rate: a slide's fade-in is rendered
|
||||
frame by frame (a crossfade, or out to the fade colour and in from it), then the slide is held for the rest of its
|
||||
duration as **one** sample lasting that long (variable frame rate), so a still slide costs one encoded frame. That
|
||||
frame is a key frame: seeking lands on slides. Encoded by `rav1e` (pure Rust, BSD-2-Clause, already used for AVIF) at
|
||||
speed 10, 8-bit 4:2:0 BT.709 limited range, in order (low latency, no frame reordering); at most 2 hours.
|
||||
|
||||
The muxers are our own (`crates/codecs/src/video.rs`, from the public ISO/IEC 14496-12 + AV1-ISOBMFF and
|
||||
Matroska/WebM specifications): MP4 is `ftyp`, one `mdat` (64-bit size patched at the end) and `moov` with an `av01`
|
||||
sample entry (`av1C` holding the sequence header OBU, `colr nclx`, `pasp`), `stts` durations, `stss` key frames and a
|
||||
single chunk; WebM is the EBML header and a Segment with SeekHead, Info (duration), Tracks (`V_AV1`, `CodecPrivate` =
|
||||
`av1C`), Clusters of SimpleBlocks (the last frame a BlockGroup with its duration) and Cues. Samples are temporal units
|
||||
without temporal delimiters. No AV1 decoder is in the product, so the tests check the container structure, sample
|
||||
counts and durations; ffmpeg / browsers play the files (checked by hand when the muxers change).
|
||||
|
||||
The export runs on a worker thread with a row in the activity stack ("Exporting slideshow": slides done, or frames for
|
||||
video, and the slide being rendered; ✕ or `activity.cancel {id: taskId}` stops it). Every output is written as
|
||||
`<file>.part` and renamed when complete, so a cancelled, failed or interrupted export leaves nothing behind (for a JPEG
|
||||
sequence, all files are renamed at the end). A photo that can't be rendered (its file gone or unreadable) is skipped
|
||||
and named in the result's `warnings`; a full disk or an unwritable folder is an error. An original in the library is
|
||||
never overwritten (`check_write_target` before and after).
|
||||
|
||||
Encoding speed (rav1e speed 10, measured 2026-10-11 on a 32-thread Linux machine shared with other work): one minute of
|
||||
slideshow (15 slides of 4 s with 1 s fades, 30 fps: 435 encoded frames) took 35 s at 720p and 74 s at 1080p, slide
|
||||
rendering included. The cost is in the fades (one encoded frame per frame of fade); held slides cost one frame each.
|
||||
|
||||
## Not yet
|
||||
|
||||
The Slideshow module view (left-panel template browser, slide editor with draggable guides and overlays), music and
|
||||
sync to music, pan & zoom, H.264 video, saving a slideshow with an album, export presets.
|
||||
@@ -0,0 +1,314 @@
|
||||
# Sony ARW lens corrections
|
||||
|
||||
Sony cameras record three lens-correction tables in the raw IFD of every ARW: distortion, vignetting and lateral
|
||||
chromatic aberration (CA). LightCraft reads them and turns distortion into a DNG `WarpRectilinear` opcode, so it
|
||||
reaches the same **Optics ▸ Enable Lens Corrections** (`optics.lens_profile`) as a DNG's embedded warp and Panasonic's
|
||||
RW2 distortion data. Lateral CA is parsed and converts to the warp's red and blue planes, but it is **off by default**:
|
||||
applied after demosaic it made the render's CA worse (Verification). Vignetting is read but not applied (below). The
|
||||
conversion is verified on the **ILCE-7RM6** only; the ILCE-7RM4A has its own conversion, with other conventions
|
||||
([Two conventions](#two-conventions)), and other Sony bodies' tables give no correction until they are verified.
|
||||
|
||||
The correction is on by default for new imports, as for any file with embedded lens data (`Photo::camera_defaults`).
|
||||
Photos imported before this change keep their settings: **Photo → Reload from Disk** adds the lens data and, when the
|
||||
photo is still at its import settings, turns the correction on as one undoable step; the automatic reload after an
|
||||
external editor saves the file does the same. Edited photos keep their settings. The Profile Distortion slider
|
||||
scales the warp as for DNG and RW2.
|
||||
|
||||
## The tables
|
||||
|
||||
ExifTool's names (EXIF table, `SubIFD` group); each table is a count-prefixed array of signed 16-bit values
|
||||
(`SSHORT`, 17 / 17 / 33 values), and each has an in-camera on/off tag:
|
||||
|
||||
| Table | Tag | Flag tag | Count (full frame / APS-C crop mode) | Flag values seen |
|
||||
|---|---|---|---|---|
|
||||
| Distortion (`DistortionCorrParams`) | `0x7037` | `0x7036` | 16 / 11 | 0 (off) or 1 (on) |
|
||||
| Vignetting (`VignettingCorrParams`) | `0x7032` | `0x7031` | 16 / 11 | 2 on all 54 photos |
|
||||
| Lateral CA (`ChromaticAberrationCorrParams`) | `0x7035` | `0x7034` | 32 / 22 (red, then blue) | 1 on all 54 photos |
|
||||
|
||||
The first value is the knot count; only the first `count` values are used. Full-frame files carry 16 / 16 / 32 knots;
|
||||
APS-C crop-mode files 11 / 11 / 22, padded to the same array length (distortion with its last value repeated,
|
||||
vignetting and CA with zeros). The CA table holds red's `count / 2` knots, then blue's. The corrections are built
|
||||
whatever the flags say: the flag only records what the camera did to its own JPEG. Tables with a count outside
|
||||
2–16 (CA: an odd count or outside 4–32), a count that doesn't fit the array, or non-integer values are ignored.
|
||||
|
||||
## Measured conventions
|
||||
|
||||
None of this is documented; it was measured against the camera's own JPEGs (method below). Residuals are in px at a
|
||||
1440 px long edge.
|
||||
|
||||
- **Knots and centre.** Knot `i` sits at sensor radius `i · s` from the default-crop centre, with
|
||||
`s = hypot(9984, 6656) / 30` = 399.98 px: the full-frame default crop's half diagonal divided by 15, so knot 15 is
|
||||
the full-frame crop corner. The spacing is fixed on the sensor: APS-C files use the same pixel spacing (verified on
|
||||
CA, rms 0.004–0.010 px against 0.011–0.014 px for `i/15` of the APS-C half diagonal; `i/10` of it, 392 px, fits as
|
||||
well). Values are interpolated linearly between
|
||||
knots; beyond the last knot the last segment is extended (it matters only in the outermost ~0.4 knot spacing at
|
||||
the corners of a zoomed-out barrel correction). The centre is the default-crop centre: the measured translation
|
||||
between our render and the camera JPEG has median 0.013 px, max 0.216 px.
|
||||
- **Distortion** is relative and indexed at the corrected radius, in units of 1/15000: a corrected radius `r`
|
||||
reads the source radius `S(r) = r · (1 + v(r) / 15000)` (positive values: pincushion; negative: barrel). The camera
|
||||
then zooms so the output fills the default crop: output radius = `z` · corrected radius, with `z` chosen so that
|
||||
the largest `S(ρ / z) / ρ` over the crop's border radii `ρ` is 1 (binding at the corner for pincushion, at the
|
||||
short-edge midpoint for barrel). `z` was 0.971–1.035 on these photos. Without the zoom every hypothesis fails
|
||||
(24.6 px); with it, the worst residual over the 34 measurable corrected photos was 0.596 px (rms 0.143; corners and
|
||||
edge midpoints 0.570 px), within the 0.75 px budget for a unit between about 14700 and 15350. A global
|
||||
least-squares fit gives 15000.7.
|
||||
- **Lateral CA** is relative to the green source radius, at that radius: red's source radius is
|
||||
`g · (1 + c_R(g) / 3.36·10⁶)`, with `g` the green source radius (after the distortion correction above) and `c_R`
|
||||
the red half on the same knots; blue likewise with the second half. Positive values: that colour's image is larger
|
||||
than green's. **The unit is provisional.** The measurement is borderline: on the 15 photos with CA above 0.15 px
|
||||
that a single unit explains, the best (minimax) unit 2.26·10⁶ leaves 0.305 px against a 0.3 px budget; per-photo
|
||||
best units scatter from 1.5·10⁶ to 7.2·10⁶ (about ±30 % scene bias: the RawDB landscape and portrait shots of one
|
||||
scene, with nearly identical tables, measure 3.4–3.5·10⁶ and 4.5·10⁶). The chosen 3.36·10⁶ is the median of the 20
|
||||
cleanest photos: worst 0.399 px on the 15, and the rms raw CA over all 46 measured photos falls from 0.079 to
|
||||
0.052 px. Swapping the halves or an absolute form (`v · norm / U`) is clearly worse. **Not applied by default**
|
||||
(Verification).
|
||||
- **Vignetting: not applied.** The camera JPEGs show no vignetting compensation relative to our uncorrected render:
|
||||
over the 39 photos whose measurement reaches the corners, the corner/centre ratio JPEG / render has median 0.996
|
||||
(p10 0.907, p90 1.087), while the tables would predict a corner gain with median +32 % for `1 + v / 2¹⁴` (+16 %
|
||||
for `v / 2¹⁵`, +63 % for `v / 2¹³`). Regressing the measured corner EV on the predicted one gives slope 0.009 ±
|
||||
0.063. No model (`1 + v/U`, `U/(U − v)`, `2^(v/U)`) at any unit from 2¹³ to 2¹⁸ reaches 3 %; the identity is the
|
||||
best of all. The raw data isn't pre-compensated either: the read noise of three dark high-ISO frames is flat from
|
||||
centre to corner, where a digital gain from these tables would raise it by 60–80 %. So the table probably describes
|
||||
the lens's natural falloff, but this camera's JPEGs don't apply it, and nothing shows its unit or model. Options:
|
||||
(a) skip it, so renders match the camera JPEG (the current ruling); (b) apply it with an unverified model for a
|
||||
Lightroom-like look; (c) shoot flat fields (a white wall at several apertures, one lens) and measure the model.
|
||||
|
||||
## Conversion to `WarpRectilinear`
|
||||
|
||||
`crates/raw/src/vendor/arw_lens_rm6.rs` builds one `WarpRectilinear` in `OpcodeList3`, centred on the default-crop centre
|
||||
(DNG pixel-index units relative to the active area; radius 1 = the farthest active-area corner, `m`):
|
||||
|
||||
1. `S` from the distortion table and the zoom `z` (bisection on [0.5, 2], 4097 border radii); the green map is
|
||||
`G(r) = S(r / z)`. Red and blue, when the CA planes are on: `G(r) · (1 + c(G(r)) / 3.36·10⁶)`.
|
||||
2. Each map is sampled at `u = i / 64`, i = 0…64 (65 samples of `G(u · m) / m`) and fitted by least squares with
|
||||
DNG's 4-term odd polynomial `u · (k0 + k1 u² + k2 u⁴ + k3 u⁶)` (`vendor::fit_radial_warp`, shared with RW2).
|
||||
3. **Fit gate:** a plane is refused when its fit is worse than 0.25 px at a 1440 px long edge at a sample the crop
|
||||
shows: the samples up to the first one at or beyond the crop corner. The lossless files' padded active area
|
||||
(10240 × 7168 for a 9984 × 6656 crop) reaches radii that are never shown (`u` up to 0.925 is shown there).
|
||||
Over all 54 photos the fit's worst error at all 65 samples was 0.220 px (a lossless file; ARW6 files at most
|
||||
0.175 px). Between samples the error is somewhat larger: 0.071 against 0.049 px for the full-frame 16–35 mm
|
||||
example in the tests.
|
||||
4. **By default one plane, G**, applied to all three channels: `lens_opcodes` calls `warp_opcode(…, lateral_ca:
|
||||
false)`. With `lateral_ca: true` (a code change) the planes are `[R, G, B]`, unless the CA table is absent or
|
||||
malformed, a CA value is implausible (|c| above 2·10⁻³ of the radius, i.e. 6720; the largest value in the 54
|
||||
photos' tables is 1724) or a colour plane fails the gate: then G alone again. The G plane is the same either way.
|
||||
No opcode when the distortion table is absent or all zero (CA alone is never applied: it is relative to green),
|
||||
the zoom has no solution in [0.5, 2] or the G fit fails. A refused table leaves the photo uncorrected rather than
|
||||
wrongly warped.
|
||||
|
||||
The opcode then goes through the same pipeline stage as a DNG's (`crates/pipeline/src/optics.rs`): it rotates with
|
||||
the photo (portrait files are covered) and is carried by DNG export, as RW2's is.
|
||||
|
||||
## Which bodies get it
|
||||
|
||||
Only bodies listed in `FULL_FRAME_CROP` (`arw_lens_rm6.rs`) get an opcode: today `ILCE-7RM6` (9984 × 6656). The unit and
|
||||
the knot spacing are verified on that body alone; the spacing is defined by its full-frame crop, and a body with
|
||||
another sensor size or another unit would be warped wrongly. Other bodies get no correction from this conversion; the
|
||||
ILCE-7RM4A gets its own, with other conventions (below). To add a body: collect photos of it shot with distortion
|
||||
correction on (several lenses and focal lengths), repeat the camera-JPEG registration below against the uncorrected
|
||||
render, confirm the unit, the knot spacing and the zoom rule (or measure the body's own), then add its full-frame
|
||||
default crop to the table with a test.
|
||||
|
||||
## Two conventions
|
||||
|
||||
A second Sony decoder, `crates/raw/src/vendor/arw_lens.rs`
|
||||
([Sony embedded distortion corrections](sony-lens-corrections.md), PR #498), reads the same `0x7037` table on the
|
||||
**ILCE-7RM4A**, validated against Sony Imaging Edge exports (distortion On/Off pairs at 200 and 600 mm with the
|
||||
FE 200–600 mm; corrected TIFFs at 24 mm with the FE 24–105 mm). Its conventions differ from the ones above
|
||||
(`r_o` = output radius about the crop centre, `v` = the table, linear between knots):
|
||||
|
||||
| | ILCE-7RM6 (this page, `arw_lens_rm6.rs`) | ILCE-7RM4A (`arw_lens.rs`) |
|
||||
|---|---|---|
|
||||
| Knots | `i · 399.98` px, fixed on the sensor; last segment extended | `i / 15` of the crop's half diagonal; radius clamped to 1 |
|
||||
| Table indexed at | the corrected radius `r_o / z` | the output radius `r_o` |
|
||||
| Unit | 15000 | 16384 |
|
||||
| Zoom | fill: the largest `S(ρ / z) / ρ` over the border is 1 | `1 / max f` over the border radii |
|
||||
| Aspect crops | applied; the zoom for the recorded crop is unverified | refused (native 3:2 only) |
|
||||
| Tables | distortion (16 knots; 11 in APS-C); lateral CA parsed, off by default; vignetting read, not applied | distortion, 16 entries only |
|
||||
|
||||
`arw::decode` passes both the same active area and crop (the DNG-style default crop, on the ILCE-7RM6 the same as
|
||||
Sony's crop tags); their model lists don't overlap, so a photo gets at most one of them: an ILCE-7RM6 this page's
|
||||
conversion, an ILCE-7RM4A the other, every other body neither.
|
||||
|
||||
**Cross-check.** The ILCE-7RM4A formula, scored on the 34 measurable corrected ILCE-7RM6 photos exactly as in
|
||||
Measured conventions (radial bins, px at 1440, max / rms; "c" = the worst corner or edge-midpoint point):
|
||||
|
||||
| Variant | Unit | All photos | Corners max / median | 24–70 GM II (23) | 100 mm Macro (8) | 200–600 G (3) |
|
||||
|---|---|---|---|---|---|---|
|
||||
| **A**: this page | 15000 | **0.596 / 0.143** | 0.570 / 0.099 | 0.596 / 0.100, c 0.474 | 0.361 / 0.135, c 0.336 | 0.588 / 0.325, c 0.570 |
|
||||
| **B1**: the ILCE-7RM4A formula | 16384 | **1.429 / 0.319** | 1.913 / 0.204 | 1.429 / 0.385, c 1.913 | 0.289 / 0.049, c 0.234 | 0.264 / 0.115, c 0.320 |
|
||||
| **B2**: B1 at its best single unit | 15680 | 0.940 / 0.223 | 1.202 / 0.098 | 0.940 / 0.215, c 1.202 | 0.327 / 0.100, c 0.278 | 0.683 / 0.428, c 0.637 |
|
||||
| **B3**: A's indexing and zoom at 16384 | 16384 | 1.450 / 0.455 | 1.845 / 0.350 | 1.450 / 0.539, c 1.845 | 0.284 / 0.062, c 0.238 | 0.654 / 0.329, c 0.586 |
|
||||
|
||||
- B1 misses the 0.75 px budget on these photos, but only on the 24–70 GM II: at 24–28 mm it under-corrects the barrel
|
||||
in the outer half (up to 1.43 px at 0.7–0.85 of the half diagonal), at 45–70 mm the pincushion by a nearly uniform
|
||||
0.2–0.4 px. On the 100 mm and the 200–600 it fits better than A, and on the 200–600, the one lens both validations
|
||||
share, its unit agrees with this body's (best unit under its indexing 16524–16602). So the data does not show the
|
||||
two bodies differing.
|
||||
- The zoom rules agree (within 0.0035 on every photo); the unit and the table index make the difference. Under A's
|
||||
indexing the 24–70 GM II's barrel and pincushion ends want the same unit (14749 / 14860, 0.7 % apart); under B's
|
||||
they need 14792 / 15705 (6 % apart).
|
||||
- APS-C: B refuses 11-entry tables. Its knots read literally on the APS-C crop (`i / 15` of its half diagonal,
|
||||
261.5 px) fit the APS-C RawDB files' lateral CA 4 × worse on 3 of 6 photos than the sensor-fixed 400 px; `i / 10`
|
||||
(392 px) can't be told from 400 px.
|
||||
|
||||
**Open question: no single unit fits every lens under either convention.** The 200–600 wants a 5–7 % larger unit (a
|
||||
weaker correction) than the 24–70 GM II's pincushion end with similar table values (+409 … +561 against +406 … +454
|
||||
at the corner), under both indexings and every knot spacing tried (0.94–1.12 ×: the ratio of the two lenses' best
|
||||
units stays 1.053–1.073). A's 15000 is the compromise that keeps every photo within 0.6 px; 16384 is the 200–600's
|
||||
value. That rests on 3 measurable 200–600 photos (594–600 mm). The ILCE-7RM4A's own wide-angle evidence is its
|
||||
weakest: its On/Off pairs are all 200–600, and its 24 mm check (LightCraft export against Sony's TIFF) is median 0.35 /
|
||||
95th percentile 1.04 px at 2376 px. On its `WIDE` unit-test table the two formulas differ by up to 2.49 px at 1440 at
|
||||
the corner (computed from the formulas, not measured).
|
||||
|
||||
**What would settle it:** Sony Imaging Edge On/Off exports of the 24–70 GM II (or any wide zoom's wide end) on either
|
||||
body, which would show whether the wide-end disagreement is the body or the formula; and more lenses, and more
|
||||
200–600 photos, on the ILCE-7RM6, to tell a per-lens unit from a convention. Until then each body keeps the
|
||||
conventions it was validated with.
|
||||
|
||||
## Method
|
||||
|
||||
Photos: 54 ILCE-7RM6 ARWs: 42 private, and the 12 CC0 samples of the
|
||||
[dnglab RawDB ILCE-7RM6 set](https://rawdb.dnglab.org/sets/Sony/ILCE-7RM6) (`ILCE-7RM6_{FF,APSC}_{land,port}_RAW{,-C,-C-HD}.ARW`:
|
||||
full frame and APS-C, landscape and portrait, lossless, Compressed and Compressed HQ). `cargo xtask corpus --download`
|
||||
fetches three of them: the APS-C lossless file as `arw-sony-ilce7rm6-apsc-land-lossless.arw`, and the ARW 6.0
|
||||
decoder's full-frame Compressed and APS-C Compressed HQ files (`arw6-sony-ilce7rm6-ff-land-c.arw`,
|
||||
`arw6-sony-ilce7rm6-apsc-land-hq.arw`). The corpus test `corpus_sony_lens_tables_become_opcodes` checks all three, and
|
||||
the full-frame lossless file where it is present.
|
||||
Four lenses: FE 24–70 mm F2.8 GM II (27 photos), FE 16–35 mm F2.8 GM II (12, all RawDB), FE 100 mm F2.8 Macro GM OSS
|
||||
(9), FE 200–600 mm F5.6–6.3 G OSS (6). 41 photos have in-camera distortion correction on (all private); 13 have it
|
||||
off (the 12 RawDB files and one private photo). Only aggregate numbers per lens are reported. The scripts are local
|
||||
(the gitignored `plan/arw6/lens/`), not in the repository; the steps are described so they can be redone.
|
||||
|
||||
- **Oracle:** the camera JPEG inside each ARW (`JpgFromRaw`, 9984 × 6656 / 6528 × 4352, stored unrotated, turned to
|
||||
the photo's orientation). Tag values were read with ExifTool used as a tool. Clean room: no lens-correction code of
|
||||
any other project and no Adobe data was read.
|
||||
- **Distortion (camera-JPEG block registration).** Our render at half the JPEG size and the JPEG (2 × 2 box-reduced)
|
||||
are both reduced to a quarter of the JPEG size; on the green channel, every 40 px a 64 px JPEG block is located in
|
||||
the render by normalised cross-correlation with parabolic sub-pixel refinement. Pass 1 searches coarse-to-fine
|
||||
(±28 px at 1/16 size, then ±6 px); pass 2 (used for every number) searches ±6 px around pass 1's smooth radial fit
|
||||
(data-derived, needed for a macro of a periodic screen). Blocks with low contrast (std < 2), NCC < 0.8 or a
|
||||
tangential displacement above 4 px are dropped. A robust fit of `p_render = g(r) · p_jpeg + t` (`g` an even
|
||||
4-term polynomial) gives the translation `t`; the measured radius ratio is the median of 32 radial bins (≥ 10
|
||||
blocks each). A photo is measurable with ≥ 300 blocks and ≥ 15 bins reaching 0.7 of the half diagonal: 34 of the
|
||||
41 corrected photos (two black frames, a near-black night frame, two low-detail frames and two whose blocks reach
|
||||
only 0.54 of the half diagonal are not). 108 hypotheses (radius norm, knot placement, relative or absolute, table
|
||||
indexed at the corrected or the source radius, zoom rule), each with its best unit, were compared.
|
||||
- **Lateral CA (raw CFA).** The demosaiced render shows only 25–60 % of the lens's CA and the JPEG's 4:2:2 chroma
|
||||
and noise reduction hide it, so CA was measured on the raw: from LightCraft's uncompressed CFA DNG export, the
|
||||
red (blue) plane against green interpolated at the same sites (4-neighbour mean), square-root encoded, 2 × 2
|
||||
binned; 40 px blocks every 24 px, ±3 px NCC search, radial component, median per 16 radial bins.
|
||||
- **Vignetting (exposure brackets).** The JPEG is resampled into the render's geometry; per pixel and channel, the
|
||||
exposure at which eight renders bracketed −0.3 … +1.8 EV equal the JPEG value is interpolated (smooth areas, JPEG
|
||||
values 12–240, monotone brackets). That cancels the fitted tone curve, since exposure is a scene-linear gain before
|
||||
it. Medians in 16 annuli give the JPEG's falloff relative to our uncorrected render.
|
||||
|
||||
## Verification
|
||||
|
||||
Every photo rendered with Enable Lens Corrections on and off at half the JPEG size (50 of the 54 are Compressed or
|
||||
Compressed HQ ARW 6.0 files, so the renders used a local build of this code merged with the ARW6 decoder), then the same block
|
||||
registration (passes 1 and 2) against the camera JPEG, and R and B against G inside each render (80 px blocks every
|
||||
128 full-resolution px, ±4 px search; per corner the median radial shift of the 12 nearest blocks). px at a 1440 px
|
||||
long edge; aggregates only.
|
||||
|
||||
**Distortion, photos corrected in camera** (our render with the correction on vs the camera JPEG; budget 0.75 px).
|
||||
"Corners + midpoints" is the 2-D displacement at the four corners and four edge midpoints, global translation
|
||||
included; "bins" the radial residual over 32 radial bins. A photo counts as measurable as in the method above.
|
||||
|
||||
| Lens | Photos (measurable) | Focal lengths | Corners + midpoints max / rms | Bins max / rms | Uncorrected, corners (per-photo max) |
|
||||
|---|---|---|---|---|---|
|
||||
| FE 24–70 mm F2.8 GM II | 26 (23) | 24–70 mm | 0.553 / 0.125 | 0.503 / 0.066 | 1.1–17.3 |
|
||||
| FE 100 mm F2.8 Macro GM OSS | 9 (7) | 100 mm | 0.409 / 0.111 | 0.317 / 0.097 | 0.6–4.8 |
|
||||
| FE 200–600 mm F5.6–6.3 G OSS | 6 (3) | 594–600 mm | 0.679 / 0.321 | 0.498 / 0.274 | 7.5–10.8 |
|
||||
| **All** | **41 (33)** | | **0.679** / 0.150 (206 points) | 0.503 / 0.109 | 0.6–17.3 |
|
||||
|
||||
No photo is over budget; the global translation is at most 0.056 px. The 8 not measurable are black, near-black or
|
||||
low-detail frames, or frames whose blocks don't reach 0.7 of the half diagonal. That is one more than in the
|
||||
measurement (33 measurable against 34): one 100 mm photo keeps only 255 of the 300 blocks needed when it is matched on
|
||||
the corrected render, as block coverage differs slightly between the two renders. The 200–600 mm keeps the systematic
|
||||
residual the measurement found for it (its own best unit is 15659, see Limits).
|
||||
|
||||
**Controls, correction off in camera** (13 photos: the 12 RawDB files, full frame and APS-C, and one private 24–70 mm
|
||||
at 58 mm). Their JPEG keeps the lens's distortion, so our corrected render must differ from it by the model's own shift:
|
||||
it does, by up to 10.5 px (full frame) and 11.4 px (APS-C), and matches that shift within 0.639 px at the corners and
|
||||
midpoints (bins 0.259 px; full-frame RawDB files ≤ 0.218 px, APS-C ≤ 0.639 px). This checks that the pipeline renders
|
||||
the model (also for APS-C, barrel, zoom 0.984), not that the APS-C model is right.
|
||||
|
||||
**Portrait photos:** 8 corrected (orientation 6 and 8) within 0.232 px, 6 controls within 0.369 px of the model's
|
||||
shift: the warp turns with the photo.
|
||||
|
||||
**Lateral CA in the render** (radial R-vs-G and B-vs-G shift, median of the 12 blocks nearest each corner; 43 photos
|
||||
with enough detail at all four corners; budget 0.3 px):
|
||||
|
||||
| Lens | Photos | Off: max R / B | Off: rms | On: max R / B | On: rms | Camera JPEG: max / rms |
|
||||
|---|---|---|---|---|---|---|
|
||||
| FE 24–70 mm F2.8 GM II | 23 | 0.089 / 0.071 | 0.028 | 0.219 / 0.148 | 0.069 | 0.150 / 0.036 |
|
||||
| FE 16–35 mm F2.8 GM II | 12 | 0.125 / 0.054 | 0.041 | 0.030 / 0.051 | 0.020 | 0.058 / 0.016 |
|
||||
| FE 100 mm F2.8 Macro GM OSS | 6 | 0.020 / 0.050 | 0.013 | 0.061 / 0.157 | 0.044 | 0.021 / 0.004 |
|
||||
| FE 200–600 mm F5.6–6.3 G OSS | 2 | 0.033 / 0.101 | 0.032 | 0.146 / 0.075 | 0.070 | 0.113 / 0.039 |
|
||||
| **All** | **43** | 0.125 / 0.101 | 0.032 | **0.219** / 0.157 | 0.052 | 0.150 / 0.028 |
|
||||
|
||||
Within budget everywhere, but **the correction makes the render's own CA larger on average** (rms 0.032 → 0.052 px;
|
||||
smaller only for the 16–35 mm). The reason is where it runs: over the radial bins beyond 0.3 of the half diagonal
|
||||
(418 bins), our demosaiced render shows only 0.29 × the lens CA measured on the raw CFA (correlation 0.85), while the
|
||||
warp after demosaic moves R and B by 0.84 × the table (correlation 0.96). On the raw data the table halves the CA (rms
|
||||
0.062 → 0.035 px); applied after a demosaic that already hid most of it, it overshoots (rms 0.021 → 0.035 px over the
|
||||
same bins). All of this is far below one pixel at 1440 px.
|
||||
|
||||
**Ruling: the lateral CA planes are off by default.** `lens_opcodes` emits the G plane alone; the conversion stays in
|
||||
the code and its unit tests (`warp_opcode(…, lateral_ca: true)`), so it can be turned on once CA is corrected where
|
||||
the table applies. **Follow-up:** warp the raw CFA's red and blue sites before demosaic (the table halves the raw CA,
|
||||
rms 0.062 → 0.035 px), then turn the planes on and repeat this check. Optics ▸ Remove Chromatic Aberration
|
||||
(`optics.remove_ca`, an automatic estimate from the image) remains available for visible fringes. The distortion
|
||||
numbers above were measured with the three-plane warp, whose G plane is the one the default emits.
|
||||
|
||||
**Fit gate margins** (worst of R, G and B at the gated samples; gate 0.25 px): the 4 lossless files 0.160 px (margin
|
||||
0.090; 0.220 px at all 65 samples, the padded radii never shown), the 46 full-frame ARW6 files 0.175 px (margin 0.075),
|
||||
the 4 APS-C ARW6 files 0.035 px. The largest CA value in the 54 tables is 1724 (FE 24–70 mm), a quarter of the 6720
|
||||
bound. So every photo passes: with the CA planes on (the verification renders) each got the three-plane warp, and the
|
||||
corrected and uncorrected renders differ on all 54; by default each gets the one-plane distortion warp.
|
||||
|
||||
## Performance
|
||||
|
||||
`LIGHTCRAFT_PROFILE=1` renders of the full-frame lossless file and the full-frame Compressed HQ file (corpus
|
||||
`arw-sony-ilce7rm6-ff-land-lossless.arw`, `arw6-sony-ilce7rm6-ff-land-hq.arw`), on a 4-core laptop shared with other
|
||||
builds (so absolute times are high); the fastest of 3–5 runs. The warp runs in the `sample` stage:
|
||||
|
||||
| Render | Off | One plane (the default; measured with manual Distortion 1) | Three planes (CA planes on) |
|
||||
|---|---|---|---|
|
||||
| Full size 9984 × 6656, lossless | 267 ms | — | 3098 ms |
|
||||
| Full size 9984 × 6656, Compressed HQ | 403 ms | 1187 ms | 4014 ms |
|
||||
| 1920 px long edge (2496 × 1664 source), Compressed HQ | 23.7 ms | 45.4 ms | 112.0 ms |
|
||||
|
||||
The default one-plane warp takes the sample stage from 24 to 45 ms at 1920 px (inferred from the manual Distortion
|
||||
run: the same single-plane path, one plane for all three channels). The three colour planes cost about 2.5–3× that,
|
||||
as for an RW2 or DNG with three planes (the same path): the price of turning the CA planes on. The stage cache keys
|
||||
the resampled source by the source, framing and output size, so tone, colour and exposure drags don't re-run it.
|
||||
|
||||
## Limits
|
||||
|
||||
- **ILCE-7RM6 only.** Other Sony bodies record the same tags; their knot spacing (defined here by the full-frame crop),
|
||||
unit and zoom rule are unverified, so they get no correction from this conversion (the ILCE-7RM4A's distortion has
|
||||
its own: [Two conventions](#two-conventions)).
|
||||
- **APS-C distortion is unverified in camera:** no APS-C photo with distortion correction on was available; the APS-C
|
||||
knot spacing is verified on CA only, and the APS-C zoom follows the full-frame rule.
|
||||
- **Aspect-ratio crops** (in-camera 4:3, 16:9, 1:1) were not measured; the correction uses the crop the file records.
|
||||
- **One distortion unit for every lens.** Fitted per lens the unit is 14826 (24–70 mm, 23 photos, very consistent),
|
||||
15659 (200–600 mm, 3 photos) and 16017 (100 mm, tiny tables); with the single 15000 the 200–600 mm keeps a systematic
|
||||
residual of up to 0.59 px (within budget, above the method's 0.03 px noise floor). Something lens-dependent is not
|
||||
captured; per-lens units would need per-lens verification.
|
||||
- **Lateral CA off by default.** Its unit is provisional (above), and a warp after demosaic, as for RW2 and DNG,
|
||||
overshoots: our demosaic already hides about 70 % of the lens CA, and with the planes on the rms corner CA rose
|
||||
from 0.032 to 0.052 px (Verification). Correcting CA before demosaic is the follow-up.
|
||||
- **Vignetting not applied** (above).
|
||||
- **DNG export** carries the warp in `OpcodeList3`, as for RW2: a DNG reader applies it like any embedded lens
|
||||
correction.
|
||||
- **Existing imports** need Photo → Reload from Disk to pick up the lens data.
|
||||
- The camera-JPEG colour fit still matches its pairs without the correction (docs/camera-preview-colour.md).
|
||||
|
||||
## Sources
|
||||
|
||||
- [ExifTool EXIF tag names](https://exiftool.org/TagNames/EXIF.html): the names and types of tags `0x7031`–`0x7037`
|
||||
(ExifTool 13.59 was used to read the tag values). Their meaning, units and conventions were measured as above.
|
||||
- [dnglab RawDB, Sony ILCE-7RM6](https://rawdb.dnglab.org/sets/Sony/ILCE-7RM6): the 12 CC0 samples (data only;
|
||||
dnglab's code was not consulted).
|
||||
+175
-37
@@ -1,25 +1,143 @@
|
||||
# Sony embedded distortion corrections
|
||||
# Sony embedded lens corrections
|
||||
|
||||
LightCraft reads the signed 16-sample distortion table in the raw image IFD (`0x7037`) of
|
||||
Sony **ILCE-7RM4A (A7R IVA)** Bayer ARWs. Other camera models are deliberately left uncorrected,
|
||||
even when they contain a table with the same layout.
|
||||
It converts that table into `OpcodeList3` / `WarpRectilinear`, so the existing profile correction control,
|
||||
CPU/GPU optics path, EXIF orientation handling, and DNG export use the same correction.
|
||||
The **ILCE-7RM6** (A7R VI) has its own conversion, with other conventions measured against its camera JPEGs:
|
||||
[Sony ARW lens corrections](sony-ilce7rm6-lens-corrections.md). On ILCE-7RM6 photos the formula below misses the 24–70 GM II by
|
||||
up to 1.43 px at 1440 px while fitting the 100 mm and 200–600 better, and no single unit fits every lens under either
|
||||
convention; that page's *Two conventions* section has the comparison and what would settle it.
|
||||
|
||||
This adds **distortion only**. Sony vignetting and lateral chromatic-aberration tables are not decoded.
|
||||
The enabled and independently validated model is ILCE-7RM4A with the FE 24–105mm F4 G OSS and
|
||||
FE 200–600mm F5.6–6.3 G OSS. Linear YCbCr ARWs and non-3:2 camera crops are excluded pending validation. An aspect crop may
|
||||
retain the full-frame radial normalization; the decoder does not guess that relationship. Older files that carry
|
||||
only encrypted correction metadata, different table lengths, and rejected tables remain uncorrected.
|
||||
The camera's distortion Off setting does not erase its table. Newly imported photos use LightCraft's existing
|
||||
embedded-profile default (enabled); the profile correction control can disable or adjust it.
|
||||
Sony ARWs record three lens corrections per shot in the raw image IFD: shading (vignetting), lateral chromatic
|
||||
aberration (CA) and distortion, each as a camera setting and a radial table, with copies in the encrypted
|
||||
`SR2SubIFD`. LightCraft **decodes all three** wherever a file carries them and **applies one**: the distortion table
|
||||
of the **ILCE-7RM4A (A7R IVA)** in Bayer ARWs with native 3:2 framing, independently validated with the
|
||||
FE 24–105mm F4 G OSS and FE 200–600mm F5.6–6.3 G OSS (the ILCE-7RM6's distortion is applied too, by its own
|
||||
conversion above). Every other model,
|
||||
and shading and CA on every model, are decoded only: no warp, vignetting or CA correction is added for them. The decoded record stays with the image
|
||||
(`RawInfo::lens_metadata` / `RawImage::lens_metadata`, types in `crates/raw/src/lens_metadata.rs`, decoder in
|
||||
`crates/raw/src/vendor/arw_lens.rs`) for diagnostics and for the validation work described below.
|
||||
|
||||
The applied distortion is converted into `OpcodeList3` / `WarpRectilinear`, so the existing profile correction
|
||||
control, CPU/GPU optics path, EXIF orientation handling, and DNG export use the same correction. Linear YCbCr ARWs
|
||||
and non-3:2 camera crops are excluded pending validation. An aspect crop may retain the full-frame radial
|
||||
normalization; the decoder does not guess that relationship. Tables of other lengths and rejected tables remain
|
||||
uncorrected, and a table found only in the encrypted `SR2SubIFD` is never applied. The camera's distortion Off
|
||||
setting does not erase its table. Newly imported photos use LightCraft's existing embedded-profile default
|
||||
(enabled); the profile correction control can disable or adjust it.
|
||||
|
||||
## What is decoded
|
||||
|
||||
| Component | Raw-IFD setting / table | `SR2SubIFD` setting / table | Accepted layout |
|
||||
|---|---|---|---|
|
||||
| Shading | `0x7031` / `0x7032` | `0x797c` / `0x797d` | SHORT\[1\]; SSHORT\[17\]: 16, then 16 samples |
|
||||
| Lateral CA | `0x7034` / `0x7035` | `0x797f` / `0x7980` | SHORT\[1\]; SSHORT\[33\]: 32, then two 16-sample curves |
|
||||
| Distortion | `0x7036` / `0x7037` | `0x7981` / `0x7982` | SHORT\[1\]; SSHORT\[17\]: 16, then 16 samples |
|
||||
|
||||
- **Bounded, exact reading.** A raw-IFD field is the one the TIFF reader parsed, the copy the image itself uses:
|
||||
its first occurrence, within the reader's limits (8,192 entries per directory, a total value budget). The directory
|
||||
is also scanned, in either byte order and in BigTIFF, for diagnostics only: a tag that occurs more than once is
|
||||
flagged (`raw_ifd_repeated`, `sr2_repeated`), and an entry the reader left out is reported with its reason (values
|
||||
outside the file, an unknown type, or past the reader's limits) rather than treated as absent. `SR2SubIFD` fields
|
||||
are read straight from their first entry. A setting may also be a nonnegative SSHORT (the documented editor type
|
||||
differs from the type the cameras store). Anything else is refused with its reason (`SonyFieldError`: field type,
|
||||
count, leading sample count, values outside the file or block, past the reader's limits, a negative setting).
|
||||
Nothing is allocated from a count in the file.
|
||||
- **Raw IFD first, `SR2SubIFD` as a checked fallback.** The raw IFD's copy wins. The `SR2SubIFD`'s copy is used only
|
||||
when the raw IFD lacks the tag; a malformed raw-IFD copy is reported, never silently replaced. When both copies are
|
||||
well-formed their agreement is recorded (`copies_agree`), and on disagreement the raw IFD's copy is used. The block
|
||||
is decrypted (by the existing `vendor/sr2.rs`) for every ARW that has one, so the check always runs; a block that
|
||||
can't be found or decrypted gives no copies. Locating it selects the `SR2Private` directory's offset, length and
|
||||
key exactly as the TIFF reader would (the reader's own directory layout, 8,192-entry limit, readable-entry rules
|
||||
and value budget, then the first readable occurrence of each), but decodes only each field's first value, so the
|
||||
directory's other entries cost no memory however large they claim to be; the block itself is limited to 1 MiB. The
|
||||
plain tag numbers are not looked up inside the `SR2SubIFD`.
|
||||
- **Settings keep their number and a documented meaning:** shading 256 Off, 257 and 272 Auto, 511 unavailable; CA
|
||||
0 Off, 1 Auto, 255 unavailable; distortion 0 Off, 1 Auto, 17 Auto fixed by the lens, 255 unavailable. Any other value
|
||||
is `Unknown(value)`, never Off (the A7CR's Low shading setting has no documented number). Values are not read as
|
||||
bit masks. Off does not mean absent: the table is still recorded.
|
||||
- **Only the 16-sample (CA: 2 × 16) layout is interpreted.** Many bodies store 11 (CA: 22) samples padded into the
|
||||
same 17 (33) values: older compacts and bodies such as the DSC-RX100 III and ILCE-3500, and the ILCE-7M4's APS-C
|
||||
captures (its full-frame captures carry 16). Those tables are refused as `CountPrefix(11)` and stay
|
||||
uninterpreted. An all-zero table is kept: it is a valid no-op, not a sign of an unsupported lens.
|
||||
- **Framing evidence travels with the tables:** the stored frame (padding included), Sony's crop tags and the DNG
|
||||
default crop as recorded, the image crop, the reference rectangle the distortion conversion is centred on and
|
||||
normalized to (the default crop when present, else the image crop), compression, whether the data is linear
|
||||
YCbCr (lossless M/S), and whether both crops are native 3:2.
|
||||
- **Per-component status.** `Applied` (converted into an opcode), `NoTable`, `NotValidatedComponent` (shading and CA
|
||||
on every body), `NotValidatedModel`, `NotValidatedMode` (linear YCbCr, non-3:2 framing, or a distortion table found
|
||||
only in the `SR2SubIFD`), `Neutral` (all-zero table in the validated scope) and `Rejected` (the validated
|
||||
conversion refused the table). A readable table never implies a usable correction; only `Applied` components
|
||||
become opcodes.
|
||||
|
||||
The applied path is unchanged: the validated conversion still receives the raw IFD's `0x7037` table exactly as the
|
||||
TIFF reader parsed it, with the same model, framing and fit checks, and produces the same warp. A repeated tag keeps
|
||||
the reader's choice and is only flagged, and a table the reader never reads (past its entry limit) is reported but
|
||||
never applied, so already-catalogued photos, their previews and their stored lens data stay consistent with a fresh
|
||||
decode.
|
||||
|
||||
## What each component still needs
|
||||
|
||||
The following summarizes an investigation on the ILCE-7CR (A7CR): an owner's collection of 131 raws with four
|
||||
lenses (Voigtländer APO-LANTHAR 28mm F2 and 50mm F2, both manual focus; Sony FE 24–50mm F2.8 G; Tamron 35–150mm
|
||||
F2–2.8), plus the three public raw.pixls.us A7CR samples. No private photographs, names or derived images are
|
||||
part of this repository.
|
||||
|
||||
- **Inventory.** All 131 raws carry all three tables in both the raw IFD and the `SR2SubIFD`, and the copies agree
|
||||
in every file; all four lenses provide tables, the manual-focus ones included. Shading is 272 (Auto) and CA 1
|
||||
(Auto) everywhere; distortion is 17 (Auto, fixed by the lens) on the nine FE 24–50 files and 0 (Off) on the rest.
|
||||
Every image crop is 9504 × 6336 at (32, 20), in uncompressed, compressed and lossless-L (padded to 9728 × 6656)
|
||||
storage. The decoder reproduces this inventory exactly (see *Local inventory check*).
|
||||
- **Distortion.** The table layout and crop tags match the A7R IVA's, but its interpretation applied unchanged does
|
||||
not reproduce the A7CR camera JPEG at 24 mm: at 2376 px wide, median / 95th-percentile feature residuals were
|
||||
1.61 / 6.17 px (12.98 / 51.19 px uncorrected, 6,539 matches), with a signed radial pattern (about +1.7 px at
|
||||
radii 0.25–0.5, −7.4 px at 0.8–1) that no translation removes. At 50 mm it agrees (0.23 / 1.05 px, from
|
||||
2.21 / 12.25 px). Scaling the raw table by about 10/9, or using the MakerNote's distortion array instead, brings
|
||||
24 mm to about 0.37 / 1.10 and 0.33 / 0.97 px. Those are exploratory comparisons on two files against the camera
|
||||
JPEG, not a model: the MakerNote values are roughly 1.11 times the raw table without one exact ratio, and the
|
||||
A7R IVA was validated against a different reference renderer (Imaging Edge exports). Needed: A7CR Imaging Edge
|
||||
On/Off exports at 24 and 50 mm and with another lens, compared with the raw table at its fixed scale; a decision on
|
||||
the reference (camera JPEG or Imaging Edge); then ILCE-7CR added to the validated models for the full-frame Bayer
|
||||
3:2 mode only. Neither a 10/9 multiplier nor the MakerNote table is used.
|
||||
- **Shading.** The layout decodes, but no public specification gives the sample-to-gain function, its radius
|
||||
convention on the A7CR, or whether the raw samples already contain part of the correction. Brightness ratios on six
|
||||
natural scenes show no consistent missing peripheral brightening. Needed: evenly lit flat fields with shading
|
||||
Off / Auto / Low at several apertures and focal lengths, raw CFA ratios between them, and Imaging Edge On/Off
|
||||
exports, to fix the gain function and processing stage and rule out double correction.
|
||||
- **Lateral CA.** A public analysis reads the table as a red, then a blue curve relative to green, at a 2⁻²¹
|
||||
relative radial scale. On three distortion-Off files that candidate reduced red and blue feature residuals
|
||||
modestly (for example 0.35 → 0.29 px median for red with the 28 mm), which supports investigating it but certifies
|
||||
neither scale, interpolation nor processing stage. Two product changes come before it: embedded CA must be
|
||||
independent of the distortion amount (today `pipeline::optics` scales the whole embedded per-plane warp with the
|
||||
profile distortion control), and the red and blue planes must be resampled in camera RGB, before the camera colour
|
||||
model mixes them (`engine::files::load_bytes_now` applies the colour model before the optics stage). Then
|
||||
validation on full-resolution achromatic edges.
|
||||
- **Other modes.** APS-C, aspect crops and lossless M/S (linear YCbCr) captures were not measured and stay
|
||||
excluded.
|
||||
|
||||
## Local inventory check
|
||||
|
||||
`crates/raw/tests/sony_lens_inventory.rs` is opt-in and does nothing in CI. With `LIGHTCRAFT_SONY_LENS_DIR` naming a
|
||||
directory of ARWs it decodes each from its headers and prints its record (settings, sources, copies' agreement,
|
||||
sample ranges, statuses); `LIGHTCRAFT_SONY_LENS_FULL=1` also compares header and full decode. With
|
||||
`LIGHTCRAFT_SONY_LENS_INVENTORY` naming a CSV inventory it checks every file's table counts, sizes, sample counts,
|
||||
minima and maxima, raw-IFD versus `SR2SubIFD` agreement, settings (numbers and labels), stored size, compression and
|
||||
crop tags. A file with a row must decode, and every file must have a row, whether it decodes or not. Any decode
|
||||
error fails the check except an unsupported variant, which is counted and must equal `LIGHTCRAFT_SONY_LENS_UNSUPPORTED`
|
||||
(default 0). On the 131 A7CR raws above, all 131 inventory rows reproduce and every file decodes. On 133 public Sony
|
||||
ARWs (127 raw.pixls.us samples from 100 bodies, four corpus copies and two files attached to a public issue), 110 carry
|
||||
a record, 14 decode without one, and 9 are unsupported variants (eight packed ARWs of older bodies and one ARW
|
||||
without a CFA image); header and full decode agree on the 124 that decode, and no record has disagreeing copies.
|
||||
|
||||
## Clean-room evidence
|
||||
|
||||
The [ExifTool EXIF tag-name documentation](https://exiftool.org/TagNames/EXIF.html) identifies
|
||||
`0x7037` as 17 signed 16-bit integers. The first value is the count, 16, followed by radial samples.
|
||||
No external photo decoder implementation or Adobe lens profile was consulted.
|
||||
Sony Imaging Edge Edit 4.1 was used only as a black-box reference on local scratch copies.
|
||||
The [ExifTool EXIF tag-name documentation](https://exiftool.org/TagNames/EXIF.html) names the raw-IFD tags
|
||||
`0x7031` to `0x7037` (VignettingCorrection / VignettingCorrParams, ChromaticAberrationCorrection /
|
||||
ChromaticAberrationCorrParams, DistortionCorrection / DistortionCorrParams) with their setting values, and gives the
|
||||
tables as 17 or 33 signed 16-bit integers whose first value is the count. The
|
||||
[Sony SR2SubIFD documentation](https://exiftool.org/TagNames/Sony.html#SR2SubIFD) names the encrypted copies
|
||||
`0x797d`, `0x7980` and `0x7982`; the setting tags next to them (`0x797c`, `0x797f`, `0x7981`) are unnamed there and
|
||||
were identified by inspecting files, where they equal the raw-IFD settings. The corpus test's expected tables are the
|
||||
values ExifTool, run as a black-box tool, prints for the public samples. No external photo decoder implementation,
|
||||
lens database or Adobe lens profile was consulted. Sony Imaging Edge Edit 4.1 was used only as a black-box reference
|
||||
on local scratch copies.
|
||||
|
||||
The observed inverse mapping, with radius `r` normalized to the default crop's half diagonal, is:
|
||||
|
||||
@@ -45,7 +163,8 @@ so the warp stays on the optical centre either way. On the A7R IVA that framing
|
||||
pixels left of Sony's exports (eight pixels in a 2376-pixel-wide export).
|
||||
|
||||
The main raw-IFD table is important: the similarly named MakerNote table has different values and
|
||||
must not be substituted into this formula. Main raw-IFD and SR2SubIFD values agreed in the test files.
|
||||
must not be substituted into this formula. Main raw-IFD and SR2SubIFD values agreed in the test files, and the
|
||||
`SR2SubIFD` copy is never converted.
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -90,7 +209,18 @@ The distortion geometry remains aligned while every body's image framing follows
|
||||
|
||||
Tests cover signedness/length rejection, zero and malformed tables, independent 600 mm reference
|
||||
geometry, barrel framing, offset crop normalization, both TIFF byte orders, header/full consistency,
|
||||
and preservation through DNG export. No private photographs or reference TIFFs are committed.
|
||||
and preservation through DNG export. The decoder's synthetic tests (`crates/raw/src/vendor/arw_lens.rs`) add both
|
||||
byte orders and BigTIFF, exact SHORT / SSHORT types, negative samples, missing, short, long, huge and zero counts,
|
||||
wrong leading counts, values outside the file, a table past the TIFF reader's entry limit (not applied), repeated
|
||||
tags (the reader's copy kept, as before), unknown and negative settings, raw-IFD versus
|
||||
`SR2SubIFD` precedence and agreement, the correct `SR2SubIFD` tag numbers, a wrong decryption key, hostile entries
|
||||
inside the decrypted block, linear YCbCr, framing evidence (Sony's crop at x = 0 against the default crop, agreeing
|
||||
crops, padded storage, aspect crops, crop tags outside the frame), all eight EXIF orientations leaving the record
|
||||
unchanged, and neutral, out-of-range and folding tables. On a small classic-TIFF fixture in both byte orders, every
|
||||
truncation and four mutations of each byte outside the pixel data (set to 0x00 and 0xff, top and low bit flipped)
|
||||
decode or fail without a panic. `tests/sr2_heap.rs` measures the peak heap of decoding a 16 MiB file whose
|
||||
`SR2Private` directory holds eight fields aliasing the whole file: 37 kB, against 134 MB when those fields were
|
||||
decoded. No private photographs or reference TIFFs are committed.
|
||||
|
||||
## Camera coverage and regression boundary
|
||||
|
||||
@@ -99,27 +229,35 @@ model names, and every other model remain unsupported by this distortion decoder
|
||||
numbers and table lengths do not establish the scale, interpolation or crop normalization on another
|
||||
body. Support can expand after independent geometry validation; do not add model-name prefix matching.
|
||||
|
||||
The current `cargo xtask corpus --download` manifest contains 23 Sony CC0 samples across 17 bodies,
|
||||
including samples 4822 (A7R IVA / 24–105 mm) and 3989 (A9 II / 200–600 mm). All 23 files have
|
||||
pinned SHA-256 hashes and are checked with `sony_embedded_distortion_is_limited_to_validated_models`:
|
||||
The current `cargo xtask corpus --download` manifest contains 25 Sony CC0 samples across 18 bodies,
|
||||
including samples 4822 (A7R IVA / 24–105 mm) and 3989 (A9 II / 200–600 mm), each with a pinned SHA-256 that the
|
||||
download checks. `sony_embedded_distortion_is_limited_to_validated_models` checks 23 of them (the two ILCE-7CM2
|
||||
codings have their own test), and `sony_lens_records_of_the_public_samples` verifies all 25 against their pins
|
||||
(`SONY_SAMPLES` in `crates/raw/tests/corpus.rs`, itself anchored by a pinned digest and compared with the manifest)
|
||||
before decoding. **No CI job fetches the corpus**: these fixture tests run only where it has been downloaded, and
|
||||
otherwise skip each absent file. `LIGHTCRAFT_CORPUS_REQUIRED=1` makes `sony_lens_records_of_the_public_samples`
|
||||
fail on any absent pinned file instead.
|
||||
|
||||
| Camera | Corpus samples | Raw-IFD table observed | Expected correction |
|
||||
| Camera | Corpus samples | Decoded record: tables, settings (shading / CA / distortion) | Applied |
|
||||
|---|---|---|---|
|
||||
| ILCE-7RM4A | Compressed (4822) | 16 samples | One distortion warp |
|
||||
| ILCE-9M2 | Compressed (3989) | 16 samples | None |
|
||||
| ILCE-7M3 | Compressed, uncompressed | 16 samples | None |
|
||||
| ILCE-7M4 | 14-bit, lossless L/M/S | 11 samples in the 14-bit file; 16 in L/M/S | None |
|
||||
| ILCE-7RM2 | 12-bit uncompressed | 16 samples | None |
|
||||
| DSC-RX100 | One | No raw-IFD table | None |
|
||||
| DSC-RX100M3 | One | 11 samples | None |
|
||||
| ILCE-7CR | Compressed, lossless L/M | Not used; model excluded | None |
|
||||
| ILCE-7RM4 | 14-bit compressed | Not used; model excluded | None |
|
||||
| DSLR-A500, DSLR-A700, SLT-A33 | One each | Not used; model excluded | None |
|
||||
| ILCE-3500, ILCE-7S | 5600 K, Shade respectively | Not used; model excluded | None |
|
||||
| ILCE-7SM2, DSLR-A580 | 16:9 framing, one each | Not used; model excluded | None |
|
||||
| DSLR-A900 | Packed 12-bit | Not used; model excluded | None |
|
||||
| ILCE-7RM4A | Compressed (4822) | All three tables; 257 / 1 / 17 | One distortion warp |
|
||||
| ILCE-9M2 | Compressed (3989) | All three; 257 / 1 / 0 | None |
|
||||
| ILCE-7M3 | Compressed, uncompressed | All three; 257 / 1 / 0 | None |
|
||||
| ILCE-7M4 | 14-bit, lossless L/M/S | L/M/S: all three, 272 / 1 / 17; the 14-bit file (APS-C framing, 4608 × 3072): settings only, its 11-sample tables are not interpreted | None |
|
||||
| ILCE-7RM2 | 12-bit uncompressed | All three; 256 / 0 / 1 | None |
|
||||
| DSC-RX100 | One | Shading, from the `SR2SubIFD` (the raw IFD has no tables); CA and distortion in the 11-sample layout | None |
|
||||
| DSC-RX100M3 | One | Shading; CA and distortion in the 11-sample layout | None |
|
||||
| ILCE-7CR | Compressed, lossless L/M | All three; 272 / 1 / 0 | None |
|
||||
| ILCE-7RM4 | 14-bit compressed | All three; 257 / 1 / 17 | None |
|
||||
| ILCE-3500 | 5600 K | Settings only (unavailable) | None |
|
||||
| ILCE-7S | Shade | An all-zero CA table; settings unavailable | None |
|
||||
| ILCE-7SM2 | 16:9 framing | All-zero shading and CA tables; settings unavailable | None |
|
||||
| DSLR-A500, DSLR-A700, SLT-A33, DSLR-A580, DSLR-A900 | One each | No record | None |
|
||||
|
||||
These are **model-boundary regression checks, not new geometric validation of those models**. In particular,
|
||||
These are **model-boundary regression checks, not new geometric validation of those models**.
|
||||
`sony_lens_records_of_the_public_samples` also checks the exact tables, settings, provenance and framing evidence of
|
||||
the three A7CR codings and the A7R IVA sample, and that across the Sony corpus only the A7R IVA's distortion is ever
|
||||
applied. In particular,
|
||||
refusing the A7 III tables resolves the unverified corner warp identified in review. The lossless M/S
|
||||
files are linear YCbCr and remain excluded independently of the model check. Header and full decode
|
||||
must agree for every sample. Synthetic tests also verify both TIFF byte orders, exact model matching,
|
||||
|
||||
+34
-24
@@ -1,6 +1,6 @@
|
||||
# Target-app parity: LightCraft vs Adobe Lightroom
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-14 · **Change:** minor (gap 4 closed: full-resolution zoom; headline numbers unchanged) · **Target:** Adobe Lightroom Classic 15.5 (August 2026) and Lightroom 9.6 (desktop)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-15 · **Change:** minor (RAW: 83% of Adobe's models decode, 38% verified after the camera-coverage sweep #1327) · **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
|
||||
@@ -12,11 +12,11 @@ have their own documents: [raw-parity.md](raw-parity.md), [file-format-parity.md
|
||||
|
||||
| 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**, checklist | **81.6%** of 532 in-scope rows (P0 98.0%, P1 95.2%, P2 50.0%) | **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 |
|
||||
| **Mainstream practitioner** | **~51%** (range 46–56%) | estimated: weekly areas of a working photographer, depth 74.0% × 0.804 × colour 0.85 |
|
||||
| **Essentials user** | **~65%** (range 60–70%) | estimated: core features at default settings, depth 78.0% × 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) |
|
||||
@@ -47,11 +47,11 @@ phase #85, duplicate Local entries #22, black GPU exports on an Intel iGPU #78).
|
||||
| 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% | 34–58 h | [ui-parity.md](ui-parity.md) |
|
||||
| ↳ RAW cameras, colour and lens profiles (part of features) | 83% of Adobe's 1,446 models decode (38% verified), measured | ~56% | 255–480 h | [raw-parity.md](raw-parity.md) |
|
||||
| UI/UX fidelity | ~85% | ~70% | 32–54 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) |
|
||||
| Localization (12 key languages) | 7 of 12 present | ~55% (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) |
|
||||
@@ -68,18 +68,18 @@ from the checklist sections and the deep-dive documents.
|
||||
|---|---:|---:|---:|---:|---|
|
||||
| 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% | 77% | 120–220 h | [raw-parity.md](raw-parity.md), measured model by model: 85% of photographers' cameras decode (use-weighted), × 0.9 for per-body bugs; CR3 variants, compressed ORF, HE NEF |
|
||||
| Colour, camera profiles, render fidelity | 10% | 65% | 35% | 80–150 h | 4 bundled profiles vs Adobe's 1,500; per-file fits median ΔE ~5 vs the camera JPEG, ~10% far off; no fidelity suite ([raw-parity.md](raw-parity.md#colour)) |
|
||||
| Colour, camera profiles, render fidelity | 10% | 65% | 35% | 80–150 h | 5 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) |
|
||||
| Merge and HDR | 3% | 85% | 60% | 20–35 h | merge 88% (HDR merge 🟡: AI Denoise on merged DNGs, JPEG response, memory; gap 29), 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** | |
|
||||
| **Weighted** | 100% | **~77%** | **~61%** (61.5%) | **600–1,100 h** | |
|
||||
|
||||
## AI
|
||||
|
||||
@@ -90,6 +90,8 @@ search embeddings; generative remove runs in Adobe's cloud.
|
||||
|
||||
| Feature | LightCraft | Status |
|
||||
|---|---|---|
|
||||
| 2026-10-12 | minor | Mamiya MEF decoded (raw-parity.md): 241 verified, 35 unsupported; rounded numbers unchanged |
|
||||
| 2026-10-12 | minor | Epson ERF decoded (raw-parity.md): 240 models verified, 229 preview-only; shares and rounded numbers unchanged |
|
||||
| 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 | 🟡 |
|
||||
@@ -117,8 +119,8 @@ work. Each has its own hours to ~95%, calibrated as in [How hours are calibrated
|
||||
| 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 |
|
||||
| Mainstream practitioner | **~51%** | **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 | **~65%** | **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%
|
||||
|
||||
@@ -129,17 +131,17 @@ 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% | 77% (85% use-weighted × 0.9) |
|
||||
| RAW decoding and camera coverage | 9% | 83% (92% 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% |
|
||||
| Localization | 3% | 55% |
|
||||
| Performance | 6% | 70% |
|
||||
| Stability | 8% | 60% |
|
||||
| Platforms | 4% | 60% |
|
||||
| Ecosystem / plug-ins | 2% | 15% |
|
||||
| **Weighted sum** | 100% | **60.7% ≈ 61%** (range 56–66%) |
|
||||
| **Weighted sum** | 100% | **61.2% ≈ 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
|
||||
@@ -160,7 +162,7 @@ essentials replaces its guessed 45% raw look with 84% × 0.75 (+1 point).
|
||||
| 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%
|
||||
### Mainstream practitioner: ~51%
|
||||
|
||||
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,
|
||||
@@ -171,20 +173,20 @@ than the user's own.
|
||||
|---|---:|---:|
|
||||
| Import and library | 18% | 80% |
|
||||
| Cull: views, compare, zoom, ratings | 12% | 70% |
|
||||
| Raw decoding for their camera | 27% | 85% (measured use-weighted share whose camera fully works, [raw-parity.md](raw-parity.md#by-use-estimated)) |
|
||||
| Raw decoding for their camera | 27% | 92% (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% | **72.1%** |
|
||||
| **Weighted depth** | 100% | **74.0%** |
|
||||
|
||||
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). 72.1% × 0.804 × 0.85 = **~49%** (range 44–54%).
|
||||
corrects colour by hand (33 open colour issues). 74.0% × 0.804 × 0.85 = **~51%** (range 46–56%).
|
||||
|
||||
### Essentials user: ~64%
|
||||
### Essentials user: ~65%
|
||||
|
||||
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.
|
||||
@@ -199,11 +201,11 @@ basic sliders, crop, apply a preset, undo, export JPEGs.
|
||||
| Crop and straighten | 10% | 80% |
|
||||
| Presets and profiles | 8% | 80% |
|
||||
| Undo and history | 5% | 90% |
|
||||
| Their camera's raws: decode × default look | 10% | 64% (85% whose camera fully works × colour factor 0.75) |
|
||||
| Their camera's raws: decode × default look | 10% | 69% (92% whose camera fully works × colour factor 0.75) |
|
||||
| Export JPEG | 10% | 85% |
|
||||
| **Weighted depth** | 100% | **77.5%** |
|
||||
| **Weighted depth** | 100% | **78.0%** |
|
||||
|
||||
77.5% × 0.830 = **~64%** (range 59–69%).
|
||||
78.0% × 0.830 = **~65%** (range 60–70%).
|
||||
|
||||
### User evidence (GitHub issues, excluding the four maintainers)
|
||||
|
||||
@@ -257,7 +259,7 @@ verification. Calibrated on this repository's history (git log and GitHub PR ope
|
||||
(#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).
|
||||
13.8 h (#267).
|
||||
- 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.
|
||||
|
||||
@@ -274,6 +276,7 @@ most of its list; what remains is the data-heavy part (colour, lenses, models) i
|
||||
|
||||
| Date | Checklist (all / P0 / P1 / P2) | Ready for real work | Remaining to full parity | Source |
|
||||
|---|---|---|---|---|
|
||||
| 2026-10-12 | 81.1% (unchanged) | ~61% full · ~51% mainstream · ~65% essentials | unchanged | 22 more CR3 bodies verified (raw-parity.md) |
|
||||
| 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) |
|
||||
@@ -297,11 +300,18 @@ P2 items 12–25 h; look tuning, performance, packaging, hardening 25–45 h.
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-14 | minor | Localization ~52% → ~55% (mean of the 12 key languages): de, es, fr, ja and uk catalogs filled |
|
||||
| 2026-10-12 | minor | UI/UX remaining 34–58 h → 32–54 h (canvas tools by keyboard); headline numbers unchanged |
|
||||
| 2026-10-14 | minor | Merge and HDR: merge 100% → 88% (LR-MERGE-HDR ✅ → 🟡 after testing on real 67 MP brackets; gap 29); area percentages unchanged |
|
||||
| 2026-10-14 | minor | Gap 4 (full-resolution zoom) closed: removed from the interaction-fidelity notes, the alpha-gate partial rows and the beta needs; headline numbers and the ×0.95 interaction factor unchanged |
|
||||
| 2026-10-12 | minor | UI/UX remaining 40–70 h → 34–58 h (accessibility audit landed, ui-parity.md); percentages unchanged |
|
||||
| 2026-10-14 | minor | Camera-coverage sweep (#1327): 30 models verified on 40 CC0 files (`coverage_sweep_corpus.rs`, `coverage-sweep.tsv`; `docs/raw/coverage.py` 515 → 545 verified rows); the counts above are not re-measured here. Sensor verification does not establish colour parity (#1277); headline numbers unchanged |
|
||||
| 2026-10-12 | minor | 22 more CR3 bodies verified on one CC0 file each (raw-parity.md): use-weighted share whose camera decodes 85% → 92%, RAW decoding 77% → 83%; full 60.7% → 61.2% (~61%), mainstream depth 72.1% → 74.0% (~49% → ~51%), essentials depth 77.5% → 78.0% (~64% → ~65%) |
|
||||
| 2026-10-12 | minor | 117 Nikon and Fujifilm bodies verified (raw-parity.md): use-weighted share whose camera decodes 85% → 86%, RAW decoding 77% (unchanged); mainstream depth 72.1% → 72.4%, essentials depth 77.5% → 77.6%; headline numbers unchanged |
|
||||
| 2026-10-11 | minor | EOS R5 Mark II CR3 verified (raw-parity.md): use-weighted share whose camera decodes 84% → 85%, RAW decoding 76% → 77%; full 60.6% → 60.7%, mainstream depth 71.8% → 72.1%, essentials depth 77.4% → 77.5%; the rounded numbers (~61%, ~49%, ~64%) are unchanged |
|
||||
| 2026-10-10 | minor | RAW measured model by model (raw-parity.md): RAW decoding (76%) and colour (35%) are explicit rows of the full sum (59% → 61%); mainstream uses the use-weighted 84% plus a ×0.85 colour discount (51% → 49%); essentials uses 84% × colour 0.75 (63% → 64%); beta ~14 points |
|
||||
| 2026-10-10 | minor | Full number restored to an additive weighted sum over the dimensions (~59%; method aligned with the standard, no new evidence); hours to ~95% for each of the three audiences; beta distance ~16 points |
|
||||
| 2026-10-10 | minor | Added mainstream practitioner (~51%) and essentials user (~63%) numbers; full ready re-derived from written weights × discounts (55% → 46%); user-issue evidence; beta hours 340–600 |
|
||||
| 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* |
|
||||
| 2026-10-14 | minor | RAW: 82% of Adobe's models decode, 36% verified (integration batch 36) |
|
||||
|
||||
+40
-9
@@ -1,6 +1,6 @@
|
||||
# UI parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-14 · **Change:** minor (zoom row: diagnostic overlays sharp at 1:1); previously minor (zoom row: soft proofing sharp at 1:1) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-14 · **Change:** minor (zoom row: diagnostic overlays and soft proofing sharp at 1:1; canvas tools by keyboard; focus-order test; ~50 unnamed hand-drawn widgets named) · **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
|
||||
@@ -32,11 +32,11 @@ assessment and the notes that don't fit a row. Visual reference for agents: `pla
|
||||
| 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 tree audited by a test in every view, Develop tool and the main dialogs: every control named, sliders with value, range and Increment / Decrement, dialogs titled, tool sliders reachable with Tab | 55% | crop handles, spot and mask placement on the canvas still need the pointer; not tried with a real screen reader ([audit](#accessibility-audit)) |
|
||||
| Accessibility | VoiceOver / Narrator, keyboard navigation | AccessKit tree audited by a test in every view, Develop tool and the main dialogs: every control named, sliders with value, range and Increment / Decrement, dialogs titled, tool sliders reachable with Tab; crop handles, spots, gradient handles and mask pins by keyboard | 75% | brush strokes and red-eye ellipses need the pointer; not tried with a real screen reader ([audit](#accessibility-audit)) |
|
||||
| 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: **34–58 h** (zoom detail 8–15 h, brush and masking feel 8–12 h, accessibility 4–8
|
||||
Remaining: **32–54 h** (zoom detail 8–15 h, brush and masking feel 8–12 h, accessibility 2–4
|
||||
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).
|
||||
|
||||
@@ -60,17 +60,21 @@ under the UI command that wraps it (a no-op error); the UI command now wins.
|
||||
| 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 |
|
||||
| Hide / show pins (Tool Overlay) | ⇧H (cycles Auto, Always, Selected, Never) | H (Classic) | H opens Remove; View ▸ Tool Overlay and the Remove / Masking panels pick a mode |
|
||||
| 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.
|
||||
**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. `` ` `` cycles the flag (unflagged → pick → reject → unflagged) and ⌘↑ / ⌘↓ raise / lower it; the native menu leaves ⌘↑ / ⌘↓ to egui so Compare/Survey act on the active photo. Remaining Classic gaps: filter-bar keys.
|
||||
|
||||
**Grid thumbnail size (KEYC-COMPARE):** Classic's `=` and `-` increase and decrease the Grid thumbnail size (same keys on macOS and Windows; `+` also works for the larger size here, as Shift+`=` or the keypad). They step the bottom-bar slider by 30 pt inside its 90–480 pt range, in Photo Grid, Square Grid and People only; Detail, Compare, Survey and Reference ignore them, and ⌘= / ⌘− stay Zoom In / Out. See [library shortcuts](library-shortcuts.md).
|
||||
|
||||
**Library navigation keys (KEYC-COMPARE):** in Photo Grid and Square Grid, `Home` / `End` make the first / last photo of the view the active, selected one, and `Shift+Left` / `Shift+Right` add the previous / next photo of the view to the selection (the added photo becomes active; the keys never remove a photo from the selection, and do nothing at either end of the view). They wait in the other views, in the full-screen preview, while a text field or a dialog has the keyboard, and when you gave the key to a command; they are listed under Fixed keys in Help → Keyboard Shortcuts. `Cmd+O` (`Ctrl+O` on Windows and Linux) runs File → Open Library… ; View → Visualize HDR has no default key (`Shift+H` cycles the Tool Overlay, issue #224; `Cmd+Shift+H` stays the Histogram). Covered by `crates/ui-egui/src/tests_keymap.rs`; the macOS native menu path for `Cmd+O` is not exercised by the headless tests.
|
||||
|
||||
**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).
|
||||
|
||||
|
||||
@@ -96,16 +100,43 @@ Found and fixed (2026-10-12): 47 problems in the views and tools, 11 more in the
|
||||
- Auto Stack's time slider had no name.
|
||||
|
||||
Keyboard reach: Crop (angle, offsets, scale, aspect) and Remove (size, feather, opacity) settings
|
||||
are reached with Tab and adjusted with the arrow keys (tested). Still pointer-only: dragging crop
|
||||
handles, placing a spot or a brush stroke, and moving a mask pin on the canvas. Not done: a session
|
||||
with a real screen reader on each platform, and focus order (egui follows drawing order: top bar,
|
||||
left panel, canvas, right panel, which is sensible but not tuned).
|
||||
are reached with Tab and adjusted with the arrow keys (tested).
|
||||
|
||||
Canvas tools by keyboard (`crates/ui-egui/src/canvas_keys.rs`, tests in `tests_canvas_keys.rs`):
|
||||
every handle drawn on the photo has an invisible stand-in that takes the focus. Tab reaches it, a
|
||||
screen reader reads its name and position ("Crop bottom-right corner", "left 0%, top 0%, right
|
||||
100%, bottom 100%"; "Spot 1", "x 30%, y 60%, size 5%"), and the arrow keys move it by 0.5% of the
|
||||
photo (Shift: 5%), one undo step per press. While it has the focus it keeps the arrows, Return
|
||||
and Space, and the app's other shortcuts still work.
|
||||
- Crop: four corners, four edges and the whole box (`crop.drag`, so the aspect lock and image
|
||||
bounds apply as they do for a drag); Return applies the crop.
|
||||
- Remove: each spot's target and source; a "New spot" point that starts at the centre, moves
|
||||
with the arrows, and turns into a spot of the brush's size when you press Return.
|
||||
- Masking: the four edges and the rotation handle of a radial gradient, the start and end of a
|
||||
linear one, and each mask pin (moving one selects its mask).
|
||||
|
||||
Focus order: the audit now also counts any widget that takes the focus or a click, whatever its
|
||||
role. That found about 50 hand-drawn icons, tiles and rows with no name: top-bar icons, flags and
|
||||
stars, filmstrip and survey tiles, preset and profile rows, curve channels, colour wheels, mask
|
||||
tiles and rows, slider labels and readouts. They are now announced as buttons. A test walks Tab
|
||||
through the Edit, Crop, Remove and Masking panels and checks that it goes top to bottom (the tool
|
||||
strip beside them is its own column, walked first). No reordering was needed once nothing
|
||||
unnamed was in the way.
|
||||
|
||||
Not done: brush strokes and red-eye ellipses still need a pointer. Nobody has tried the app with
|
||||
a real screen reader on any platform yet.
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-14 | minor | Zoom row: diagnostic overlays render zoom windows too |
|
||||
| 2026-10-14 | patch | Shortcuts: Visualize HDR loses its default ⇧H, which cycles the Tool Overlay (issue #224); both PRs had claimed it |
|
||||
| 2026-10-12 | minor | Accessibility: crop handles, spots, gradient handles and mask pins operable by keyboard with AccessKit names and values; Tab order test for the right panels; hand-drawn icons and rows named; 55% → 75%; UI remaining 34–58 h → 32–54 h |
|
||||
| 2026-10-13 | minor | Shortcuts: Tool Overlay modes for spot and mask pins on ⇧H (H stays Remove; issue #224), listed with the deliberate differences; dropped from the missing list |
|
||||
| 2026-10-13 | minor | Library culling: backtick cycles the flag; ⌘↑ / ⌘↓ raise / lower flag status |
|
||||
| 2026-10-13 | minor | KEYC-COMPARE: `=` / `-` grid thumbnail size keys noted in the shortcuts section |
|
||||
| 2026-10-13 | minor | Shortcuts: Home / End and Shift+Left / Right in the two library grids, Cmd+O (Open Library…) and Shift+H (Visualize HDR) get bindings and keyboard tests; percentages and the dated counts above are unchanged |
|
||||
| 2026-10-14 | minor | Zoom row: soft proofing gets zoom windows; LR-VIEW-ZOOM gap closed |
|
||||
| 2026-10-12 | minor | Accessibility: an AccessKit tree audit test over every view, Develop tool and 13 dialogs; unnamed fields, slider ranges and the Auto Stack slider fixed; 30% → 55%; UI remaining 40–70 h → 34–58 h |
|
||||
| 2026-10-11 | minor | Zoom row: Compare and Reference get zoom windows; what remains of LR-VIEW-ZOOM is overlays and soft proofing |
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# User docs: rules for agents and contributors
|
||||
|
||||
Everything in this folder (except this file, CLAUDE.md and README.md) is published at
|
||||
https://getartcraft.com/docs/lightcraft. The file path is the URL:
|
||||
`troubleshooting/raw-photos-look-dull.md` → `/docs/lightcraft/troubleshooting/raw-photos-look-dull`.
|
||||
Renaming a file breaks links, so add the old path to `redirect_from` when you rename.
|
||||
|
||||
## Who reads this
|
||||
|
||||
Artists and photographers using LightCraft, Discord mods answering them, and AI assistants looking
|
||||
things up for either. Write for a photographer, not a developer.
|
||||
|
||||
## Page rules
|
||||
|
||||
- One question or problem per page. Lead with the answer or the fix in the first two lines.
|
||||
- Plain words, short sentences, numbered steps for anything the reader does.
|
||||
- Start the body at `##`. The page title comes from frontmatter.
|
||||
- Link to other pages instead of repeating them. Use relative links to the `.md` file:
|
||||
`[Install LightCraft](../getting-started/install.md)`.
|
||||
- No marketing copy, no "simply", no claims you have not checked in the code or a release.
|
||||
- Call the product "LightCraft", as the app, its downloads and getartcraft.com do.
|
||||
- Name UI labels exactly as the app shows them, in **bold**.
|
||||
- Troubleshooting pages: `## Symptoms`, `## Fix`, `## Why this happens` (optional),
|
||||
`## Still stuck?` (link the issue tracker or Discord).
|
||||
|
||||
## Frontmatter
|
||||
|
||||
---
|
||||
title: Raw photos look dull
|
||||
description: One sentence for search results, link previews and AI summaries.
|
||||
order: 10 # optional, sorts within the folder (lower first)
|
||||
verified: 0.6.0 # optional, app version you last checked this page against
|
||||
redirect_from: [old/path] # optional, old URLs (relative to /docs/lightcraft)
|
||||
---
|
||||
|
||||
Only `key: value` and `key: [a, b]` lines work. Quote values that start with a quote or contain ` #`.
|
||||
|
||||
Set `verified` to the latest release (the newest release tag) after checking the page against that tag with `git show <tag>:<path>`. Pages describe the latest release users download, not unreleased code on main.
|
||||
|
||||
## Folders
|
||||
|
||||
- `getting-started/` install and first run
|
||||
- `guides/` how to do one thing
|
||||
- `troubleshooting/` symptom → fix
|
||||
- `faq/` short answers
|
||||
- `reference/` lists and settings
|
||||
|
||||
A folder's `index.md` names the folder in the sidebar. Files or folders starting with `_` are
|
||||
drafts and are not published.
|
||||
|
||||
## Check before you push
|
||||
|
||||
node <path to your artcraft-services checkout>/frontend/apps/artcraft-website-next/scripts/docs/core.mjs docs/user
|
||||
|
||||
The checker lives in storytold/artcraft-services. A CI check will be added once it is on that repo's main branch.
|
||||
|
||||
## Support PRs
|
||||
|
||||
Pages written to answer a user question come in as PRs titled `docs(support): <page title>`.
|
||||
Review them like code: check every claim against the source.
|
||||
@@ -0,0 +1 @@
|
||||
Read `AGENTS.md` in this folder: it has the rules for the user docs.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: Is LightCraft free, and does it need an account?
|
||||
description: LightCraft is free and open source, needs no account or subscription, and keeps your library on your computer.
|
||||
order: 10
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Yes, it is free. LightCraft is open source under the MIT or Apache-2.0 licence, your choice. It needs no account, no cloud service and no subscription, and it sends no telemetry.
|
||||
|
||||
## Where are my photos and edits kept?
|
||||
|
||||
On your computer. Your library lives in a folder you choose, by default `~/Pictures/LightCraft Library`. Edits are non-destructive, so your original files are never touched. The catalog is a log of human-readable operations that you can back up. Use **File** > **Back Up Library…** to make a backup.
|
||||
|
||||
## Which systems does it run on?
|
||||
|
||||
LightCraft runs on Windows, macOS and Linux, and in a web browser. See [Install LightCraft](../getting-started/install.md).
|
||||
|
||||
## Is it finished?
|
||||
|
||||
No. LightCraft is in alpha. Some things from Adobe Lightroom are not there yet, such as on-screen HDR display, video and the Print, Book and Map modules. The project's [roadmap](https://github.com/storytold/lightcraft/blob/main/ROADMAP.md) lists what is missing.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: FAQ
|
||||
description: Short answers about LightCraft, its price, platforms and file support.
|
||||
order: 40
|
||||
---
|
||||
|
||||
- [Is LightCraft free, and does it need an account?](free-and-private.md)
|
||||
- [Which cameras and file types does LightCraft open?](supported-files.md)
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Which cameras and file types does LightCraft open?
|
||||
description: The raw and image formats LightCraft reads, what happens with raws it cannot decode yet, and how to open Lightroom catalogs.
|
||||
order: 20
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
LightCraft reads raw files from DNG, Canon CR2 and CR3, Sony ARW, Nikon NEF, Fujifilm RAF (including X-Trans), Panasonic RW2, Leica RWL, Pentax PEF and Olympus ORF cameras. It also opens JPEG, PNG, TIFF, WebP, PSD composites and JPEG XL.
|
||||
|
||||
## What if my camera is not decoded yet?
|
||||
|
||||
A raw that LightCraft cannot decode opens from the camera's embedded JPEG instead, marked **Preview only**. Compressed Olympus raws, some Canon CR3 variants and Nikon High Efficiency NEF files work this way. See [A raw photo opens as "Preview only"](../troubleshooting/preview-only-raw.md).
|
||||
|
||||
How closely the starting look matches your camera's own JPEG varies by model. See [Raw photos look dull or washed out](../troubleshooting/raw-photos-look-dull.md). The project's [raw support table](https://github.com/storytold/lightcraft/blob/main/docs/raw-parity.md) lists what is known per camera.
|
||||
|
||||
## Can I open my Lightroom photos?
|
||||
|
||||
Yes. LightCraft imports Lightroom Classic catalogs. See [Move over from Lightroom](../guides/import-lightroom-catalog.md).
|
||||
|
||||
## What can I export?
|
||||
|
||||
JPEG, PNG, TIFF, PSD, WebP, AVIF, JPEG XL and DNG, or the original files with XMP sidecars. See [Export photos](../guides/export-photos.md).
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Getting started
|
||||
description: Install LightCraft on your computer and open your first library.
|
||||
order: 10
|
||||
---
|
||||
|
||||
- [Install LightCraft](install.md)
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: Install LightCraft
|
||||
description: Download LightCraft for Windows 11, macOS or Linux, install it, and open your photo library.
|
||||
order: 10
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Download the file for your system from the [latest release](https://github.com/storytold/lightcraft/releases/latest) and install it. In the file names, `<version>` stands for the version number, for example `0.7.1`. The [LightCraft page on getartcraft.com](https://getartcraft.com/apps/lightcraft) also links the download.
|
||||
|
||||
## Windows 11
|
||||
|
||||
1. Open the [latest release](https://github.com/storytold/lightcraft/releases/latest).
|
||||
2. Download `lightcraft-<version>-windows-x64.msi`. It fits most PCs (Intel and AMD, 64-bit).
|
||||
3. Run the file. The installer asks where to install. The default is `C:\Program Files\LightCraft`, and upgrades stay in the folder you chose.
|
||||
4. At the end, choose the option to start LightCraft.
|
||||
|
||||
For a Snapdragon or other Arm PC, download `lightcraft-<version>-windows-arm64.msi` instead. For a 32-bit Windows, download `lightcraft-<version>-windows-x86.msi`.
|
||||
|
||||
Upgrading from an installer older than 0.6.0 also keeps LightCraft in the folder it was installed in. If that folder was deleted, the upgrade installs to `C:\Program Files\LightCraft`.
|
||||
|
||||
To run it without installing, download `lightcraft-<version>-windows-x64-portable.zip`. Portable builds for `arm64` and `x86` are on the release page too.
|
||||
|
||||
## macOS
|
||||
|
||||
1. Download `lightcraft-<version>-macos-universal.dmg`. It works on Apple silicon and Intel Macs, and is signed and notarized.
|
||||
2. Open the file and install LightCraft.
|
||||
|
||||
## Linux
|
||||
|
||||
The release has these files for `x86_64` and `aarch64` (Arm). Replace `x86_64` with `aarch64` on Arm.
|
||||
|
||||
| File | Notes |
|
||||
|----------------------------------------------|----------------------------------------------------------|
|
||||
| `lightcraft-<version>-linux-x86_64.AppImage` | Runs anywhere. |
|
||||
| `lightcraft-<version>-linux-x86_64.flatpak` | Sandboxed. Install with `flatpak install --user <file>`. |
|
||||
| `lightcraft-<version>-linux-x86_64.deb` | For Debian and Ubuntu. |
|
||||
| `lightcraft-<version>-linux-x86_64.rpm` | For Fedora, RHEL and openSUSE. |
|
||||
| `lightcraft-<version>-linux-x86_64.tar.gz` | Unpack anywhere. |
|
||||
|
||||
RISC-V and FreeBSD builds are on the release page too. On a Wayland desktop, LightCraft runs through XWayland when it is available, because only X11 gives it file drag-and-drop.
|
||||
|
||||
## Install with ArtCraft Launcher
|
||||
|
||||
[ArtCraft Launcher](https://getartcraft.com/docs/craft-launcher) lists LightCraft and can install and update it for you. On Windows it installs the release `.msi`.
|
||||
|
||||
## In a web browser
|
||||
|
||||
The release also has `lightcraft-web-<version>.zip`, a static site that runs LightCraft in a modern browser. Host it on any static web server.
|
||||
|
||||
## First run
|
||||
|
||||
1. Start LightCraft. It opens your library at `~/Pictures/LightCraft Library`. A new library starts with demo photos.
|
||||
2. To bring in your own photos, see [Import photos](../guides/import-photos.md).
|
||||
|
||||
## Still stuck?
|
||||
|
||||
Ask in [Discord](https://discord.gg/artcraft) or open an issue in the [issue tracker](https://github.com/storytold/lightcraft/issues).
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: Rate, flag and label photos
|
||||
description: Sort a shoot with star ratings, pick and reject flags and colour labels, from the keyboard or the Photo menu.
|
||||
order: 20
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Select photos in **Photo Grid** or **Square Grid**, then press a key: `1` to `5` for stars, `P` to pick, `X` to reject, `6` to `9` for a colour label. The same actions are in the **Photo** menu.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Open the library in **View** > **Photo Grid** or **View** > **Square Grid**.
|
||||
2. Click a photo to select it. Click more photos to build a selection, or use **Edit** > **Select All**.
|
||||
3. Press a key:
|
||||
|
||||
| Key | Action |
|
||||
|--------------------|---------------------------------------------------------|
|
||||
| `0` | Clear the star rating |
|
||||
| `1` to `5` | Set the star rating |
|
||||
| `[` and `]` | Lower or raise the rating by one, within 0 to 5 |
|
||||
| `6`, `7`, `8`, `9` | Set a red, yellow, green or blue label |
|
||||
| `P` | Flag as a pick |
|
||||
| `X` | Flag as rejected |
|
||||
| `U` | Clear the flag |
|
||||
|
||||
4. To move on faster, hold `Shift` with a key. It applies the action and selects the next photo. Or turn on **Photo** > **Auto Advance** to move forward after every action.
|
||||
5. For purple, or to clear a colour label, use **Photo** > **Set Color Label** or the photo's right-click menu.
|
||||
|
||||
Rating, flag and label changes apply to every selected photo, and you can undo them with **Edit** > **Undo**.
|
||||
|
||||
## Compare photos
|
||||
|
||||
Choose **View** > **Compare** to see two photos side by side with synced zoom and pan, or **View** > **Survey** to see the selected photos tiled. The keys above then apply to the active photo only.
|
||||
|
||||
## Good to know
|
||||
|
||||
- **Rejected** only marks a photo for culling. It does not delete the original or remove it from the library.
|
||||
- The sidebar has **Picks** for the photos you flagged. The search box understands fields, for example `rating:>3 flag:pick`.
|
||||
- Choose **Help** > **Keyboard Shortcuts** to see every shortcut.
|
||||
- Typing in a text field keeps the keys for typing.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Edit a photo
|
||||
description: Open a photo in the Edit panel, adjust Light, Color and Effects sliders, compare with the original, and undo or reset.
|
||||
order: 30
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Double-click a photo in the grid, then press `E` to open the **Edit** panel. Drag a slider to change the photo. Your original file is never changed, because edits are stored in the library.
|
||||
|
||||
## Steps
|
||||
|
||||
1. In **Photo Grid** or **Square Grid**, double-click the photo. It opens in the **Detail** view.
|
||||
2. Press `E`, or choose **Window** > **Edit**, to open the **Edit** panel.
|
||||
3. Click **Auto** for a first pass, or skip this step and start with the sliders.
|
||||
4. Open the **Light** section and set **Exposure**, **Contrast**, **Highlights**, **Shadows**, **Whites** and **Blacks**.
|
||||
5. Open the **Color** section to change **Vibrance** and **Saturation**. Open **Effects** for **Texture**, **Clarity** and **Dehaze**. The panel also has **Detail** and **Optics** sections.
|
||||
6. Check your work against the original. Hold `\` to peek at the original. Press `Y` (**View** > **Compare Before and After**) to see before and after side by side.
|
||||
7. To go back a step, choose **Edit** > **Undo**. To drop all edits on the photo, click **Reset** at the top of the **Edit** panel.
|
||||
|
||||
## Black and white
|
||||
|
||||
Click **B&W** at the top of the **Edit** panel to turn the photo monochrome. Click it again to return to colour.
|
||||
|
||||
## HDR
|
||||
|
||||
Click **HDR**, next to **B&W**, to edit the photo in HDR, with highlights brighter than SDR white for HDR exports. LightCraft cannot show HDR on an HDR screen yet, so you edit without seeing the extra brightness.
|
||||
|
||||
## Other edit tools
|
||||
|
||||
Open them from the **Window** menu, or press the key shown next to each one:
|
||||
|
||||
| Panel | Key |
|
||||
|-------------------|-------------|
|
||||
| **Crop & Rotate** | `C` |
|
||||
| **Remove** | `H` |
|
||||
| **Masking** | `M` |
|
||||
| **Presets** | `Shift`+`P` |
|
||||
|
||||
## Good to know
|
||||
|
||||
- A raw photo that LightCraft cannot decode yet is edited from the camera's embedded JPEG. The **Edit** panel then shows **Preview only**. See [A raw photo opens as "Preview only"](../troubleshooting/preview-only-raw.md).
|
||||
- When you zoom in on a large raw, the view can look soft for a few seconds while LightCraft renders the full-resolution pixels.
|
||||
- To save the result as a file, see [Export photos](export-photos.md).
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Export photos
|
||||
description: Save edited photos as JPEG, PNG, TIFF and other files with the size, folder and file names you choose.
|
||||
order: 40
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Select the photos, then choose **File** > **Export…**. Pick a format, a size and a folder, then click **OK**. Your originals are not changed.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Select one or more photos in the grid.
|
||||
2. Choose **File** > **Export…**. The **Export** window shows how many photos it will export.
|
||||
3. Set **Format**: **JPEG**, **PNG**, **TIFF**, **PSD**, **WebP**, **AVIF**, **JPEG XL**, **DNG** or **Original files**. **DNG** writes raw photos as DNG with the edits embedded. **Original files** copies the files unchanged, each with an XMP sidecar that holds its edits.
|
||||
4. For **JPEG**, **AVIF** or lossy **JPEG XL**, set **Quality**. For **JPEG XL**, tick **Lossless** to keep every pixel exactly, at the cost of larger files. **Effort** trades time for file size, and **Progressive** makes the file show a coarse version first while it loads.
|
||||
5. Under the size options, tick **Full size**, or clear it and choose **Resize to** one of **Long Edge**, **Short Edge**, **Width**, **Height**, **Width × Height**, **Megapixels** or **Percentage**, then enter the value.
|
||||
6. Set **Color space** (**sRGB**, **P3**, **Adobe RGB**, **ProPhoto** or **Rec.2020**) if you need something other than the default. Lossy **JPEG XL** writes **Adobe RGB** and **ProPhoto** as **Rec.2020**. Tick **Lossless** to keep them.
|
||||
7. Optional: set **Sharpen** for **Screen**, **Matte** or **Glossy** output, set **Metadata** to **All**, **No camera**, **Copyright** or **None**, and tick **Remove location info** or **Watermark**.
|
||||
8. Next to **Folder**, click **Choose…** and pick where the files go. **Subfolder** adds a folder inside it.
|
||||
9. Set **File name** to a template such as `{name}-{seq}`. Click **Tags** to see the tags you can insert.
|
||||
10. Set **If file exists** to **Add number**, **Overwrite** or **Skip**.
|
||||
11. On macOS, tick **Add to Apple Photos** to add the exported files to Photos as well. Type an **Album** name to put them in that album. The first time, macOS asks whether LightCraft may control Photos.
|
||||
12. Click **OK**. The export shows its progress in the activity stack at the top left.
|
||||
|
||||
If you did not choose a folder, the window stays open and shows an error, so your choices are not lost.
|
||||
|
||||
## Reuse your settings
|
||||
|
||||
- To keep a set of choices, type a name next to **Save preset** and click **Save**. Pick it again later with **Preset** at the top of the window.
|
||||
- **File** > **Export with Previous** repeats your last export. It tells you to use **Export…** first if you have not exported yet.
|
||||
|
||||
## Contact sheet
|
||||
|
||||
To make a PDF of thumbnails, select photos and choose **File** > **Contact Sheet PDF…**.
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: Move over from Lightroom
|
||||
description: Import a Lightroom Classic catalog into LightCraft, and learn what comes across and what does not.
|
||||
order: 50
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Choose **File** > **Import Lightroom Catalog…** and pick your `.lrcat` file. LightCraft reads it directly. You do not need Lightroom installed.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Open the library you want the photos in. To start a new one, use **File** > **New Library…**.
|
||||
2. Choose **File** > **Import Lightroom Catalog…**.
|
||||
3. Pick your Lightroom Classic catalog, the file that ends in `.lrcat`. You can also give **File** > **Open Library…** a Lightroom catalog folder. LightCraft then offers this import instead of making a library there.
|
||||
4. Wait for the import to finish. It runs in the background, with a progress row in the activity stack at the top left. A message reports how many photos were added.
|
||||
|
||||
If you change your mind, one **Edit** > **Undo** reverses the changes to the catalog.
|
||||
|
||||
## What comes across
|
||||
|
||||
- Ratings, picks and rejects, and colour labels
|
||||
- Keywords, including hierarchical ones, and XMP metadata
|
||||
- Collections and collection sets, which become albums
|
||||
- Virtual copies
|
||||
- Develop settings that LightCraft can map
|
||||
|
||||
Original files stay where they are, and LightCraft refers to them in place. Photos whose originals are missing stay in the library so you can relink them later. LightCraft never changes your Lightroom catalog or your originals.
|
||||
|
||||
## What does not match
|
||||
|
||||
- Develop settings are an approximation. Camera profiles, Adobe's AI models and some masking and retouch fields are not reproduced, and settings LightCraft cannot map are reported.
|
||||
- Smart collections become regular albums that hold the photos they contain at the time of import.
|
||||
- Lightroom's process version is not carried over. Imported photos use LightCraft's newest rendering.
|
||||
|
||||
## Good to know
|
||||
|
||||
- Before it changes anything, LightCraft tries to save your source settings, history and collections in a recovery archive in the library's `Interop` folder. This is best effort. If it fails, the photos are still imported with a warning.
|
||||
- Importing the same catalog again does not duplicate virtual copies or collections. By default, edits you already made in LightCraft are kept.
|
||||
- A big catalog can take a long time. In one report on an earlier version, 38,000 photos took about 25 minutes from a USB SSD.
|
||||
- To stop the import, click ✕ on its row in the activity stack. This works while LightCraft reads the catalog. Once it starts adding the photos, it finishes.
|
||||
- The browser version cannot import a catalog.
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: Import photos
|
||||
description: Bring photos from a folder or card into your LightCraft library, in place or as copies.
|
||||
order: 10
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Use **File** > **Import Photos…** to pick files, or **File** > **Import from Folder…** to scan a whole folder. Both open the **Import Photos** window, where you choose what to bring in and how.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Open the **File** menu and choose **Import Photos…** or **Import from Folder…**, then pick the files or the folder.
|
||||
2. Look at the thumbnails. Every photo that can be imported has a checkbox. Click a photo to check or uncheck it. Shift-click sets a range. **Check All** and **Uncheck All** change every photo at once.
|
||||
3. Photos already in your library are marked **Duplicate** or **In library** and start unchecked. A file LightCraft cannot read is marked **Unreadable**. A photo you deleted that is still in **Recently Deleted** is marked **Will be restored**. **In Recently Deleted** sets what happens to those: **Restore them** (the default) brings the photos back with their edits, ratings and albums, **Import as new** deletes the old record first, and **Leave them** skips them.
|
||||
4. Under **Transfer**, choose how the files get into the library:
|
||||
- **Add in place** keeps the files where they are. The library only points to them. Nothing is copied or moved.
|
||||
- **Copy** copies the files into the library's `Originals` folder, or into a folder you pick with **Choose…** next to **Copy to**.
|
||||
- **Move** does the same, then removes each original from its source once the copy is verified and catalogued.
|
||||
5. With **Copy** or **Move**, set **Folders** to sort the copies **By day (YYYY/YYYY-MM-DD)**, **By month (YYYY/YYYY-MM)**, **Into one folder**, or with a **Custom template…**. Use **Rename** to give the files new names, for example `{date}_{seq:3}`. Leave it empty to keep the names. With **Copy**, **Copy as DNG** converts raw files to DNG.
|
||||
6. Optional: set **Album** to add the photos to an existing album or a new one, **Preset** to apply a preset to every photo, and **Keywords** (separated by commas).
|
||||
7. Click the button at the bottom. It shows the number of checked photos, for example **Import 24 Photos**. With **Move** it reads **Move 24 Photos**.
|
||||
|
||||
The import runs in the background, with a progress row in the activity stack at the top left, and you can keep working while it does. The whole import is one undo step.
|
||||
|
||||
## Good to know
|
||||
|
||||
- Importing a folder scans it for photos. It does not add the folder to **Local**. To work in a folder without importing, use **Local** > **Browse Folder…**.
|
||||
- Folder names and `{date}` use the capture time. A photo without one uses today's date.
|
||||
- Raw formats LightCraft reads include DNG, Canon CR2 and CR3, Sony ARW, Nikon NEF, Fujifilm RAF, Panasonic RW2, Leica RWL, Pentax PEF and Olympus ORF. Some variants open as **Preview only**. See [A raw photo opens as "Preview only"](../troubleshooting/preview-only-raw.md).
|
||||
|
||||
## Next
|
||||
|
||||
[Rate, flag and label photos](cull-photos.md) to sort out the keepers.
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Guides
|
||||
description: How to do one thing in LightCraft.
|
||||
order: 20
|
||||
---
|
||||
|
||||
- [Import photos](import-photos.md)
|
||||
- [Rate, flag and label photos](cull-photos.md)
|
||||
- [Edit a photo](edit-a-photo.md)
|
||||
- [Export photos](export-photos.md)
|
||||
- [Move over from Lightroom](import-lightroom-catalog.md)
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
title: LightCraft
|
||||
description: LightCraft is a free, open-source photo library and raw developer, an alternative to Adobe Lightroom.
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
LightCraft is a photo library and raw developer that runs on your own computer. It is an open-source alternative to Adobe Lightroom, written in Rust, and part of the Craft App Suite from the ArtCraft team.
|
||||
|
||||
You import photos, sort them with ratings, flags and albums, and edit them without touching the originals. It reads raw files from Canon, Sony, Nikon, Fujifilm, Panasonic, Leica, Pentax and Olympus cameras, and DNG. There is no account, no cloud, no telemetry and no subscription. It runs on Windows, macOS and Linux, and in a web browser. LightCraft is in alpha, so expect rough edges.
|
||||
|
||||
## Start here
|
||||
|
||||
- [Install LightCraft](getting-started/install.md)
|
||||
- [Import photos](guides/import-photos.md)
|
||||
- [Rate, flag and label photos](guides/cull-photos.md)
|
||||
- [Edit a photo](guides/edit-a-photo.md)
|
||||
- [Export photos](guides/export-photos.md)
|
||||
- [Move over from Lightroom](guides/import-lightroom-catalog.md)
|
||||
- [A raw photo opens as "Preview only"](troubleshooting/preview-only-raw.md)
|
||||
- [Raw photos look dull or washed out](troubleshooting/raw-photos-look-dull.md)
|
||||
- [Get help with a problem](troubleshooting/get-help.md)
|
||||
- [Frequently asked questions](faq/index.md)
|
||||
|
||||
## Get help
|
||||
|
||||
Ask in [Discord](https://discord.gg/artcraft) or open an issue in the [issue tracker](https://github.com/storytold/lightcraft/issues). Say which system and camera you use, and your LightCraft version (**Help** > **About LightCraft**; on macOS, **LightCraft** > **About LightCraft**).
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
title: Get help with a problem
|
||||
description: What to include when you ask for help with a LightCraft bug, and where to post it.
|
||||
order: 30
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Open an issue in the [issue tracker](https://github.com/storytold/lightcraft/issues), or ask in [Discord](https://discord.gg/artcraft). Include your version, your system, what you did, and what you expected.
|
||||
|
||||
## What to include
|
||||
|
||||
1. **Your version.** Choose **Help** > **About LightCraft** (on macOS, **LightCraft** > **About LightCraft**).
|
||||
2. **Your system.** For example Windows 11, 64-bit. **Help** > **System Info…** shows details about your computer.
|
||||
3. **The steps.** What you clicked, in order, and what happened.
|
||||
4. **The camera and file type**, if the problem is with a photo.
|
||||
5. **A sample file**, if a raw or other photo renders wrong. Maintainers ask for the original file, not an export. A link to a shared folder works. Uploading raws to [raw.pixls.us](https://raw.pixls.us) also helps, because every file there becomes a permanent test sample for that camera.
|
||||
6. **A screenshot** of LightCraft next to the camera JPEG or the other app, for colour problems.
|
||||
7. **The log file.** Choose **Help** > **Open Log Folder** and attach `lightcraft.log`.
|
||||
|
||||
## Where the log is
|
||||
|
||||
LightCraft writes its log to `logs/lightcraft.log` in its settings folder. On Windows that is `%APPDATA%\LightCraft\logs\`. Each start moves the previous log to `lightcraft.1.log`, and that one to `lightcraft.2.log`, so the log of a run that crashed survives the next start.
|
||||
|
||||
## Still stuck?
|
||||
|
||||
Ask in [Discord](https://discord.gg/artcraft).
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Troubleshooting
|
||||
description: Fixes for common LightCraft problems.
|
||||
order: 30
|
||||
---
|
||||
|
||||
- [A raw photo opens as "Preview only"](preview-only-raw.md)
|
||||
- [Raw photos look dull or washed out](raw-photos-look-dull.md)
|
||||
- [Get help with a problem](get-help.md)
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: A raw photo opens as "Preview only"
|
||||
description: Why LightCraft shows a raw photo as Preview only, and how to make it decode after an update with Reload from Disk.
|
||||
order: 10
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Select the photo and choose **Photo** > **Reload from Disk**. If your version can decode that raw now, LightCraft reads the sensor data again and the **Preview only** notice goes away.
|
||||
|
||||
## Symptoms
|
||||
|
||||
- The **Edit** panel shows **Preview only**, with the text "LightCraft can't decode this raw variant yet" and the name of the variant.
|
||||
- You updated LightCraft to a version that supports your camera, and the photo still looks the same.
|
||||
|
||||
## Fix
|
||||
|
||||
1. In the grid, select the photos that show **Preview only**.
|
||||
2. Choose **Photo** > **Reload from Disk**. The right-click menu on a photo has the same entry.
|
||||
3. Open a photo again. If **Preview only** is gone, the photo is now decoded from the raw data.
|
||||
|
||||
If **Preview only** stays, your version still cannot decode that raw variant. Update to the [latest release](https://github.com/storytold/lightcraft/releases/latest) and try again, or report the file as described in [Get help with a problem](get-help.md).
|
||||
|
||||
## Why this happens
|
||||
|
||||
When LightCraft cannot decode a raw on import, it remembers that and shows the camera's embedded JPEG. It does not check again after an update on its own. **Reload from Disk** is the way to make it check. Compressed Olympus raws, some Canon CR3 variants and Nikon High Efficiency NEF files are examples of files that use the embedded preview.
|
||||
|
||||
0.7.1 decodes Canon EOS R5 Mark II C-RAW files that earlier versions opened as **Preview only**. Photos imported before switch over after **Reload from Disk**.
|
||||
|
||||
Photos shown from the preview keep the camera's picture style and white balance, because they are the camera's own JPEG.
|
||||
|
||||
## Still stuck?
|
||||
|
||||
Ask in [Discord](https://discord.gg/artcraft) or open an issue in the [issue tracker](https://github.com/storytold/lightcraft/issues).
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: Raw photos look dull or washed out
|
||||
description: What to do when a raw photo looks flat, grey or desaturated in LightCraft compared with the camera JPEG.
|
||||
order: 20
|
||||
verified: 0.7.1
|
||||
---
|
||||
|
||||
Update to the latest LightCraft, then select the photo and choose **Photo** > **Reload from Disk**. Colour handling for raw files changed a lot between 0.4.0 and 0.7.1, and several flat-looking Sony and Fujifilm cases are fixed. Some Leica DNGs and dark, muted scenes still look dull.
|
||||
|
||||
## Symptoms
|
||||
|
||||
- A raw photo looks flat, grey or desaturated as soon as you open it.
|
||||
- The preview or thumbnail looks right, but the opened photo does not.
|
||||
- Blacks look lifted, and the shadows look grey.
|
||||
|
||||
## Fix
|
||||
|
||||
1. Check your version in **Help** > **About LightCraft** (on macOS, **LightCraft** > **About LightCraft**). If it is older than 0.7.1, install the [latest release](https://github.com/storytold/lightcraft/releases/latest). See [Install LightCraft](../getting-started/install.md).
|
||||
2. Select the raw photo and choose **Photo** > **Reload from Disk**.
|
||||
3. If it still looks dull, adjust it by hand in the **Edit** panel. See [Edit a photo](../guides/edit-a-photo.md).
|
||||
4. If you think the starting look is wrong for your camera, report it with the original raw file. See [Get help with a problem](get-help.md).
|
||||
|
||||
## Why this happens
|
||||
|
||||
LightCraft develops a raw from the sensor data and tries to match the look of the camera's own JPEG. How well it matches depends on the camera model.
|
||||
|
||||
- **Sony ARW:** on 0.5.0 and older, some Lossless Compressed M-size files had lifted blacks, and an A7 II file lost most of its colour. Both are fixed since 0.6.0. Some files still fall short on in-camera Dynamic Range Optimizer shots.
|
||||
- **Dark, muted scenes:** LightCraft applies only part of the camera look to them, so they can start duller than the camera JPEG. This is not fixed in 0.7.1 ([issue 865](https://github.com/storytold/lightcraft/issues/865)).
|
||||
- **Fujifilm X-Pro1 and Sony A7 IV:** reported dull on 0.4.0 and fine on 0.6.0.
|
||||
- **Leica DNG:** these files carry a colour matrix but no tone curve, so LightCraft shows them darker and flatter than the camera JPEG. This is not fixed in 0.7.1 ([pull request 807](https://github.com/storytold/lightcraft/pull/807)).
|
||||
- **Adobe RGB:** if the camera was set to Adobe RGB, 0.6.0 and older read the embedded JPEG as sRGB and matched to a too-dull target. Fixed in 0.7.1: LightCraft reads the JPEG in the colour space the raw file states.
|
||||
- **Black-and-white picture style:** a raw shot in a monochrome picture style started about 1.3 EV darker than the same camera's colour shots. Since 0.7.1, LightCraft takes the tone from the camera's black-and-white JPEG.
|
||||
|
||||
## A soft picture after zooming in
|
||||
|
||||
If a large raw looks soft right after you zoom in, wait a few seconds. LightCraft first shows the fit-size picture enlarged, then renders the zoomed area from the full-resolution raw and swaps it in. On a 61 MP file this can take a few seconds. If it stays soft at **Zoom 100%** (**View** > **Zoom 100%**), report it.
|
||||
|
||||
## Still stuck?
|
||||
|
||||
Ask in [Discord](https://discord.gg/artcraft) or open an issue in the [issue tracker](https://github.com/storytold/lightcraft/issues).
|
||||
+2
-1
@@ -55,7 +55,8 @@ gzip size (5.25 MB). `wasm-opt -Oz`, when installed, shrinks it further.
|
||||
**Fonts.** The browser has no system fonts to fall back on, so CJK text comes from
|
||||
[craft-fonts](https://github.com/storytold/craft-fonts), the optional `CRAFT_FONTS_DIR` build
|
||||
input (`CRAFT_FONTS_DIR=../craft-fonts cargo xtask web`; release builds always set it). On wasm32
|
||||
`crates/engine/build.rs` embeds only BIZ UDPGothic Regular (UI and watermark fallback). The web
|
||||
`crates/engine/build.rs` embeds BIZ UDPGothic Regular (UI and watermark fallback) and Noto Sans
|
||||
Thai Regular (~214 KiB, for Thai file and folder names in every UI language). The web
|
||||
bundle also ships Noto Sans CJK SC Regular as `lightcraft_zh_hans.otf` and loads it before the UI
|
||||
starts. Keeping the 16 MB Chinese face separate leaves the module under Cloudflare's 25 MiB
|
||||
per-file limit (the older Japanese-only module measured 21.8 MB). Without `CRAFT_FONTS_DIR`, the
|
||||
|
||||
+403
-4
@@ -2,12 +2,233 @@
|
||||
|
||||
## 2026-10-14
|
||||
|
||||
### Model downloads time out on a name that doesn't resolve
|
||||
- Model downloads (AI denoise, faces, SAM) give up on a server name that doesn't resolve within the connect timeout,
|
||||
and Cancel stops a download that is still looking the name up (issue #1532). The lookup used to block with no time
|
||||
limit, and each of a server's addresses then got the whole connect timeout of its own.
|
||||
|
||||
### Lightroom radial masks on the right side
|
||||
- Radial masks brought over from Lightroom Classic (catalog import, XMP sidecars, edits inside DNGs and presets) now
|
||||
apply their effect inside the circle, as Lightroom does, instead of outside it (issue #1815). A mask inverted in
|
||||
Lightroom stays inverted, and older Radial Filters keep their Effect Outside / Invert Mask setting. Photos imported
|
||||
before this keep the masks they got: Photo ▸ Read Metadata from File reads a sidecar's again.
|
||||
|
||||
### Delete in an album removes from the album only
|
||||
- In an album, the Delete key now takes the selected photos out of the album, as in Lightroom. It used to move them
|
||||
to Recently Deleted, so they also left their folder's view (issue #1805). They stay in the library and in their
|
||||
folder; Edit ▸ Undo puts them back in the album. Photo ▸ Remove from Album does the same and now shows the key.
|
||||
To delete photos from the library from an album, use Photo ▸ Delete Photo or right-click ▸ Delete Photo. In a smart
|
||||
album, Delete changes nothing: its rules decide what it shows.
|
||||
|
||||
### Local folders select a photo
|
||||
- Showing a Local folder now makes its first photo the active one, as albums and the other sources do (issue
|
||||
#1447), or keeps the photo you had when the folder holds it. Before, the photo from the previous view stayed active:
|
||||
Photo Grid marked nothing, and Detail, the histogram and the photo info showed a photo that isn't in the folder.
|
||||
|
||||
### Nikon Z 6II, Z 8 and D5300 colour profiles
|
||||
- Raws from the Nikon Z 6II, Z 8 and D5300 now start from a colour profile built from a few hundred photos from each camera, the same way the
|
||||
Sony and Fujifilm profiles were made, instead of fitting each photo's colour on its own. Colours that one photo
|
||||
shows only a little of come out closer to the camera's JPEG.
|
||||
|
||||
### Closer camera colour for lens-corrected raws
|
||||
- Raws from cameras that correct their own JPEG for lens distortion (Panasonic and Fujifilm with that setting on, the
|
||||
Sony A7R IVA) now start from colours closer to the camera's. The starting look was being fitted against a JPEG that
|
||||
didn't line up with the raw near the edges. Photos you already imported pick this up when their previews are rebuilt.
|
||||
|
||||
### HDR merges of moving lights, and many brackets at once
|
||||
- A star, the moon or a light that moves between the photos of a bracket (a night bracket on a tripod) no longer
|
||||
leaves a black hole where the middle photo had it clipped. With Deghost, the brightest photo's copy of it in a
|
||||
dark sky is now removed too.
|
||||
- Photo ▸ Photo Merge ▸ HDR for Each Bracket Set merges every bracket among the selected photos with the last HDR
|
||||
settings, one after the other: each stack, and photos taken less than a second apart at different exposures.
|
||||
From the command line: `lightcraft-cli merge hdr-batch FOLDER`.
|
||||
- Merging uses about a quarter less memory: three 67 MP raws need 3.8 GB instead of 4.8 GB.
|
||||
|
||||
### XMP sidecars catch up after a network share comes back
|
||||
- With automatic XMP writing on, an edit to a photo whose folder can't be written (a network share that dropped
|
||||
out, a folder that went read-only) used to be written only to the library, with a line in the log, so the sidecar
|
||||
stayed behind the edit. LightCraft now says once that the sidecars are waiting, tries again every few seconds once
|
||||
the files are reachable, and says when they're written. `library.retrySidecars` does it on request.
|
||||
|
||||
### Reliability
|
||||
- A damaged or crafted raw can no longer make LightCraft set aside gigabytes of memory before finding out the file is
|
||||
bad (issue #1512): a compressed PEF whose data is too short for the size it declares, an uncompressed TIFF-based
|
||||
raw whose tile claims far more samples than it holds, and an ARW6 with a broken tile are refused first. All 74
|
||||
files in the test corpus still decode.
|
||||
|
||||
### Reliability
|
||||
- Thumbnails and previews are written to the cache on disk by one background writer instead of a new thread for
|
||||
each image (issue #1522). When renders come in faster than the disk takes them, at most 128 MB of images wait;
|
||||
past that a write is skipped (the image stays in memory and is written by a later render), so a slow disk can't
|
||||
pile up threads and memory.
|
||||
|
||||
### Reliability
|
||||
- Saving the catalog and resuming a model download no longer write through a link left at the temporary file's
|
||||
name (`catalog.snap.tmp`, `model.onnx.part`): the link is removed and a new file made in its place, so the file it
|
||||
pointed to is never changed (issue #1502).
|
||||
|
||||
### Reliability
|
||||
- A photo whose file was replaced (Reload Changed Files after an outside edit) no longer keeps the faces recognition
|
||||
made from the old pixels: they are made again from the new file, and a scan still busy with the old file when it
|
||||
changed doesn't put its faces on the new one (issue #1524).
|
||||
|
||||
### Settings stays put when you change tabs
|
||||
- The Settings window keeps its top edge and width when you switch tabs, so the tab row no longer jumps around
|
||||
under the pointer. It used to be centred, so every tab of a different height moved it.
|
||||
|
||||
### Layout image over the loupe
|
||||
- View ▸ Loupe Overlay ▸ Choose Layout Image… draws a PNG with transparency over the photo in the loupe, such as
|
||||
a magazine cover's masthead and cover lines, so you can frame a shot for the page it is made for. It fits inside
|
||||
the photo, follows zoom and pan, and ⌥⌘O shows or hides it. The same menu sets its opacity and a matte that
|
||||
darkens the photo outside it. The layout stays chosen across launches.
|
||||
|
||||
### Smaller JPEG exports
|
||||
- JPEG exports are 12–14 % smaller at the same quality, with exactly the same pixels (issue #1373): each file now
|
||||
carries Huffman tables made for its own picture instead of the standard example tables. Every viewer opens them
|
||||
as before.
|
||||
|
||||
### Reliability
|
||||
- A photo whose Defringe amount was stored far past the sliders' 20 (in a damaged catalog or sidecar) no longer
|
||||
crashes LightCraft each time it renders: the amount acts as 20.
|
||||
|
||||
### Lens names for Nikon DSLR raws
|
||||
- Photos from Nikon DSLRs like the D700, D750, D80 or D5300 now show which lens they were taken with, for example
|
||||
"24.0-70.0 mm f/2.8". Those cameras don't write a lens name, so the lens field was empty and you couldn't filter or
|
||||
search by lens. LightCraft now reads the lens range Nikon keeps in its own maker note, the way Lightroom shows a
|
||||
lens it doesn't have a name for. Newly imported photos show it.
|
||||
|
||||
### Import when a card is connected
|
||||
- Settings → Import → Cameras and Cards has an option to open the import review as soon as a camera or memory card
|
||||
is connected, the same review File → Import from Device opens. It's off by default. A card that's already in when
|
||||
LightCraft starts doesn't ask, and if a dialog is open or an import is running it waits until that's done.
|
||||
|
||||
### Local folders
|
||||
- Photos deleted (or moved) by another app no longer stay in a Local folder, failing to load and logging an error
|
||||
each time you look (issue #1392): the next time you browse the folder, in a later session, they're left out. A photo you had rated, flagged or
|
||||
edited stays, marked missing, so its changes aren't lost; photos in My Photos are unchanged.
|
||||
|
||||
### Full-resolution panoramas
|
||||
- Panorama and HDR Panorama merges keep the resolution of their photos instead of stopping at 40 megapixels
|
||||
(issue #1455), up to 512 MP and 65,000 pixels on the long edge, as in Lightroom. When the full size needs more
|
||||
memory than the computer has, the panorama is made as large as fits (five 51 MP photos: up to 166 MP with
|
||||
16 GB, 355 MP with 32 GB) and the message says so. The merge also frees each photo's pixels once they are
|
||||
projected, so it needs less memory than before at any size (an 81 MP stitch: 4.4 GB instead of 6.2 GB).
|
||||
|
||||
### Nikon D600, D610 and D5000
|
||||
- Raws from the Nikon D600, D610 and D5000 no longer show a bright line down the right edge (issue #1627). Their
|
||||
sensor data runs a few columns of filler past the picture, which stayed in the image; these bodies now develop
|
||||
at the camera JPEG's size (6016 × 4016 for the D600 and D610, 4288 × 2848 for the D5000, as the D90 already
|
||||
did). On the D600 and D610 the white level is also measured inside the picture, so the filler can't pass for
|
||||
clipped highlights.
|
||||
|
||||
### More Canon EOS R6 Mark II C-RAW files decode
|
||||
- Some EOS R6 Mark II C-RAW files (about 1 in 50 in one photographer's library) opened as their preview with
|
||||
"Canon CRX adaptive QP value 172" or "175". They now decode from the sensor data. Photos imported before this
|
||||
switch over with Photo ▸ Reload from Disk.
|
||||
|
||||
### Nikon raws without coloured edge bars
|
||||
- Raws from older Nikon bodies no longer show a thin coloured or dark bar along one edge (the right edge, or the top
|
||||
of a portrait photo): masked sensor columns were being developed as part of the picture (issues #976, #914,
|
||||
#1236). The D7000, D5100, D800, D800E, Df, D4, D3, D3S, D700, D300, D300S, D600, D610, D810, D4S, D5600,
|
||||
Coolpix A, D3000, D40X, D60, D80, D2Xs, D200, D3200, D3100, D5000, D40, D50, D70, D70s and Nikon 1 V1 now show
|
||||
the area the camera itself frames, a few pixels smaller than before.
|
||||
### An empty library leads to Import
|
||||
- A library with no photos now opens on the Photo Grid with the sidebar (Square Grid stays as it is), instead of a
|
||||
Detail view that pointed at an empty grid. The grid and Detail view offer Import Photos… and, in the desktop app,
|
||||
Import Lightroom Catalog… as buttons, and say that photos (and, in the desktop app, folders) can be dropped into
|
||||
the window. The shortcut they show is the one Import Photos… has now.
|
||||
- The top bar has an Import button, beside Export, in every library.
|
||||
|
||||
### Reliability
|
||||
|
||||
### One kind of button
|
||||
- Dialogs' buttons and About's Discord link are drawn by one button component: primary (filled with the accent),
|
||||
secondary, danger (filled red) and ghost, in three sizes, with an icon or without, and an icon alone (named for
|
||||
screen readers). Each darkens a little when hovered and more when pressed, shows a ring where the keyboard is, and
|
||||
its text reads at 4.5:1 or more on its fill in every theme. Dialog buttons are 30 points tall, like the welcome's.
|
||||
|
||||
### A dialog's confirm button says it's the next step
|
||||
- In dialogs, the confirm button is on the right with Cancel to its left, and filled with the accent when it makes or
|
||||
brings in something (Import N Photos, Merge, Save, Create, Download…). Delete and Remove stay plain, so a destructive
|
||||
choice is never the eye-catching default.
|
||||
### Straight brush strokes with ⇧-click
|
||||
- With the brush, click once, then ⇧-click somewhere else: the brush paints a straight line between the two, and
|
||||
further ⇧-clicks carry on from the last point, as in Lightroom. Change the brush size, feather or flow before the
|
||||
⇧-click and the line tapers from the old values to the new ones. The whole line is one undo step.
|
||||
`mask.brushStroke {connect: true}` does the same for agents.
|
||||
|
||||
### Hard-edged Heal and Clone spots
|
||||
- A spot with Feather at 0 no longer draws black pixels exactly on its radius. This also fixes spots at 0% Opacity
|
||||
changing pixels along their edge. The hard edge now leaves pixels on the radius unchanged.
|
||||
|
||||
### Where the camera focused
|
||||
- **View ▸ Show Focus Point** (⌥F) draws the autofocus frame the camera recorded over the photo, in Detail, Compare
|
||||
and Survey, following rotation and crops; the Info panel says how it focused (`AF-C · Wide · Animal Eye Tracking`).
|
||||
Lightroom has no such view.
|
||||
- **Z zooms to it**: Toggle Zoom centres on the focus point, so checking that the subject is sharp is one key
|
||||
(View ▸ Zoom to Focus Point turns this off). Photos without a point zoom as before.
|
||||
- Sony α1 (ILCE-1) and A7S III (ILCE-7SM3) raws for now; manual-focus shots and Wide shots that only report the frame
|
||||
centre show nothing. More cameras will follow. Details: [focus-points.md](focus-points.md).
|
||||
- **Photos already in your library get theirs in the background**: LightCraft reads just the few kilobytes of each
|
||||
file that hold the focus point (about 100 photos a second from a spinning disk), with a *Reading focus points* row
|
||||
in the activity stack you can stop. Photo ▸ Read Focus Points runs it by hand.
|
||||
|
||||
### Cleaner HDR merges
|
||||
- Bright windows in an HDR made with Photo ▸ Photo Merge ▸ HDR no longer take a magenta tinge from the brighter
|
||||
photos along the areas they clipped: right next to a clipped area, a photo's colour isn't used. It showed most when
|
||||
the highlights were darkened or saturated.
|
||||
- The same photos give the same HDR whatever order they are selected in; before, a different order could change a
|
||||
few pixels.
|
||||
|
||||
### HDR merges keep the white balance
|
||||
- An HDR merged from raws that LightCraft colours from the camera's JPEG (CR2, NEF, ARW…) now opens at the same
|
||||
As Shot temperature and tint as its photos, and changing the white balance no longer turns it green. Sony ARW
|
||||
merges used to open at about 7000 K / +115 where the photos show 4000–5300 K / +8. HDRs merged before this keep
|
||||
their old white balance; merge them again.
|
||||
|
||||
## 2026-10-13
|
||||
|
||||
### Edits keep up in a large library
|
||||
- A small edit (a keyword, a rating, a flag, a slider) no longer has the grid's list worked out again from every
|
||||
photo: only the photos the edit touched are asked about again and put at their place in the order. In a library of
|
||||
67,000 photos that step went from 37 ms to under 1 ms. Still worked out whole: an edit to more than 256 photos, a
|
||||
change to an album, a stack or the keyword list, an album shown in its own order, Recently Added, Missing Photos,
|
||||
and a view that asks about "the last N days".
|
||||
- With no filter set, the count of the source is taken from the list instead of from a second pass over the library.
|
||||
- The side panels keep a tally an edit cannot have changed: a rating or a slider changes none of the folders,
|
||||
keywords, dates, people and counts; a keyword leaves the folders, the dates and the counts as they are. With both
|
||||
side panels open, the frame after a keyword went from about 156 ms to about 54 ms in that library (2 ms with the
|
||||
panels closed, from 71 ms).
|
||||
- The count beside each smart album in the left panel follows an edit the same way: the album asks only the photos
|
||||
the edit touched, where it asked every photo of the library after each edit (about 25 ms an album in that library).
|
||||
With that, the frame after a keyword is at about 29 ms there. New rules, a change to an album or the keyword list,
|
||||
an edit to more than 256 photos, and each new minute for an album that asks about "the last N days" are still
|
||||
counted from every photo.
|
||||
- Still tallied from every photo on each edit: the filter bar's lists of cameras, lenses and keywords.
|
||||
|
||||
### A view can hold its photos until you refresh it
|
||||
- View ▸ Hold View Until Refreshed (off unless you turn it on; kept with the library). With it on, an edit that makes
|
||||
a photo stop matching the view keeps it in the view: a keyword given in a smart album of photos without keywords,
|
||||
a flag taken off in Picks, a rating that falls under the filter bar's. With it off, as before, the photo leaves the
|
||||
grid at once and every photo after it moves up. View ▸ Refresh View (also in the sort menu while the hold is on),
|
||||
Reshuffle, another source, filter or sort, or new rules for the smart album shows what matches now.
|
||||
- Photos that start matching still appear at once, and deleting a photo or taking it out of the album or folder
|
||||
shown still takes it out of the view.
|
||||
|
||||
### The window opens at the size you left it
|
||||
- LightCraft's window opens at the size it had when you last used it, and zoomed (macOS) / maximized if it was: it
|
||||
used to open at 1600 × 1000 every time. Double-click the top bar to zoom the window, quit, and it is zoomed when
|
||||
you come back; un-zoom it and it goes back to the size it had before.
|
||||
- Full screen is not remembered (the app opens as a window), and neither is where on the desktop the window was:
|
||||
the system places it.
|
||||
- On macOS the system does not tell LightCraft when a window is zoomed from the Window menu or resized after a
|
||||
zoom, so it goes by the window's size, and when in doubt takes the window for a window of the size it has: it
|
||||
comes back as large as you left it, but not as a zoomed window. That is so after a zoom from the Window menu
|
||||
with the Dock at a side of the screen, or of a window already as wide as the screen. Zoomed by a double-click
|
||||
on the top bar it comes back zoomed. The other way round, a window you drag out until it is as wide as the
|
||||
screen and nearly as tall counts as zoomed.
|
||||
- For scripts: a size set with `ui.resize` is remembered like any other, so a script that needs a size sets it.
|
||||
|
||||
### HDR merges keep the lens correction
|
||||
- An HDR made with Photo ▸ Photo Merge ▸ HDR now keeps the lens correction the photos carry (Sony's, Panasonic's
|
||||
and Leica's, and the one some DNGs carry, e.g. from drones): Optics ▸ Enable Lens Corrections straightens it as it
|
||||
@@ -18,10 +239,6 @@
|
||||
models in a `LightCraftData` folder beside it instead of the per-user settings folder (issue #1200), as
|
||||
PhotoCraft does. If that folder can't be written, the usual folder is used and the log says why.
|
||||
|
||||
### Reliability
|
||||
- A photo whose Defringe amount was stored far past the sliders' 20 (in a damaged catalog or sidecar) no longer
|
||||
crashes LightCraft each time it renders: the amount acts as 20.
|
||||
|
||||
### Reliability
|
||||
- Importing a preset zip that unpacks to far more than any preset (a "zip bomb") is refused with a message naming
|
||||
the file, instead of asking for gigabytes of memory, which could end LightCraft.
|
||||
@@ -53,6 +270,23 @@
|
||||
else (issue #1504): trimming or clearing the cache can't delete files outside it, and thumbnails are never read
|
||||
from or written through such a link.
|
||||
|
||||
### Synchronize Folder asks a network share less
|
||||
- A Synchronize Folder scan no longer asks the disk about every photo of the library in the folder (is its file
|
||||
there, has it a sidecar): it has just listed the folder, and reads the answers off the listing. On a network share
|
||||
each of those questions is a round trip. Measured on a hard disk over SMB, for folders of 1,600 to 2,400 photos
|
||||
that had not changed: 4.6 to 7.1 s of questions after the listing (about 3 ms a photo), now under 0.05 s. The
|
||||
listing itself took 4 to 5 s and is as it was.
|
||||
- The disk is still asked wherever a listing can't be sure what a file system would say: about a name that is
|
||||
there in another case, a link, a name Windows reads another way (`aux.jpg`, a `~`, a `:`, a dot or a space at the
|
||||
end), a folder the scan did not walk to its end, and, in a folder that holds any name with a character outside
|
||||
ASCII (an umlaut, a curly apostrophe, a dash), about every name the folder does not list. Names it does list are
|
||||
answered there too. In such a folder the scan saves less, and its checks now start after the listing where they
|
||||
ran beside it.
|
||||
- A photo the folder lists is there for the scan, also where its file could not be opened by its path (a folder
|
||||
that may be listed but not searched, a path longer than the system takes): such photos used to be listed as
|
||||
missing. And a share that drops after the scan has listed a folder no longer turns that folder's photos into
|
||||
missing ones.
|
||||
|
||||
### Large libraries: Synchronize Folder, import and sidecars start sooner
|
||||
- Opening Synchronize Folder, an import review or an import no longer makes a table of every photo in the library
|
||||
before it looks at the first file. In a library of 3.5 million photos that held the window for about 6 s before
|
||||
@@ -108,6 +342,26 @@
|
||||
- An export enlarged far past the photo's size (20000 typed for 2000 with Don't Enlarge off) no longer ends
|
||||
LightCraft: an enlargement stops at 512 megapixels, as in Lightroom, and one that needs more memory than the
|
||||
computer has is refused with the size it would take, before it starts.
|
||||
### Confirm matching faces together
|
||||
- On a person's page, the ↑ control on a suggested face confirms it and all shown suggestions with equal or higher
|
||||
similarity as one undo step. Hover or focus that face and press A for the same action; hidden suggestions stay hidden.
|
||||
|
||||
### Noise reduction looks the same at every size
|
||||
- Luminance and colour noise reduction no longer look much stronger in grid thumbnails and the filmstrip than in
|
||||
the loupe (issue #960). Their radii are now set in the original photo's pixels, so a thumbnail, the fitted loupe
|
||||
and a smaller export look like the full-size result scaled down; 1:1 views and full-size exports are unchanged.
|
||||
Like in Lightroom, judge noise reduction at 1:1: at small sizes the noise it removes is mostly averaged away.
|
||||
Cached thumbnails are redrawn.
|
||||
- When the graphics driver resets the GPU while LightCraft is exporting or rendering (issue #1337, seen on Windows
|
||||
with NVIDIA), LightCraft still stops, because its window can't keep drawing on the lost device, but it now says
|
||||
"LightCraft stopped unexpectedly" and why, instead of "could not open its window", and the next start renders
|
||||
on the CPU and explains how to turn the GPU back on.
|
||||
|
||||
### Resetting a slider
|
||||
- Resting the pointer on a slider's name or its thumb now says that a double-click resets it ("Exposure — double-click
|
||||
to reset it"), in every language (issue #1436).
|
||||
- A double-click on the thumb is a single step in History and Undo. Its first click no longer nudges the value to
|
||||
where the pointer landed, and a single click on the thumb leaves the value alone.
|
||||
|
||||
### Slider drags on large raws
|
||||
- Dragging a slider no longer re-renders the edited photo's filmstrip thumbnail on every frame; it follows once you
|
||||
@@ -200,6 +454,23 @@
|
||||
|
||||
## 2026-10-11
|
||||
|
||||
### Keywords panel
|
||||
- The titles **Keywords** and **Keyword List** in the Keywords panel fold their sections shut and open again, so
|
||||
the list of every keyword is one click away however many keywords the selected photos have. What is folded is
|
||||
remembered.
|
||||
- Settings ▸ Interface ▸ Keywords of the selection ▸ **Grouped by parent** lays the selected photos' keywords out by
|
||||
the keyword they are inside: "Places › Italy" once, on a line of its own, with Rome, Venice and the others side by
|
||||
side under it. A long list stops after eight lines with "+N more", and the suggestions say only the keyword's own
|
||||
name. Whole names, one chip per keyword, stays the default.
|
||||
- A selection without keywords now says "No keywords yet" where its chips would be.
|
||||
- Typing in **Add keyword** offers the library's matching keywords right under the box. ↓ and Return (or a click)
|
||||
give the offered keyword and keep the cursor in the box for the next one; Return alone still adds what you typed.
|
||||
A name the library doesn't have is marked as a new keyword before you press Return, so a misspelling no longer
|
||||
becomes a keyword unnoticed. The suggestions further down stay put while you type.
|
||||
- With several photos selected, the Keywords panel says how many photos its keywords belong to. The × on a keyword
|
||||
is a larger target that lights up on its own, and taking a keyword off several photos at once now says which
|
||||
keyword left how many photos, and that Edit ▸ Undo puts it back.
|
||||
|
||||
### HDR and panorama merges of CR2 keep their colour
|
||||
- Photo Merge of Canon CR2 (and other raws whose colour LightCraft fits from the camera's own JPEG, such as NEF and
|
||||
ARW) gives the merged DNG the colour each photo has when opened alone (issue #965). An HDR merge of CR2s used to come
|
||||
@@ -218,6 +489,42 @@
|
||||
- Compare and Reference View panes say "Rendering…" (or that the photo can't be opened) the same way, so a
|
||||
magnified preview isn't taken for the photo when checking focus at 1:1.
|
||||
|
||||
### Lens corrections
|
||||
- Sony A7R VI (ILCE-7RM6) raws are corrected for lens distortion from the table the camera records in each file,
|
||||
under Optics ▸ Enable Lens Corrections, on by default for newly imported photos. On 33 photos shot with the camera's
|
||||
correction on (24–70 mm, 100 mm macro, 200–600 mm) the render lines up with the camera's JPEG within 0.68 px at
|
||||
1440 px at the corners, where it was up to 17 px off before. The camera's lateral chromatic aberration table is read
|
||||
too, but not applied by default: our demosaic already hides most of that colour fringing, and the table on top made
|
||||
it slightly worse. The vignetting table is read but not applied: the camera's own JPEGs don't apply it either. This
|
||||
covers lossless, Compressed and Compressed HQ (ARW 6.0) ARWs alike. The A7R IVA (ILCE-7RM4A) has its own distortion
|
||||
correction, checked against Sony's exports; other Sony bodies record the same tables, but they stay uncorrected until
|
||||
they are checked the same way. Photos imported earlier get the correction with Photo ▸ Reload from Disk (when still
|
||||
at their import settings). See `docs/sony-ilce7rm6-lens-corrections.md`.
|
||||
|
||||
### The thumbnail cache is no longer taken for your photos
|
||||
- LightCraft's cached thumbnails no longer show up in Windows Photos / Gallery or other photo apps as pictures of
|
||||
yours (issues #610, #1066). They were ordinary `.jpg` files in the library's `thumbs` folder, which is usually
|
||||
inside Pictures, so every thumbnail (one for each photo, size and state of its edits) was listed as a photo.
|
||||
They are now kept under a name that is no picture's. The ones already there are taken over, not rendered again:
|
||||
the first time a library opens after this update, "Tidying the thumbnail cache" shows in the activity stack
|
||||
while they are renamed (it can be stopped, and goes on at the next open).
|
||||
- Opening a library no longer rewrites the date of every thumbnail it shows, which made them all look new at each
|
||||
launch. Reading a thumbnail writes nothing (but for one that went unused for a week, whose date is brought
|
||||
forward); what was read is remembered for the session, so a full cache still lets go of what is not in use first.
|
||||
- A `thumbs` folder that holds nothing but the cache says that it is one (`CACHEDIR.TAG`), so backup programs that
|
||||
go by that can leave it out. It is safe to delete while LightCraft is closed, as before. A `thumbs` folder that
|
||||
also holds files of yours (a library opened on a photo folder that had one) is not tagged, and your files in it
|
||||
are left as they are. Note that files there named exactly like the cache's own (`ab/ab…` with 32 hex digits and
|
||||
`.jpg`) have always been taken for the cache's, and are renamed with it.
|
||||
- If you go back to an older version, it renders its thumbnails again as `.jpg`. This version then takes those
|
||||
over one by one as they are used; the rest stay until the cache makes room.
|
||||
|
||||
### Nikon raws without coloured edge bars
|
||||
- Raws from older Nikon bodies no longer show a thin coloured or dark bar along one edge (the right edge, or the top
|
||||
of a portrait photo): masked sensor columns were being developed as part of the picture (issues #976, #914). The
|
||||
D7000, D5100, D800, D800E, Df, D4, D3, D3S, D700, D300, D300S, D600, D610, D810, D4S, D5600, Coolpix A, D3000, D40X,
|
||||
D60, D80 and D2Xs now show the area the camera itself frames, a few pixels smaller than before.
|
||||
|
||||
### JPEG XL export
|
||||
- Export as JPEG XL (issue #247): Format ▸ JPEG XL in the Export dialog, `format: "jxl"` for agents and the CLI
|
||||
(`render in.raw -o out.jxl`). Quality as for JPEG, or Lossless; Effort (Fast / Normal) trades time for a
|
||||
@@ -227,6 +534,16 @@
|
||||
- Lossy JPEG XL files in Display P3 or Rec. 2020 now open in their real colours; saturated colours used to come in
|
||||
noticeably duller.
|
||||
|
||||
### Export next to the originals
|
||||
- The Export dialog has Export to: Specific folder (as before) or Same folder as original photo, like Lightroom
|
||||
Classic (issue #956). With the second, each photo is exported into the folder its original is in, plus the
|
||||
Subfolder if you give one (say `Exports`), so a batch from several folders lands next to each set of originals.
|
||||
"If file exists" works per folder as usual, and an original is never written over.
|
||||
- A photo that has no folder on disk (a demo photo, or one in the web version's browser storage) or whose folder
|
||||
is missing (moved, drive unplugged) is not exported; it gets its own error naming it.
|
||||
- The choice is saved in export presets and Export with Previous. Agents pass
|
||||
`destinationMode: "sameAsOriginal"` (or `"specificFolder"`) to `app.export`; `dir` is then not needed.
|
||||
|
||||
### Open Library knows a Lightroom catalog
|
||||
- Choosing a Lightroom Classic catalog folder in File → Open Library… (or one of its `Previews.lrdata` /
|
||||
`.lrcat-data` folders, or the `.lrcat`) no longer makes an empty LightCraft library inside it (issue #891). The
|
||||
@@ -284,6 +601,88 @@
|
||||
preset pickers in Import and Settings ▸ Import scroll the same way.
|
||||
- Importing a large collection and opening its library no longer compare every preset with every other.
|
||||
|
||||
### Slideshow export: PDF, JPEG and video
|
||||
- View ▸ Export Slideshow… (or the Export buttons at the end of Settings ▸ Slideshow) writes the slideshow out, like
|
||||
Lightroom Classic's Export PDF, Export JPEG and Export Video: the photos in view as their slides, with the layout,
|
||||
overlays and the intro and ending screens, in view order.
|
||||
- **PDF:** one page per slide at 1024, 1920 or 3840 pixels on the long side, at a JPEG quality you choose. Each page
|
||||
carries the slide duration and fade, so a PDF viewer's presentation mode plays it as a slideshow, and "Automatically
|
||||
show full screen" asks the viewer to open it that way.
|
||||
- **JPEG:** numbered files (`Holiday-001.jpg`, `Holiday-002.jpg`…) in a new folder.
|
||||
- **Video:** AV1 video in an MP4 (or WebM) file at 720p or 1080p, 24 or 30 frames per second: each slide stays up for
|
||||
its duration and the fades are rendered frame by frame (crossfades, or fades through the fade colour). The video has
|
||||
no sound yet. It is AV1 rather than Lightroom's H.264, which has no open encoder we can ship; current browsers,
|
||||
VLC and recent phones and TVs play it.
|
||||
- The export runs in the background with its row in the activity stack; ✕ stops it and leaves no half-written file
|
||||
behind. A photo that can't be read is skipped and named in the message at the end. Agents use `slideshow.export`
|
||||
(`slideshow.exportStatus` for the result).
|
||||
|
||||
### Slideshow templates
|
||||
- Settings ▸ Slideshow now opens with a template browser, like Lightroom Classic's Template Browser. A template holds
|
||||
everything about how a slideshow looks and plays: the playback timing and fades, the layout, options and backdrop,
|
||||
the overlays and the intro and ending screens. Click one to apply it; point at one to see it on the selected photo in
|
||||
the preview beside it without changing anything.
|
||||
- Five built-in templates of our own: Plain Black (the photo on black), Gallery Wall (a light wall, a white mat and a
|
||||
soft shadow, with the caption and rating under the photo), Edge to Edge (photos cropped to fill the screen), Cinema
|
||||
Wide (16:9 with black bars, the title in the corner, fades through black and a closing card) and Shooting Data (the
|
||||
exposure, ISO, focal length, camera and lens under each photo on a dark backdrop).
|
||||
- Save the current settings as a template of your own; right-click it to update it with the current settings, rename,
|
||||
export or delete it, and import templates others share with you. Your templates are `.json` files in the settings
|
||||
folder's `slideshow-templates` folder, shared by all your libraries.
|
||||
- Applying a template can't be undone with Edit ▸ Undo (slideshow settings are library preferences), so the settings it
|
||||
replaced are listed as "Previous settings" until you quit: click that to go back.
|
||||
- A template file that can't be used (damaged, from a newer LightCraft, too large) is listed as skipped instead of
|
||||
stopping the others, and a template whose identity plate image or background photo isn't there still applies, with a
|
||||
note saying what is missing. Agents use `slideshow.templates.*`, and `slideshow.preview {template}` renders a template
|
||||
without applying it.
|
||||
|
||||
### Slideshow intro and ending screens
|
||||
- A slideshow can now open with an intro screen and close with an ending screen, like Lightroom Classic's Titles
|
||||
panel. Each is switched on on its own and has a background colour and, centred on it, your identity plate (the one
|
||||
set under Overlays: its text or image) or a line of text of its own, in the plate's colour or one you pick, at a
|
||||
scale. Each stays up for its own duration (by default the slide duration) and fades in and out like a slide.
|
||||
- The intro plays once before the first photo; the ending after the last photo when Repeat is off (while repeating
|
||||
the show runs until you stop it, so the ending doesn't come up). Random order never moves them, ←/→ step across them,
|
||||
and the control bar says Intro or End while one is up (the photo count only counts photos).
|
||||
- Set them in Settings ▸ Slideshow ▸ Titles; the preview there switches between the photo's slide, the intro and the
|
||||
ending. They are saved with the library. Agents use `slideshow.titles`, and `slideshow.preview {title: "intro"}`
|
||||
renders a screen as a PNG.
|
||||
|
||||
### Slideshow overlays
|
||||
- Slides can now carry Lightroom Classic's Slideshow overlays: an identity plate (a line of text in a colour, or an
|
||||
image file such as a PNG logo with transparency, at a size and opacity, optionally drawn behind the photo), the
|
||||
photo's rating as stars, and any number of text overlays (up to 16) built from tokens: `{caption}`, `{title}`,
|
||||
`{file}`, `{date}`, `{exposure}` ("1/250 s at f/8"), `{iso}`, `{focal}`, `{camera}`, `{lens}`, `{rating}` and the
|
||||
other file-naming tokens, with a size, colour, opacity and an optional soft shadow (opacity, offset, radius, angle).
|
||||
Each sits at one of nine anchors of the slide or of the photo, moved by an offset, and never leaves the slide.
|
||||
- The export watermark can be drawn on every slide's photo too ("Use export watermark" takes the one you last
|
||||
exported with).
|
||||
- Set them in Settings ▸ Slideshow ▸ Overlays; the slide preview there and View ▸ Slideshow show them. Sizes are a
|
||||
share of the slide, so slides look the same on any screen. They are saved with the library. Agents use
|
||||
`slideshow.overlays`; `slideshow.preview` now also returns where each overlay landed.
|
||||
|
||||
### Slideshow layout, options and backdrop
|
||||
- Slides can now be laid out like Lightroom Classic's Slideshow Layout, Options and Backdrop panels: margins (all four
|
||||
linked, or each on its own), Zoom to Fill Frame (crop the photo to fill its cell), a stroke border (colour, width),
|
||||
a cast shadow (opacity, offset, radius, angle), and a backdrop colour with an optional colour wash (a gradient from a
|
||||
second colour, at an angle and opacity) and a background image (a photo from the library, at an opacity).
|
||||
- Set them in Settings ▸ Slideshow, which now shows the selected photo as a slide as you change them (with the margin
|
||||
guides, at the screen's aspect or 16:9 / 4:3). Sizes are a share of the slide, so a slide looks the same on any
|
||||
screen. They are saved with the library.
|
||||
- View ▸ Slideshow plays the composed slides, prepared ahead off the UI thread like before, so fades and the playback
|
||||
controls work as they did. With the default layout (no margins, border, shadow or backdrop) it plays the photos as
|
||||
before. Agents use `slideshow.layout`, and `slideshow.preview` returns one composed slide as a PNG.
|
||||
|
||||
### Slideshow playback
|
||||
- View ▸ Slideshow (⌥⌘↩) now plays with Lightroom Classic's Playback settings: how long each slide stays up, a fade
|
||||
between slides (a crossfade, or through black, white or any colour; 0 cuts), random order (every photo once per
|
||||
pass, a new order each time round), repeat (off: the slideshow ends after the last photo) and preparing previews in
|
||||
advance (the next two slides render while the current one is up, so a fade never waits or flashes).
|
||||
- Change them in Settings ▸ Slideshow (View ▸ Slideshow Options…); they are saved with the library. Agents use
|
||||
`slideshow.playback`; `view.slideshow` takes any of them for one run (`interval` still sets the slide duration).
|
||||
- While it plays, moving the pointer shows a small control bar: previous, play / pause, next, the slide number and
|
||||
end. Space pauses, ← / → step (a cut), Esc ends. A slide's time starts once it is shown sharp.
|
||||
|
||||
## 2026-10-10
|
||||
|
||||
### Dialogs fit the window
|
||||
|
||||
+48
-4
@@ -147,7 +147,18 @@ Values pass through our control specs, so anything outside our slider ranges get
|
||||
|
||||
`crs:CameraProfile` is kept as the selected name in the photo's import warning and the active profile is left as it is: the name carries no rendering data and never selects an Adobe profile. Import reports such a profile as not applied (colours may differ from Lightroom), except Lightroom's default profiles (`Adobe Standard`, `Adobe Color`), which every sidecar names and which LightCraft's own starting look stands in for.
|
||||
|
||||
**Not mapped:** camera profiles and looks (`CameraProfile`, `Look`; we have our own profile set), red eye, lens blur,
|
||||
**Profiles named by presets (`Look`, issue #1001).** A preset keeps the profile it names (`crs:Look`: `Name`, `Group`,
|
||||
`UUID`, `Amount`; in `.lrtemplate` files the `Look` table) as `profile.look` in its settings. When the user has imported
|
||||
a profile of that name (`profile.import`; the name compared ignoring case and repeated spaces, the group breaking
|
||||
ties), applying the preset selects it at the look's amount (`Amount` 1 = 100 %). Lightroom's basic profiles map to our
|
||||
own (`Adobe Color` → Color, `Adobe Neutral`, `Adobe Vivid`, `Adobe Landscape`, `Adobe Portrait`, `Adobe Monochrome`
|
||||
→ Monochrome). Any other `Adobe …` / `Camera …` profile and the numbered creative ones (`Artistic 01`, `B&W 05`,
|
||||
`Modern 10`, `Vintage 02`) can't be used here, and a third-party profile not imported yet leaves the photo's profile as it
|
||||
is; import reports either per preset (`Profile “Name” (Lightroom's own)` / `(not imported yet)` in `unmapped`).
|
||||
References are resolved again whenever profiles are imported or deleted, so a pack's profiles and presets can come in
|
||||
either order. The look's embedded `Parameters` are not read.
|
||||
|
||||
**Not mapped:** camera profiles (`CameraProfile`; we have our own profile set), red eye, lens blur,
|
||||
process-version 2010 field names, and AI features. Local adjustments and spot removal are read as described below.
|
||||
|
||||
## Spot removal
|
||||
@@ -181,24 +192,57 @@ mask: `CorrectionName` → name, `CorrectionAmount` → Amount, inactive correct
|
||||
| `LocalExposure2012` | `adjust.exposure` | stored as a fraction, ×4 EV |
|
||||
| `LocalContrast2012`, `LocalHighlights2012`, `LocalShadows2012`, `LocalWhites2012`, `LocalBlacks2012`, `LocalClarity2012`, `LocalTexture`, `LocalDehaze`, `LocalTemperature`, `LocalTint`, `LocalSaturation`, `LocalHue`, `LocalSharpness`, `LocalLuminanceNoise`, `LocalMoire`, `LocalDefringe`, `LocalToningSaturation` | the matching `adjust.*` | stored −1..1, ×100 |
|
||||
| `LocalToningHue` | `adjust.color_hue` | degrees |
|
||||
| other `Local*` sliders (`LocalGrain`…) | — | no counterpart in our masks: reported as `Mask: LocalGrain` when set (`LocalCurveRefineSaturation` 100 is neutral) |
|
||||
| `Mask/Gradient` (`FullX/Y`, `ZeroX/Y`) | linear gradient | full effect at the Full point |
|
||||
| `Mask/CircularGradient` (`Top/Left/Bottom/Right`, `Angle`, `Feather`, `Flipped`) | radial gradient | box fractions → long-edge radii (presets assume 3:2; sidecars use the photo's shape); `Flipped` → invert |
|
||||
| `Mask/CircularGradient` (`Top/Left/Bottom/Right`, `Angle`, `Feather`, `Flipped`) | radial gradient | box fractions → long-edge radii (presets assume 3:2; sidecars use the photo's shape). `Flipped="true"` means effect inside: in `MaskGroupBasedCorrections` with `Version` 2 (what Lightroom writes for an ordinary radial) and in the legacy `CircularGradientBasedCorrections` Radial Filter, whose default (no `Flipped`) is outside. A `MaskGroupBasedCorrections` radial without `Version` is inside whatever `Flipped` says, and its `Feather` is halved (Lightroom rescales it that way when it upgrades one). Inverting is `MaskInverted` |
|
||||
| `Mask/Paint` (`Dabs` "d x y", `Radius`, `Flow`, `CenterWeight`, `MaskValue`) | brush | one brush component per correction; `MaskValue` ≤ 0 erases |
|
||||
| `Mask/Image` `MaskSubType` 1 / 2 | Subject / Sky | other AI selections are reported, not guessed |
|
||||
| `Mask/RangeMask` `Type` 2 / 3 (`LumRange`, `DepthRange`) | luminance / depth range | lightness converted to our range scale; colour ranges are reported |
|
||||
| `Mask/RangeMask` `Type` 2 / 3 (`LumRange`, `DepthRange`) | luminance / depth range | lightness converted to our range scale; a range at full strength at white (third `LumRange` value 1) stays open above our scene white; colour ranges are reported |
|
||||
| `MaskBlendMode` 0 / 1 / 2, `MaskInverted` | add / subtract / intersect, invert | |
|
||||
|
||||
Applying a preset adds its masks to the photo's own (masks the photo already has are not added twice), and the Amount
|
||||
slider scales them. A sidecar's masks replace the photo's, because a sidecar holds the whole edit. Components we can't
|
||||
carry over are listed in `preset.import`'s `unmapped` as `Mask: <kind>`.
|
||||
|
||||
## Local adjustment presets (mask effects)
|
||||
|
||||
`mask.importEffects {path | paths, group?, dryRun?}` (and `preset.import`, File ▸ Import Profiles & Presets…, drag & drop)
|
||||
reads these into the Masking panel's Effect menu (`crates/engine/src/cmd/mask_effect_files.rs`):
|
||||
|
||||
| File | How it is read |
|
||||
|---|---|
|
||||
| Lightroom Classic `.lrtemplate` (`%APPDATA%\Adobe\Lightroom\Local Adjustment Presets`, `~/Library/Application Support/Adobe/Lightroom/Local Adjustment Presets`) | a Lua table with `type = "LocalizedAdjustmentPreset"`; `title` (else `internalName`, else the file name) → name; `value` holds the `Local*` field names in lower camel case: `exposure2012` → `LocalExposure2012`, mapped as in the table above (`exposure`, `contrast`, `clarity` are the older process version's; the 2012 fields win); `luminanceNoise` → Noise, `toningHue` / `toningSaturation` → Color |
|
||||
| Camera Raw local-correction `.xmp` (`CameraRaw/LocalCorrections`) | top-level `crs:Local*` properties (or, in a file with `crs:PresetType="Local"` without them, its first correction's); `crs:Name` → name, `crs:Group` → group. Develop presets (no `crs:Local*`) stay develop presets |
|
||||
| `.lceffect` | ours: `{"format": "lightcraft.maskEffects", "version": 2, "effects": [{name, adjust, group?, favorite?, fields?, with_amount?, brush?, extra?}]}` (a bare array or one effect also reads); `mask.exportEffects {path, names?, group?}` writes it |
|
||||
| `.zip` | the presets above inside it; its folders give groups |
|
||||
|
||||
Groups: a file's folder (relative to the imported folder; names that only say "local adjustment presets" don't count)
|
||||
names its group, unless the file names one. Lightroom users mark sections of the flat preset menu with **divider
|
||||
presets**: presets that set nothing, named like `10 ----- DETAIL ENHANCERS ----- 10` (a run of three or more `-`, `=`,
|
||||
`_`, `*`, `#`, `~`, `—`, `.`). These become groups instead of effects: a preset whose name starts with a number goes to
|
||||
the divider with the largest number not above it (`12 Sky` under `10 ----- DETAIL ENHANCERS ----- 10` → *Detail
|
||||
Enhancers*); presets without a number keep their folder's group. An earlier import's divider effects are removed.
|
||||
Same-named effects are replaced (a star is kept).
|
||||
|
||||
Settings with no local slider here are listed per preset in `unmapped` (and the toast) and **kept** with the effect in
|
||||
`extra` (an `.lceffect` export carries them), but not applied: `grain` (Grain; LightCraft has no local grain),
|
||||
`pointColors` (Point Color: `SrcHue/Sat/Lum`, `HueShift`, `SatScale`, `LumScale`, `RangeAmount`, `Hue/Sat/LumRange`
|
||||
`{LowerNone, LowerFull, UpperFull, UpperNone}`; there is global Point Color only), `toningLuminance`. Zero values aren't
|
||||
listed (`refineSaturation = 0` in most files). Lightroom keeps brush size, feather, flow and density per brush, not in
|
||||
presets, so there is nothing to import for them; an effect saved here can carry them (`brush`).
|
||||
|
||||
Applying (`mask.applyEffect {name, id? | ids? | all?, photos?: "selected"}`) sets the sliders the effect carries —
|
||||
all of them for an imported preset (unnamed ones to 0, as Lightroom does), or only the ones chosen when it was saved
|
||||
(`mask.saveEffect {fields: "changed" | [..]}`) — and Amount only if it carries it. The effect is remembered for the
|
||||
mask's kind: the next brush / linear / radial / … mask starts with it (`mask.toolEffect`).
|
||||
|
||||
## Preset files
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Ours: `.lcpreset` | JSON `{"format": "lightcraft.preset", "version": 1, "presets": [{id, name, group, settings}]}`, where `settings` is a partial develop-settings object (only the groups the preset includes). A file can hold one preset or many, and every preset keeps its group. Import also accepts a bare preset object or an array of them. |
|
||||
| Export | `preset.export {path, ids?, group?}`: all user presets by default, or the given ids or one group. In the app: File ▸ Export Presets…, Presets panel ▸ ⋯ ▸ Export User Presets…, or right-click a group ▸ Export Group…. |
|
||||
| Import | `preset.import {paths, group?, dryRun?}`: files or folders (recursive): `.lcpreset`, `.xmp`, classic `.lrtemplate` (a Lua table: `value.settings` holds the same field names as `crs:`), photos that carry their edits in XMP ("DNG presets" from mobile apps; their crop, geometry and custom white balance are left out) and `.zip` bundles of any of these. Presets in a folder (or a folder inside a zip) go to a group named after it, unless the file names its own group. The result lists, per preset, the settings that couldn't be carried over (`unmapped`, e.g. `CameraProfile`, `Look`, local masks), and the app's toast names them; fields that only describe the preset or the photo (`Cluster`, `SortName`, `Description`, `SupportsAmount2`, `RequiresRGBTables`, `CropConstrainToWarp`, `OverrideLookVignette`, `AsShotTemperature` / `AsShotTint`, empty `PointColors` slots) aren't listed. Older (process version 2010) fields — `Exposure`, `Contrast`, `FillLight`, `HighlightRecovery`, `Shadows`, `Brightness`, `Clarity`, `ToneCurve` — are approximated with today's sliders when a preset has no 2012-era fields. Dropping preset files on the window imports them too. In the app: File ▸ Import Presets…, or Presets panel ▸ ⋯ ▸ Import Presets…. A preset that's already there (same name, group and settings) is skipped. If an id clashes, the import gets a fresh `user.*` id, and built-in presets are never replaced. |
|
||||
| Import | `preset.import {paths, group?, dryRun?}`: files or folders (recursive): `.lcpreset`, `.xmp`, classic `.lrtemplate` (a Lua table: `value.settings` holds the same field names as `crs:`), photos that carry their edits in XMP ("DNG presets" from mobile apps; their crop, geometry and custom white balance are left out) and `.zip` bundles of any of these. Local adjustment (brush) presets — Lightroom Classic's `.lrtemplate` with `type = "LocalizedAdjustmentPreset"`, Camera Raw's local-correction `.xmp`, our `.lceffect`, also inside zips — become mask effects (`mask.effects`) instead (see *Local adjustment presets* below); the result lists them under `effects`, and divider presets under `effectDividers`. Presets in a folder (or a folder inside a zip) go to a group named after it, unless the file names its own group. The result lists, per preset, the settings that couldn't be carried over (`unmapped`, e.g. `CameraProfile`, a profile named by `Look` that isn't imported, local masks), and the app's toast names them; fields that only describe the preset or the photo (`Cluster`, `SortName`, `Description`, `SupportsAmount2`, `RequiresRGBTables`, `CropConstrainToWarp`, `OverrideLookVignette`, `AsShotTemperature` / `AsShotTint`, empty `PointColors` slots) aren't listed. Older (process version 2010) fields — `Exposure`, `Contrast`, `FillLight`, `HighlightRecovery`, `Shadows`, `Brightness`, `Clarity`, `ToneCurve` — are approximated with today's sliders when a preset has no 2012-era fields. Dropping preset files on the window imports them too. In the app: File ▸ Import Presets…, or Presets panel ▸ ⋯ ▸ Import Presets…. A preset that's already there (same name, group and settings) is skipped. If an id clashes, the import gets a fresh `user.*` id, and built-in presets are never replaced. |
|
||||
| XMP presets | Read with the `crs:` table above, with `crs:Name` as the name (falling back to the file name) and `crs:Group` as the group (falling back to "Imported Presets"). Only the fields the preset sets are included, so applying it leaves everything else alone and the Amount slider scales it like any other preset. We only read XMP presets; we don't write them. |
|
||||
|
||||
LightCraft ships no third-party presets. Its built-in presets are its own values (`crates/engine/src/presets.rs`).
|
||||
|
||||
Reference in New Issue
Block a user