Between a kept luminance share of 0.15 and 0.25 the table colour is now blended in with a smoothstep,
so noisy shadows show no step between pixels that get the table colour and pixels that keep theirs.
At 0.25 and above pixels render exactly as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A slideshow template is the Playback (not "prepare previews"), Layout /
Options / Backdrop, Overlays and Titles settings as one versioned JSON
document (format lightcraft.slideshowTemplate, version 1).
- Engine: slide_template (SlideLook, Template, built-ins, user template
files in <settings>/slideshow-templates read through each section's own
merged() validation; size and count caps; newer versions refused; bad
files reported and skipped; file names sanitised so ids never leave the
folder). Applying replaces the four settings in one step and keeps the
replaced ones as "previous" for the session (prefs have no undo).
- Five built-ins of our own: Plain Black, Gallery Wall, Edge to Edge,
Cinema Wide, Shooting Data (no Lightroom names or designs, no images).
- Commands slideshow.templates.list/apply/save/update/rename/delete/
import/export; slideshow.preview {template} previews without applying.
- UI: Template Browser at the top of Settings > Slideshow (built-in, user,
previous settings; click applies, hover previews on the selected photo,
right-click update / rename / export / delete; save and import), file
dialogs on the desktop; strings in the nine locales.
- Docs: parity row (partial), whats-new, control protocol and MCP.
Intro and ending title screens (Lightroom Classic's Titles panel): each on
or off, a background colour and, centred, the Overlays identity plate or a
line of text, in the plate's colour or an override colour, at a scale, for
its own duration (default: the slide duration).
- Playback timeline: titles are items (Item::Title) of Playback; the intro
plays once before the first photo, the ending after the last photo when
repeat is off; random order never moves them; arrows step across them;
fades, pause and readiness work as for slides; n of N counts photos only.
- Engine: slide_title (TitleSettings in prefs.json, TitleCompose drawing
through the slide composer and overlay text renderer), slideshow.titles
get/set, slideshow.preview {title}.
- UI: titles composed on a render worker (Renderer::request_title), the
control bar shows Intro / End, Settings > Slideshow > Titles section and
a Photo / Intro / Ending preview choice; strings in the nine locales.
- Docs: parity row (partial), playback note, whats-new, control and MCP.
Exercise both separator directions for folder and individual-file imports.
Verify duplicate detection, stable photo IDs, added/deleted file detection,
and reuse of a confirmed scan when the folder spelling changes.
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Rebuild fixture path components with native separators so expected paths
match directory scans on Windows, including files that have been removed.
This is a prerequisite for Windows validation and overlaps the path-helper
fix in upstream PR #660; it can be dropped once that change lands.
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
HueSat::apply restores luminance with before / after. Near black, where noise makes some channels
negative, the hue/saturation table can bring after close to 0, and the gain turned single pixels
white (isolated white dots in dark areas, most visible at fit). Luminance is now restored only if
the table kept at least 25 % of it; such colours keep their colour, like black and non-finite ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Canon EOS R50 C-RAW files reach QP 168 (quant 44, step 102, measured about 100). The quantization step and the adaptive QP map range accept it; anything above stays rejected. Bumps RENDER_CACHE_VERSION since such files change from the embedded preview to a raw decode.
- Engine: slide_overlay (OverlaySettings in prefs.json, the new slideshow.overlays
command): identity plate (text, or a PNG/JPEG file with its transparency; size,
colour, opacity; render behind image), rating stars (own vector stars), up to 16
text overlays with tokens ({caption}, {exposure}, {file}, {date}, {focal}… plus
every rename token; unknown tags show as typed and are reported) and a drop
shadow, each at one of nine anchors of the slide or photo plus an offset, kept on
the slide; the export watermark on the photo. Sizes relative to the slide's
shorter side; validated and clamped.
- Drawn by the engine as a second pass over lightcraft_slideshow::compose_with
(new behind hook for "render behind image"); the watermark's text renderer moved
to engine text.rs (TextLayout, Inter + craft-fonts CJK) and is shared; glyphs
off the image are skipped so huge text stays cheap.
- rename::expand_tokens_with lets overlays add tokens without changing rename.
- Playback composes slides when overlays are on; slideshow.preview returns each
overlay's box. Settings > Slideshow > Overlays section with live preview.
- Docs: parity row (partial), whats-new, control/MCP docs, nine locale catalogs.
- Tests: tokens, nine anchors, star count, plate image opacity and missing file,
text shadow, resolution independence, hostile input, big-slide cost, CJK with
craft-fonts, prefs persistence, preview and headless playback pixel checks.
- New crate lightcraft-slideshow (L1, no UI): SlideSettings (margins linked or
independent, guides, aspect preview, zoom to fill, stroke border, cast shadow,
backdrop colour, colour wash, background image; lengths relative to the slide's
shorter side; validated and clamped) and a CPU compose() used by playback, the
Settings preview and slideshow.preview.
- Engine: slideshow.layout (partial merge, saved in prefs.json) and
slideshow.preview {id?, width?, height?, path?} (PNG to path or base64);
RenderJob::with_slide composes on the render worker; the background photo is
rendered once and shared.
- Playback: with a non-default layout each slide is the composed screen-sized
slide, prepared ahead like before; the default layout plays as before.
- Settings > Slideshow: Layout, Options and Backdrop sections and a debounced
live preview of the active photo's slide (with margin guides).
- Tests: composer geometry/pixels/hostile input, command get/set/persist/preview,
headless playback of a composed slide and of the default layout.
Reset Edits rebuilt a photo without a default-preset look from DevelopSettings::default(),
so a raw imported with capture sharpening 40 and colour noise reduction 25
(DevelopSettings::for_raw) came back with both at 0, and with its embedded lens
corrections off. It now starts from the photo's own built-in defaults
(Photo::camera_defaults, the same as import) and keeps the white balance of its
current as-shot reference, as before. Rendered files are unchanged (their defaults
are DevelopSettings::default()). Reported in #763's notes.
The R5 Mark II's APS-C crop-mode files (5376 x 3574) state an IAD1 active area of x 132..5243,
but columns 132..~256 sit at the black level and the image runs to the right edge (measured on
raw.pixls.us 7883/7884), while their recommended crop, x 272..5359 (5088 x 3392, the camera JPEG's
size), lies on the image. The recommended crop didn't fit inside the stated active area, so the
whole active area was kept: a black band down the left and ~130 image columns lost.
When the recommended crop doesn't fit inside the stated active area, it is now the valid area.
On 7883 the render's high-pass correlation with the camera JPEG goes from -0.13 to 0.99. The
active area and crop of the other 108 decodable CC0 CR3s on raw.pixls.us are unchanged.
RENDER_CACHE_VERSION 49.
Merge origin/main into #480 and apply the review:
- the Samsung-with-a-Pentax-maker-note -> PEF rule now also needs raw evidence; its test fixture
gets a CFA photometric, and the same RGB file without it is not a raw;
- for the Pentax family the Exif CFAPattern (0xa302) counts as raw evidence, as main's PEF reader
takes its layout from it (uncompressed / PackBits PEFs);
- Samsung's private raw compressions 32769..=32773 count for SRW (NX1 / NX500 use 32773);
- the engine fallback in files.rs is dropped (main's version kept): a corrupt raw without a
preview stays an import error; the engine regression test for camera-authored TIFFs is kept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge origin/main into #555. The decode_hasselblad doc comment records how the coding rule was
established (first hypothesis recalled by the AI author from training data that includes other
converters, corrected for byte order and confirmed by a black-box search over 17,280 layout
hypotheses on the CC0 files; the code is original). The LR-IMP-FORMATS row on main's text now
lists the decoded FFF and lossless-JPEG 3FR files instead of preview-only. RENDER_CACHE_VERSION
37 -> 38.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's reconstruction (#607) replaces this branch's rewrite of highlight::reconstruct. Kept from the
branch: develop_binned_masked (clipping decided per sample before averaging) and the denoised twin
using the same mask. New: highlight::reconstruct_masked, #607's reconstruction with the clipped
channels told by the mask (block means as lower bounds), shared with reconstruct_with through a
generic clip test (no slowdown on full-size images), and CameraColourModel::rebuild_highlights_masked
so binned previews keep the colour model's clipped white. RENDER_CACHE_VERSION 38.
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>
Only proxies of raws that take the per-file camera look (Photo::relative_wb) go stale: JPEG/PNG/DNG proxies are never rebuilt for the look. The opening scan runs once per LOOK_VERSION (a look-version marker in the smart previews folder), not at every library open; Build Smart Previews still refreshes stale proxies. Each proxy is checked and written under one lock, so the background refresh and library.smartPreviews never write the same file at once. LOOK_VERSION 2: main's DRO / ILCE-7CR camera-look changes (#528, #583, #568, #616).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main (#575, #580) rewrote default_crop. The image crop now keeps main's
order for every Sony body (Sony's crop tags, then DefaultCrop, then the
recorded-size crop), so framing does not change. Only the ILCE-7RM4A
distortion warp takes its centre and normalization from DefaultCrop when
the file has one, which keeps the geometry validated against Sony's
exports (centre x 4783.5 on the A7R IVA sample). The DNG round-trip test
now checks both: Sony's crop on the image, the warp centred on the
default crop. RENDER_CACHE_VERSION 38.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's SR2SubIFD white balance (#575) already reads the A900's applied
levels (2688 / 1024 / 1024 / 1516, the same 2.625 / 1.480 gains), so the
hard-coded maker-note 0x0020 block at offset 188 is dropped. The centred
crop now goes through #580's recorded_size_crop (a `centred` flag, only
for the packed 12-bit layout); every other body keeps main's framing.
Adds the CC0 A900 sample to the corpus with checks for its white balance,
black level, bit depth and crop. RENDER_CACHE_VERSION 38.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cross clicked in the frame its task ended no longer puts "no task N"
in the status bar: the row's cancel goes to the engine directly instead
of through the app's command runner, which reports every error there.
The face-scan row test scans demo photos no other scan test uses, so it
no longer joins the scan deadlock of #630 (with one of the existing pump
tests it hung 13 of 20 runs; now 0 of 20).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While a photo's AI Denoise picture is being made or waits its turn, the
stack shows "AI Denoise" with the running photo's tiles as a percentage
and its file name (no cross: what is made follows the Denoise amounts and
Settings). The row goes when the queue is idle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While photos are left to search for faces the stack shows "Finding
faces" with how many are done (no cross: the scan is switched off in
Settings). The engine keeps the scan's peak, so Settings and the stack
agree. Also translates the "Downloading model" label.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Downloading the SAM 3, face and AI Denoise models shows a row with the
model's name and the megabytes so far; its cross stops the download like
the Settings button. The denoise download tests get their own scratch
folders (they shared the face tests' names and could delete each
other's files).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Build Previews, Build Smart Previews and Discard Smart Previews show a row
with the photo count and stop from its cross; the start toast goes, the
finish toast stays.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The import review's folder scan (and reading a folder for Local) is a
row in the activity stack: "Looking for photos…" while the folders are
listed, then the files read of the total. Its cross drops the scan at
once, without waiting for the file being read, as the old Cancel did.
The separate Scanning window is gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>