Commit Graph
983 Commits
Author SHA1 Message Date
bflatastic 6eb04f9a1c Merge PR #1119
# Conflicts:
#	docs/whats-new.md
2026-10-13 11:02:52 +07:00
bflatastic c7e259b3ce Merge PR #1297
# Conflicts:
#	docs/parity-checklist.md
#	docs/raw-parity.md
#	docs/whats-new.md
2026-10-13 11:02:49 +07:00
bflatastic bcbcf3b968 Merge PR #1357
# Conflicts:
#	docs/parity-checklist.md
#	docs/raw-parity.md
#	docs/whats-new.md
2026-10-13 11:02:48 +07:00
bflatastic 695eb6acc5 Merge PR #1282
# Conflicts:
#	docs/parity-checklist.md
2026-10-13 11:02:44 +07:00
bflatastic 5e430d057f Merge PR #1301 2026-10-13 11:02:40 +07:00
bflatastic 9e0f00c557 Merge PR #1222
# Conflicts:
#	docs/parity-checklist.md
2026-10-13 11:02:40 +07:00
bflatastic 33f03ba0f7 Merge PR #1094
# Conflicts:
#	crates/pipeline/src/spots.rs
#	docs/gaps.md
#	docs/hardware-parity.md
2026-10-13 11:01:54 +07:00
bflatastic 18bd8fd881 Merge PR #1397
# Conflicts:
#	docs/whats-new.md
2026-10-13 11:01:53 +07:00
bflatastic a39567306b Merge PR #1071
# Conflicts:
#	docs/parity-checklist.md
2026-10-13 11:01:52 +07:00
bflatastic 14b111f6f5 Merge PR #1344
# Conflicts:
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-13 11:01:49 +07:00
bflatastic d3d55e8327 Merge PR #1413
# Conflicts:
#	docs/whats-new.md
2026-10-13 11:01:48 +07:00
bflatastic ecf1236b7c Merge PR #1150
# Conflicts:
#	docs/whats-new.md
2026-10-13 11:01:46 +07:00
bflatastic f28b9c46d3 Merge PR #1051
# Conflicts:
#	crates/pipeline/src/spots.rs
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-13 11:01:45 +07:00
bflatastic 6aabe43386 Merge PR #1023
# Conflicts:
#	ROADMAP.md
#	crates/pipeline/src/spots.rs
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-13 11:01:44 +07:00
bflatastic b9b6bf57de Merge PR #1020
# Conflicts:
#	docs/parity-checklist.md
2026-10-13 11:01:43 +07:00
bflatastic 64b3361125 Merge PR #1340
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-13 11:01:42 +07:00
bflatastic 44684b7950 Merge PR #1288
# Conflicts:
#	docs/parity-checklist.md
#	docs/raw-parity.md
#	docs/whats-new.md
2026-10-13 11:01:41 +07:00
bflatastic 61c3042efe Merge PR #1280
# Conflicts:
#	docs/parity-checklist.md
#	docs/raw-parity.md
#	docs/whats-new.md
2026-10-13 11:01:40 +07:00
bflatastic 2fc2419fa1 Merge PR #1193
# Conflicts:
#	docs/parity-checklist.md
2026-10-13 11:01:37 +07:00
bflatastic 5cec4d0720 Merge PR #992 2026-10-13 11:01:10 +07:00
bflatastic 1543fef701 Merge PR #1268 2026-10-13 11:01:01 +07:00
bflatastic ac19325c57 Merge PR #978 2026-10-13 11:01:01 +07:00
bflatastic b56f052a59 Merge PR #1387 2026-10-13 11:00:58 +07:00
bflatastic b2a5997e55 Merge PR #1412 2026-10-13 11:00:53 +07:00
bflatastic 43799cc903 Merge PR #1296 2026-10-13 11:00:48 +07:00
bflatastic a6369c4009 Merge PR #1264 2026-10-13 11:00:47 +07:00
bflatastic c9e12bd9ff Merge PR #1123 2026-10-13 11:00:41 +07:00
dev-null-undefinedandClaude c8f676252f M5.6: with a GPU, a slider drag's preview is drawn in the frame of the drag tick
A drag tick requested the loupe's draft and the frame ended; the draft,
done in 1.5-3 ms on the GPU, was picked up at the start of the next frame,
a frame after the slider moved. Now, in a drag, the loupe waits up to 40 %
of a frame for its draft when the last loupe render took well under that
(not with a render offload, nor zoomed in, where what changes on screen is
the window's draft). A CPU render, which would only make the frame late, is
not waited for.

JobPool::wait waits for the next finished job, which try_recv then hands
out; Renderer::poll's collection of finished jobs is split out so the wait
can turn the draft into the texture.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-13 03:40:23 +02:00
Nathaniel LedfordandClaude Opus 5.5 58822f6229 LR-BEHAV-LOCALIZE: strong text is heavier in scripts whose fallback face is a variable font
The semibold family had a semibold Inter but, for other scripts, the same
regular craft-fonts faces as regular text, so a heading or the chosen tab
in Arabic was drawn at regular weight beside bold Latin.

A fallback face with a weight axis (today Noto Sans Arabic, 100 to 900)
is now registered a second time for the semibold family at weight 600,
through epaint's FontTweak::coords. The bytes are borrowed from the
embedded font, not copied. Faces with one fixed weight, regular and
monospace text, the order of fallbacks and Latin are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:15:57 -04:00
Marco Arnulfo e1b29a3fd4 LR-IMP-CAMERA-COVERAGE: Nikon D7100 NEFs develop at Lightroom's frame, so its crops line up (fixes #1248) 2026-10-13 02:16:52 +02:00
dev-null-undefinedandClaude a99c084805 M5.6: a slider drag no longer decodes the edited photo's thumbnail
Each drag tick changed the edited photo's settings, so the filmstrip asked
for a new thumbnail render every frame. For an unedited raw shown with its
embedded preview, the thumbnail-level source had never been decoded, so each
of those renders decoded the whole raw (a 64 MP ARW: over a second), several
side by side, and the loupe's drafts queued behind them.

- The edited photo's thumbnail is not re-rendered during a slider drag while
  it has one; it follows once the drag ends.
- A thumbnail of a photo whose preview-level source is decoded (the one in
  the loupe) is cut from that source (SourceRef::Fit) instead of decoding the
  file again; not when the photo has a denoised picture.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-13 00:29:45 +02:00
Marco Arnulfo c07035c444 CR2: as-shot white balance of the PowerShot G9 from its WBInfo preset rows (part of #1273) 2026-10-13 00:04:47 +02:00
Marco Arnulfo 5eee65edac ORF: black level from the main maker note for bodies without ImageProcessing; gate and bound the 0x1017/0x1018 gains (part of #1273) 2026-10-12 22:48:34 +02:00
PiMinusMaxandClaude Opus 5.5 d9006c96f6 LR-EDIT-COLOR-TEMP: Kelvin white balance from Sony's white-balance presets
Sony ARWs of cameras without measured colour matrices were edited on the
relative scale (6500 K / 0 = as shot). Their SR2SubIFD stores the
multipliers of the camera's presets at 2500, 3200, 4500, 6000 and 8500 K;
lightcraft_raw::kelvin_presets reads the as-shot multipliers on the curve
through them and they take the spectral matrices' place in the #730
design (as-shot Kelvin and tint only; look, Bradford adaptation and the
pixel-identical legacy upgrade unchanged).

Covered: ILCA-99M2, ILCA-77M2, SLT-A33, DSC-RX10, ILCE-3500, ILCE-7S.
Kelvin-dial shots read back 3400 -> 3396, 5200 -> 5193, 4700 -> 4708,
5600 -> 5594 K; Shade 7493 K. Off-curve constants (isotherm tilt 0.74,
tint spacing 1) measured from the 14 Sony bodies with both spectral
matrices and presets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:37:22 +02:00
Alex ChambersandCodex 1926c9029f LR-PROF-CAMERACOLOR: cover the held-out toe error gate
Add correlated dark holdouts that reject misleading training and accept
matching training. Check finite, monotone curves in both cases. Confirm
the regression fails with the error gate removed and passes when restored.

Qualify the improvement claim when no original curve can be fitted, and
explain the source-look process policy and offline smart preview refresh.

Co-Authored-By: Codex <noreply@openai.com>
2026-10-12 22:27:31 +02:00
Alex ChambersandCodex c11764a12a LR-PROF-CAMERACOLOR: fit the camera toe from dark JPEG tones
Use separate luminance pairs for tone fitting so the camera look follows
its JPEG into deep shadows. Keep colour pairs and holdouts unchanged.
Require enough correlated shadow samples and lower held-out error, with
noise and compression floors and the existing median curve fit.

Add synthetic regressions, bump look and render cache versions, and
record the public multi-make and private numeric validation in the docs.

Fixes #1307

Co-Authored-By: Codex <noreply@openai.com>
2026-10-12 21:50:24 +02:00
Marco Arnulfo 8c539426eb Docs: CR2 white level from the active area (#1272), 60D, 450D and 550D affected too 2026-10-12 21:02:48 +02:00
Marco Arnulfo dd502bac9a LR-IMP-CAMERA-COVERAGE: Pentax PEF masked borders in raw-parity, the checklist and what's new (#1271) 2026-10-12 20:37:31 +02:00
Marco Arnulfo acbd08eb73 LR-LIB-DELETE: a file in Recently Deleted can be checked by hand in the import review (fixes #1285)
With "Leave them", the review refused every click on a file whose photo is in
Recently Deleted, and its "In Recently Deleted" badge was drawn over the
checkbox. Leave them now only keeps such files out of the default selection
(Check All and the file-type toggles skip them); a click checks one and it is
restored, as the import does by default. The badge goes under the checkbox
when it doesn't fit beside it.
2026-10-12 18:14:05 +02:00
Markus FriedelandClaude Opus 5.5 978132fdca LR-EDIT-COLOR-TEMP: the Kelvin Temp slider has Lightroom's scale, 7000 K in the middle (#1295)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:37:42 +02:00
Christos SidiropoulosandCodex GPT-5.6 Sol 8a4fec438a Fix #1194: locate missing files by folder tree
Co-Authored-By: Codex GPT-5.6 Sol <codex@openai.com>
Signed-off-by: Christos Sidiropoulos <dev@csidirop.de>
2026-10-12 17:15:54 +02:00
Markus FriedelandClaude Opus 5.5 a940fae193 MENU-CTX-ALBUM: an album's Import ▸ Import from Device lists the devices found (#1267)
Without a path, file.addFromDevice took the first device found, so with
two cards connected the album menu imported from whichever came first.
Like File ▸ Import from Device, the album's Import from Device is now a
submenu with one entry per camera or card (or "No Camera or Card
Found"), each passing its path along with the album.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:52:06 +02:00
Markus FriedelandClaude Opus 5.5 edb3cbfd8a MENU-CTX-ALBUM: Import ▸ submenu on an album opens the review with that album chosen (#1267)
An album's context menu gets Import ▸ with File ▸ Import's ways in
(Import Photos…, Import from Folder…, Import from Device). file.addPhotos,
file.addFolder and file.addFromDevice take {album}; the scan task carries
it and the review chooses it when the scan is done, if it still offers
that album (not deleted, not a folder or smart album).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:45:14 +02:00
Andrew FrahnandClaude Opus 5.5 03a3bbd561 Up / Down move through the grid's rows (#1171)
library.up / library.down (Up / Down) go to the cell above / below in the
grids (nearest by position in justified rows; the top / bottom row stays
put), and step one photo in the filmstrip.

Sources: own design.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 01:39:01 +11:00
Marco Arnulfo a4716d9e4f LR-IMP-FORMATS: transparent areas develop on white instead of black (#1212)
The decoders keep the alpha plane, but to_working converted only the
colour, so transparent pixels kept the black most encoders store under
them: renders, previews, exports and contact sheets showed it. The
working image is now flattened onto white, in linear light like the
rest of the pipeline.
2026-10-12 13:15:19 +02:00
Alex ChambersandClaude Opus 5.5 f1c023ed3d LR-META-XMP: Read Metadata from File doesn't auto-write the sidecar it just read (#934)
With XMP auto-write on, photo.readMetadataFromFile committed what it read
and the command handler then wrote the sidecar back, adding lc:settings to
a sidecar that had only another app's crs: settings. Later reads prefer
lc:settings, so LRTimelapse's next crs: edits were ignored. The read now
sets the existing one-command skip_auto_write switch (as photo.removeRegion
does); edits made afterwards are still auto-written.

Tests: a read leaves the sidecar byte for byte and a later develop edit is
still written; the issue's crs:Exposure2012 0.5 -> 1.2 round trip is read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:24:29 +02:00
dev-null-undefinedandClaude 31c31b726b LR-VIEW-DETAIL: the loupe says when the render behind a stand-in fails
A photo whose render failed while the loupe showed its embedded JPEG or a thumbnail kept
that stand-in up as if it were the photo; "This photo can't be opened" only showed when
nothing at all could be drawn. Now a caution pill at the "Rendering…" spot says so:
"Original offline · no smart preview" when that is why, else "This photo can't be opened",
with the reason on hover and for screen readers (widget `loupe:renderFailed`). Agents see
it as `ui.inspect` → `loupe.failed`, so one waiting for a finished loupe knows when there
won't be one.

A library change retries failed renders; while the retry of the same key runs, the pill
stays and "Rendering…" doesn't take over. The renderer remembers which photo a failure
belongs to (`failure_of`): the centre message no longer shows the previous photo's error
for a moment after a step. Tests share one render offload (`headless::RenderGate`) that
holds renders and can fail chosen slots.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 00:01:22 +02:00
dev-null-undefinedandClaude 2df78c9e58 LR-BEHAV-BG-TASKS: a render job that panics fails instead of never answering
A panic inside RenderJob::run or QuickJob::run (a raw decoder or pipeline bug) unwound the
job pool's worker without sending a result. The slot stayed pending and its key was never
asked for again, so the loupe or the thumbnail rendered forever; and the pool never
replaces a dead worker, so after as many such panics as it has workers (2–6) no photo
rendered until LightCraft was restarted.

Both now catch the panic (guard::catch) and return it as the job's failure, answering the
request it came from, so the renderer records it like any failed render: no retry until
the catalog changes, and the workers live on. run() is the one place every render goes
through (the pool, export, Build Previews, contact sheets, face and AI-mask workers);
callers that had their own guard keep working, and the watermark preview's, now
redundant, is gone. The web build aborts on panic, so nothing changes there.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-11 23:23:50 +02:00
lloydandClaude Opus 5.5 090553d14d LR-MERGE-HDR: merges of raws without colour matrices keep their colour (#965)
Photo Merge decoded each raw itself and wrote the reference frame's own colour
tags into the merged DNG. A CR2 (and NEF, ARW and the other raws whose colour is
fitted from the camera JPEG) has none, so an HDR merge of CR2s rendered with no
camera colour: green and about 16 L* dark.

`lightcraft_merge::load_frame_with` takes the raw's colour tags from the caller,
and the engine passes `starting_colour_tags`: the colour the raw opens with
(`starting_colour`) as DNG tags. That is one forward matrix with a colour matrix
and AsShotNeutral that agree with it at the as-shot white, the look's hue/sat
table as ProfileHueSatMap and its tone curve as ProfileToneCurve. Raws with
their own matrices (DNG) keep their tags. The look's chroma curve has no DNG
tag and is left out.

On two CC0 CR2s (EOS 550D, 40D) an HDR merge of three copies against the photo
alone: mean CIE76 dE 26.15 -> 1.07 and 22.89 -> 0.47.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:42:18 +02:00
Fabio LussiandClaude Opus 5.5 12498b3acf CLI --import <folder> uses the engine's import extensions (HEIC, HEIF, NRW)
expand_paths kept its own PHOTO_EXTENSIONS list, which had fallen behind
lightcraft_engine::import::EXTENSIONS. It now filters with
import::is_supported, so folder walks and library.import take the same files.

Fixes #1080

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:13:57 +02:00