Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, model-by-model RAW coverage against Adobe's camera list (docs/raw/), and format, hardware, UI and localization parity docs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge origin/main into #560 (fit_preview / camera-look refactors of #528, #583, #568, #616).
`starting_colour` now tries the per-file camera-JPEG fit (with the camera profile when there is
one) first and uses the spectral-sensitivity matrices only when that fit fails, before the neutral
fallback, so no photo with an accepted JPEG fit changes. Tests pin the order through an injectable
fit; docs, parity, ROADMAP and what's new describe it. RENDER_CACHE_VERSION 37 -> 38.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Synchronize Folder (#604) shows its scan ("Looking for changes", while
its dialog is open) and its run ("Synchronizing folder") as rows: the
scan's cross stops it and closes the dialog, the run's stops it like
Cancel did (what was done stays, as one undo step; the end says Stopped).
Its progress window is gone. The contact-sheet PDF export (#563), which
went through the export task already, gets a test for its row.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LR-BEHAV-BG-TASKS now cites activity.list / activity.cancel and lists
every job on the stack; the import and Build Previews rows no longer
describe progress windows and toasts; a what's-new entry.
Fixes the stack not growing when tasks arrive while it already shows a
row (an egui area lays out in last frame's size, and the scroll area took
that as all the room, so later rows were cut off), and adds the Russian
"Quit Anyway".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Canon's SensorInfo left border is not where light starts: on every corpus
body 10-36 columns left of it already hold image (EOS 6D: masked columns
0-70, border 84), and the black level was averaged over all of them. The
6D read 2591 instead of 2047 (4 % of the range), so CR2s rendered dark with
crushed shadows; 40D +141, 5DS R +131, 5D Mark II +73. The masked run is
now measured from the data: columns whose mean stays within 1/256 of the
range of the leftmost columns', minus a two-column margin.
Against Lightroom Classic (EOS 6D still life, 2000 px, ΔE00): base 7.63 ->
5.23 (p95 24.7 -> 11.3); mean over 86 edit variants abs 9.13 -> 6.19,
effect 3.09 -> 2.75.
RENDER_CACHE_VERSION 23.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ORF decoder supplies the as-shot white balance (ImageProcessing
WB_RBLevels) and no colour matrix, like ARW, NEF, RW2, RAF, CR2/CR3, PEF
and SRW, but ORF was left out of camera_preview::file_local_look and the
catalog's relative_wb, so it rendered with the neutral fallback matrix:
flat, grey and dark. It now gets the same guarded fit to its camera JPEG
and white balance relative to the as-shot look. Corpus (held-out RMS
against the fallback, all accepted): E-1 0.126 -> 0.014, E-400 0.087 ->
0.022, XZ-2 0.061 -> 0.023; compressed ORFs still open from their preview.
Against Lightroom Classic (CC0 E-1 kit, 2000 px, ΔE00): unedited render
11.25 -> 8.30; mean over 86 variants abs 12.10 -> 9.48, effect 3.44 ->
2.80. Every other kit's unedited render is byte-identical.
RENDER_CACHE_VERSION 23.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The docs claimed only a sidecar written here before auto-write was
turned off could be mistaken for an update; in fact the library only
knows when a photo came in or was last developed, so any later rating,
label or metadata change made here can be. Says so, with the headless
fixed clock, the sidecar naming fallback and the walk's limits; the
parity row and what's new also cover relinking moved files, Local
files, offline folders and the `disk` guard. Adds the test that a
sidecar the library auto-wrote is never an update.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LRC-LIB-LIBFOLDERS lists folder.label and the Set Color Label menu, with
its limits (no filter or sort by folder label; labels don't follow a
folder moved outside LightCraft). What's new describes the feature and
catalog format v4. The roadmap notes folder records as the first step
towards Classic's folder-id model and when the next step would pay off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
heic-rs reconstructs iPhone HEVC tiles bit-exactly (checked against libde265), but
its colour stage was 2-27 code values off libheif on every iPhone photo: it ignores
the HEVC VUI and assumes BT.709 limited range. lightcraft-heif now converts YCbCr
itself (nclx, else VUI, else H.265 defaults; nearest chroma, bilinear for odd clap
offsets, as libheif), inherits tile ICC/nclx on grids, follows libheif's imir axis
and clap rounding, and outputs 16-bit RGB. Measured on 30 real and synthetic
files: within 1 code value of libheif (pillow-heif 1.8 / libheif 1.23).
Also: HEIF header reader for import (no pixel decode), embedded thumbnail for small
decodes, nclx/VUI colour hint (shared CICP mapping with PNG), clear 4:2:2/4:4:4
Unsupported error, Format::not_decodable as the one source of "why not" (import
reports "HEIC/HEIF support isn't included in this build"), `.heif` imports.
Release packaging and Nix build with the heif feature, as whats-new promised.
lightcraft_heif::testdata writes lossless (PCM) synthetic HEICs for the tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What's New now says that an unreadable list names its line or asks for
UTF-8, and that export names any keyword it had to leave out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parity row covers File ▸ Import / Export Keywords… and the apps
that share the format, and lists what stays open (IPTC keywords in
exported files, hierarchy from other apps' XMP fields); What's New
explains it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The keyword rows of the parity tracker describe the box and the chip
menu; What's New explains the chips, Will Export and what follows the
selection.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lightroom Classic 15.6 imports an XMP packet's channel curves only when it holds
ToneCurvePV2012 and all three of ToneCurvePV2012Red/Green/Blue; any partial set
(master + one or two channels, channels without the master) imports without
channel curves. #416 read them whenever the master curve was present.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parity row said Person shapes exported files: it is stored only.
It now also covers the list without a selection, the default parent's
reach (typed keywords too) and keywords' hierarchy on import. The
synonyms' doc no longer says search finds them, which it doesn't yet.
What's New follows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The LRC-LIB-KEYWORDS row lists the Keyword List, its commands and what
isn't there yet; LR-LIB-KEYWORD no longer says keywords can't be
dragged. What's New describes the list, its dialogs, drag and drop and
the export options.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Previews were always sRGB, which wide-gamut monitors show oversaturated.
Settings > Display > Choose Profile... (and the UI command
app.displayProfile) now shows photos through the monitor's ICC profile,
matrix/TRC or LUT-based.
- codecs: DisplayProfile (moxcms): the display's primaries (colorant tags,
or measured through the A2B tables of a LUT-only profile), the proxy ->
device correction (per-channel curve tables for matrix/TRC profiles, a
CMS transform for LUT profiles) and sRGB <-> display transforms.
- pipeline: DisplaySpace / RenderRequest::display: the per-pixel stage
renders into the display's primaries and gamut maps into its gamut
(CPU and GPU: only to_out / out_luma change). Soft proofing's display
gamut warning uses the display's gamut.
- engine: RenderJob::with_display; display::present converts sRGB
results (thumbnails, cached previews, embedded JPEGs). Histograms and
the preview caches stay sRGB; exports are unchanged.
- ui: the loupe, Before, Compare, hover and second window render for the
display; everything else is converted on the render workers. Settings >
Display tab, ui.json setting, file picker opening in the system's ICC
folder.
Tests: profile parsing and transforms (sRGB, P3, gamma 2.2, a synthetic
LUT-only profile, corrupted files), display renders equal 8-bit renders
into the matching output space, sampled histograms, and a headless UI test
of the whole flow. docs/display-profiles.md describes the design.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WEuxxPyG8t6KcADbZSEAUj
New Album, Rename Album, New Smart Album, Merge Keywords and the text
prompts (rename a preset or a version, …) had Rename Keyword's bug:
their field took the focus back on every frame, so egui never reported
the focus Return gives up, and Return did nothing; only OK confirmed.
All six now use one `dialog_field`: a shared text field that keeps the
focus except while its own menu has it, opens with its text selected
and reports Return. They get the Cut / Copy / Paste / Select All menu.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What's New and the KEY-CLIPBOARD row overstated the Windows / Linux
fix: Ctrl+V reaches the app only while the system clipboard holds text
(egui-winit drops it otherwise), and it never worked before, so not
"again". The text field's module doc says what it depends on, that its
widget id must be unique on screen, and that new text boxes use it; MCP
`click` lists `button`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A parity row (🟡: three fields use it so far, the rest still use
egui's own) with the summary refreshed, and What's New for the menu,
Esc and Ctrl+C / Ctrl+V on Windows and Linux.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A raw without colour matrices of its own now gets DNG ColorMatrix1/2 and
ForwardMatrix1/2 for its model when the model is one of the 52 cameras
in rawtoaces-data (Academy Software Foundation, Apache-2.0): 22 Canon,
11 Nikon, 11 Sony, 3 Fujifilm and 5 others, plus the other names its
alias list gives (Rebel T3i and Kiss X5 for the EOS 600D; bodies it
lists as sharing a sensor). tools/spectral_camera_table.py fits, under
Standard Illuminant A and D65, a white-preserving 3x3 to the measured
spectral sensitivities over rawtoaces-data's 190 training reflectances
and writes crates/raw/src/spectral_table.rs. No number comes from Adobe
or from a raw decoder. lightcraft_raw::spectral looks a camera up by
Exif make and model; the DNG colour model does the rest.
camera_preview::starting_colour takes the first available of: the
file's own matrices, a camera profile for the model (fitted to the
JPEG for tone), the spectral matrices, the file-local JPEG fit, the
neutral fallback. A profiled model whose profile fit fails takes its
spectral matrices. White balance stays relative to the as-shot look for
every raw without matrices of its own, so Photo::relative_wb and the
controls are unchanged; calibrate still pools covered models.
Tests: one per precedence step (synthetic), the table's lookup, aliases
and DNG shape, and a corpus test of the order on ILCE-7M4 (profile),
EOS 5D Mark III and D5100 (spectral), EOS 7D (own fit) and a DNG. The
ILCE-7RM2 and GFX100S corpus tests now expect the spectral matrices.
Attribution in assets/ATTRIBUTION.md and NOTICE. RENDER_CACHE_VERSION 23.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parity rows cite panels/right.rs, where the field lives, and say
that it applies on Return or leaving it, that Esc keeps the old angle
and that it takes a decimal comma; the Angle slider row points to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From final review: the problem-message example ("rule 2.1: rating is
0–5, not 9") predated the rating check's rewording ("no rating 0–5 is
9"); two doc comments still said Album rules take a plain album; and
What's New described the Album rule's old flat list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>