Commit Graph
1494 Commits
Author SHA1 Message Date
akvaithiandClaude Opus 5.5 88f424e7e7 LR-EDIT-DETAIL-DENOISE: share tiles with a server only when it is faster
Measured with RawNIND on a 20.8 MP raw: an Apple M3 does a tile in 116 ms, an
RTX 3060 Ti over Tailscale 345 ms there and back; sharing blindly made the
export take 34 s instead of 6.4 s while the photo waited for the server's last
tiles. The greeting now times a check tile there and back, and tiles are
shared only when that beats this computer's own time per tile (the card's, or
the CPU's with its threads counted as `card_is_faster` does). Otherwise
`denoise.status` → `device.remote` says `slower` with both times. With the
server configured but slower the export takes 7.2 s (greeting + check tile).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:53:39 -05:00
PiMinusMaxandClaude Opus 5.5 bc5c561dd8 LR-VIEW-BEFOREAFTER: zoomed side by side / stacked views stay in their panes
Zoomed in, each view's photo reaches past its pane. The whole-frame renders
were drawn unclipped (only the window renders were clipped to their pane),
so the After's magnified whole-frame render covered the Before pane's margins
and the gap between the panes with a blurred picture, and the Before side
looked like it didn't fill its pane. Both whole-frame renders are now clipped
to their pane, like the windows over them; the Before / After labels stay
under the pane instead of moving off screen with the photo's bottom edge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:47:43 +02:00
Adrian D'souza 5855ab80a6 XMP.434: reconcile current main & complete warning locales
Preserve Target-aware sidecar operations, add French/Ukrainian warnings, and ensure omitted diagnostic fields decode in the native UI.

Generated with Codex.
2026-10-11 02:11:00 +05:30
akvaithiandClaude Opus 5.5 84b8995d7b LR-EDIT-DETAIL-DENOISE: run tiles on another computer's graphics card
- `lightcraft_denoise::remote`: protocol v1 over TCP (JSON lines + byte-shuffled,
  deflated half-float tiles), a `Remote` client (connection pool, four slots,
  greeting checks the model's SHA-256 and tile size, gives up after three failed
  tiles) and `serve` (shared token compared in constant time, size caps including
  payloads that inflate past their tile, connection limit, timeouts).
- Engine: with LIGHTCRAFT_DENOISE_URL / LIGHTCRAFT_DENOISE_TOKEN set, the loaded
  model greets the server on first use and adds its slots to this computer's
  tiles at once; a tile goes to a free server slot, else runs here, and a tile
  the server fails runs here too. `denoise.status` → `device.remote` says where.
- `lightcraft-cli denoise-serve` serves the installed, selected model on this
  computer's card (checked against the CPU, as in the app) or CPU.
- docs/denoise.md: setup, safety (unencrypted: VPN/LAN only) and the protocol.

Tested: protocol round trips, refusals (token, model, tile size, hostile
payloads), fallback and give-up; the engine model with a live, a mismatched
and a dead server; the CLI binary serving a synthetic model end to end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:21:48 -05:00
Jason Baldwin a3c33658bb Merge origin/main into brush-hold-hardens (clean merge; tracker edit followed the parity-checklist.md rename) 2026-10-10 21:49:33 +02:00
Jason Baldwin ae033aaf32 LRC-SS-LAYOUT: slideshow layout, options and backdrop: slides composed with margins, stroke, shadow and backdrop
- 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.
2026-10-10 21:47:42 +02:00
Jason Baldwin 7216c8589a LR-EDIT-COLOR-TEMP: raw-parity.md describes Kelvin WB for matrix cameras (#730) 2026-10-10 21:47:36 +02:00
Jason Baldwin 45227de921 Merge origin/main into kelvin-wb-with-matrices (no conflicts; docs/parity.md rename followed cleanly) 2026-10-10 21:46:44 +02:00
Jason Baldwin 0fdf6c5785 Merge remote-tracking branch 'origin/main' into brush-live-preview-gaps 2026-10-10 21:44:40 +02:00
Jason Baldwin 78c5b4d099 Merge origin/main into crop-angle-constrained 2026-10-10 21:39:04 +02:00
Jason Baldwin 62dacf2791 Merge origin/main into crop-rotation-artefact 2026-10-10 21:37:05 +02:00
Jason Baldwin 7a232ada8b Merge remote-tracking branch 'origin/main' into nef-probe-header-only 2026-10-10 21:37:02 +02:00
Jason Baldwin 7765255ec6 Merge follow-up: whats-new entry under 2026-10-10 2026-10-10 21:36:32 +02:00
Jason Baldwin de6b33c662 Merge remote-tracking branch 'origin/main' into reimport-after-delete 2026-10-10 21:33:45 +02:00
Jason Baldwin b4d7cd1a03 Merge remote-tracking branch 'origin/main' into gpu-fallback-per-render 2026-10-10 21:33:40 +02:00
Jason Baldwin 89516d2e3e Merge origin/main into lock-unlock-on-drop (whats-new entry moved under 2026-10-10) 2026-10-10 21:32:55 +02:00
Jason Baldwin e7076762c0 Merge remote-tracking branch 'origin/main' into sony-arw-washed-out 2026-10-10 21:31:53 +02:00
Jason Baldwin bf4a271a71 Merge remote-tracking branch 'origin/main' into lock-unlock-on-drop 2026-10-10 21:31:51 +02:00
Jason Baldwin be4cbebbd3 LR-PREF-PEOPLE: restore 'faces' typo in the tracker row after the merge 2026-10-10 21:27:27 +02:00
Jason Baldwin 2c2f28952f Merge origin/main into menu-scroll-clips-shortcuts (docs restructure; no conflicts) 2026-10-10 21:18:32 +02:00
Jason Baldwin 85b6fdaedd Merge remote-tracking branch 'origin/main' into faces-toggle-needs-a-model 2026-10-10 21:18:31 +02:00
Jason Baldwin 6ae35b0a5b Merge remote-tracking branch 'origin/main' into albums-library-photos-only 2026-10-10 21:18:30 +02:00
Jason Baldwin 46ff7bcf4e Merge remote-tracking branch 'origin/main' into grid-add-to-album-new-album 2026-10-10 21:18:25 +02:00
Jason Baldwin 4dd6fb5089 Merge origin/main into uppercase-extensions (whats-new: keep main's entries, re-add the Formats bullet under 2026-10-10) 2026-10-10 21:16:49 +02:00
Jason Baldwin dd73753723 Merge origin/main into info-dialogs-close (no conflicts; MENU-HELP-SYSINFO note now in docs/parity-checklist.md) 2026-10-10 21:16:30 +02:00
Jason Baldwin 179941f4ff Merge origin/main into dialogs-fit-the-window (re-applied LR-BEHAV-DIALOGS row and LR-EXP-DIALOG note onto docs/parity-checklist.md, regenerated summary) 2026-10-10 21:15:37 +02:00
dev-null-undefinedandClaude 4860f5e8d4 LR-IMP-FORMATS: ARW6 companding curve derived clean-room from CC0 lossless pairs
The 2668-entry table read off the black-box oracle's output is gone.
arw6_curve.rs now builds the 4096-entry table at first use from our own
measurement: piecewise linear through knots u_k = 128 k, c_k = u_k for
k <= 11 and 356.89 + 655.646 ln(k - 6) above, rounded half up, fitted to
the 7 same-exposure lossless (LJ92) / ARW6 pairs of the CC0 ILCE-7RM6 set.
A unit test pins the whole table (sum 27776336, weighted 92792980288),
its anchors, the identity through 1408 and strict monotonicity.

The corpus sums become regression values of the new output; the 12-bit
codes before the curve stay verified against the oracle (Phase 0).
docs/arw6-compression.md describes the curve, how it was measured, its
uncertainty, the structure and x2-scale evidence, why it is not in the
file, and the after-the-fact comparison with the oracle's curve; the
tracker and docs no longer call the output bit-exact against LibRaw.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 21:08:17 +02:00
dev-null-undefinedandClaude 2218a53f2b LR-IMP-FORMATS: ARW6 module docs cite docs/arw6-compression.md
docs/superpowers/ held the working spec and plan, which pointed at the
local plan/ folder. The ARW6 module docs now cite the sections of
docs/arw6-compression.md, which gains the facts they relied on from the
spec: the NP field of word 0, the stream header word layout and how the
first half's residual lines are counted.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 21:08:17 +02:00
dev-null-undefinedandClaude 2f75b21ac3 LR-IMP-FORMATS: ARW6 corpus pins two files (FF Compressed, APS-C HQ)
`cargo xtask corpus --download` now fetches one full-frame Compressed and
one APS-C Compressed HQ file (about 94 MB) instead of all 12 (about
630 MB); the corpus test checks those two and the lossless-sibling
regression test is gone, since nothing would download those files.
docs/arw6-compression.md keeps the full table with source paths and
SHA-256, says which two xtask fetches and how to fetch the rest with
`curl -L`, and records the CC0 1.0 statement of RawDB's set record
(accessed 2026-10-10).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 21:08:17 +02:00
dev-null-undefinedandClaude 1be303ca00 LR-IMP-FORMATS: ARW6 corpus hashes live in RAW_SAMPLES; drop docs/arw6-corpus.sha256
The RawDB entries in xtask carry their SHA-256 as the third field, which
`cargo xtask corpus --download` checks; the corpus test keeps only the
sensor sum checks.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 21:08:17 +02:00
dev-null-undefined fa7f1e8d6c LR-IMP-FORMATS: ARW6 docs after the final review 2026-10-10 21:08:17 +02:00
dev-null-undefinedandClaude aea5236790 LR-IMP-FORMATS: ARW6 decode timing method
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 21:08:17 +02:00
dev-null-undefinedandClaude 9aa9bcb54e LR-IMP-FORMATS: ARW6 decode timings
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 21:08:17 +02:00
dev-null-undefined 458b938248 LR-IMP-FORMATS: ARW6 corpus verification, docs and tracker 2026-10-10 21:08:16 +02:00
Jason Baldwin 1064e9847d Merge origin/main into enter-applies-copy-paste (parity rows applied to docs/parity-checklist.md) 2026-10-10 21:07:39 +02:00
Jason Baldwin 52875ec3f9 Merge origin/main into slideshow-playback (docs restructure #788: parity.md is now parity-checklist.md; slideshow rows re-applied, summary regenerated) 2026-10-10 20:54:29 +02:00
Steffen SauderandClaude Sonnet 5.5 e363d298d9 LR-IMP-FORMATS: point to the two Olympus patents as a clean-room base for compressed ORF
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 20:51:23 +02:00
Jason Baldwin 92077d0807 LRC-SS-PLAYBACK: slideshow playback: fades, random order, repeat, previews prepared in advance, playback controls 2026-10-10 20:31:38 +02:00
Brandon ThomasandClaude Opus 5.5 964d9338ba Progress docs: target-app parity, RAW coverage vs Adobe, gaps, alpha gate, readiness by audience (#788)
Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, model-by-model RAW coverage against Adobe's camera list (docs/raw/), and format, hardware, UI and localization parity docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:25:15 -04:00
radialmonster 0041aef955 LR-EDIT-OPTICS-PROFILE: apply DNG WarpRectilinear2 lens corrections (Pixel DNGs, #635) 2026-10-10 14:21:13 -04:00
lloydandClaude Opus 5.5 d7eb6b2ab4 LR-PREF-DISPLAY: macOS previews follow the screen's profile, so they match exports (#787)
Previews looked more saturated than the exported files on Mac screens. The
pixels are the same: preview and export match to within one level on the CPU
and GPU paths, and exports embed a correct sRGB profile. But wgpu leaves the
window's Metal layer without a colour space for sRGB surfaces, and Core
Animation shows such a layer without colour matching ("If nil, no
colormatching occurs", CAMetalLayer.h). On a P3 screen the sRGB previews
were therefore shown too saturated, while Preview and Photos convert the
exports properly.

While no monitor profile is chosen in Settings > Display, the desktop app now
shows previews through the profile of the screen the window is on
(NSWindow.screen.colorSpace.ICCProfileData, safe objc2 calls), through the
existing display-profile path. It is read again about once a second, so
moving the window to another screen is followed. A chosen profile still wins;
"Use Screen Profile" goes back to it. app.displayProfile reports it as
path: null, screen: true. Other platforms and headless sessions are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:51:01 +02:00
radialmonster 70103a7e55 LR-EDIT-LIGHT-HIGHLIGHTS: keep local contrast under Highlights/Shadows, as process V2 (#632)
The highlights/shadows base (fast guided filter of log luminance, eps 0.35)
followed thin high-contrast detail, so the per-pixel shift flattened twigs,
lines and texture in bright areas (and dark ones under Shadows); Exposure
kept them.

This changes how every existing edit with Highlights or Shadows renders, so
it ships as a new rendering process (docs/process-versions.md):

- Process::V2 (version 2) is added and made LATEST. New photos and Reset get
  it; existing edits stay on V1 until Update to Current Process. Settings
  saved without the field still load as V1.
- From V2 the base is the same guided filter of a separable median of log
  luminance (radius 0.15 % of the long edge, <= 24 px): fine detail takes its
  surroundings' shift and keeps its contrast, region steps stay put (no new
  halos). V1's base is untouched: local::tone_base_detail is 0 under V1 and
  tone_base then is exactly guided_fast(l, sigma, BASE_EPS), as before.
- CPU (local::prepare) and GPU prepare (median_h / median_v kernels, bit for
  bit with the CPU median) both branch on it via PlaneSigmas::base_detail.
- The base plane's cache key is now (sigma, process, median radius)
  (local::BaseKey), so a warm cache never serves one process the other's
  base. plane_at is shared with the GPU crate.
- finish::base_tone: V2 uses V1's tone map.

Tests: V2 keeps twig/local contrast (>= 0.9 of Exposure's) with no halo; V1
plane sigmas have no median and its base equals guided_fast bit for bit; V1
and V2 render alike without Highlights/Shadows; warm-cache renders across
V1/V2 switches equal fresh ones (fails if the key drops the process); GPU
matches CPU on both processes at 720 and 2400 px, cached and not.

Pentax 645D 2401 at 4000 px: main and V1 renders bit-identical (plain,
Highlights -100, Shadows +100). Highlights -100 bright rel. detail
0.095 (V1) -> 0.147 (V2), Exposure -1: 0.124; Shadows +100 dark rel. detail
0.126 -> 0.148.

RENDER_CACHE_VERSION 54 (adjust at merge).
2026-10-10 13:46:14 -04:00
Nathaniel LedfordandClaude Opus 5.5 02a21b860d LR-BEHAV-SIDEBAR-SECTIONS: review fixes for the header button and the pinned header
A keyword made from Keywords' + is shown (the section and its parents open); a
press on a header button never starts a section drag; a section dragged to the
top edge scrolls past a pinned header again (only a drag picked up by the
pinned header waits until it has left it). Tests that could not fail are
replaced, and the parity rows say what the code does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:14:07 -04:00
Nathaniel LedfordandClaude Opus 5.5 d331829770 LR-BEHAV-SIDEBAR-SECTIONS: a section declares its header button; Keywords gets + (Create Keyword Tag)
Albums' + is no longer a special case of the header: header_button says which
section has a button and whether it acts or opens a menu, and the frame draws
it in the header and its pinned copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:04:02 -04:00
Jason Baldwin bf49935fe7 LR-BEHAV-DIALOGS: dialogs fit the window; options scroll, title and buttons stay visible (#781)
Every dialog but Import draws its options in a vertical scroll area capped at the
window height minus the title bar, frame and button row (measured on the previous
frame), so on a 1366x768 screen the Export dialog's title and Cancel / OK stay on
screen. Dialogs that fit keep their size. Lists that scroll on their own (What's
New, All Metadata, shortcuts, smart-album rules, credits) get shorter first rather
than scrolling inside a scrolling dialog. Import keeps its resizable window.
2026-10-10 18:57:37 +02:00
Nathaniel LedfordandClaude Opus 5.5 9cd9e29614 LR-BEHAV-SIDEBAR-STICKY: rows beneath the pinned header are not drop targets
An album or photos released on the pinned Albums header went to the row
scrolled under it. Folding from the pinned header keeps the sideways scroll,
its hand-off to the next frame can't go stale, and a section picked up by the
pinned header doesn't start scrolling at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:51:55 -04:00
Jason Baldwin 19833e56e3 MENU-HELP-SYSINFO: System Info, All Metadata and What's New end with one Close button (#782)
Their confirm does nothing, so they join About, Shortcuts and Settings in the
footer's informational list: one Close, no Cancel / OK. System Info keeps Copy
to Clipboard; Esc still closes them.
2026-10-10 18:50:12 +02:00
Nathaniel LedfordandClaude Opus 5.5 5e68d92c9f LR-BEHAV-SIDEBAR-STICKY: a long section's header stays in sight; sections are easier to tell apart
Pinned header at the top of the sidebar, hairlines between sections, the fold
chevron in the rows' triangle column, a count on folded sections, fainter zero
counts. From review: a move nobody could see is no move, ui.set refuses
`sidebar` together with `collapsedSidebar` and unknown names in the latter.
Translations and What's New for the sidebar work.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:44:46 -04:00
Nathaniel LedfordandClaude Opus 5.5 5ac3e556ac LR-BEHAV-SIDEBAR-REORDER: drag sidebar sections by their header, Move Up / Down, Recently Deleted joins My Photos
view.sidebarMoveSection; a section with nothing to list stays with a note
instead of disappearing (so every move is one you can see). ui.set reads
`sidebar` strictly and still takes the older collapsedSidebar list; an album
folder's triangle and row can no longer toggle twice in one click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:36:13 -04:00
Nathaniel LedfordandClaude Opus 5.5 a64efb149c LR-BEHAV-SIDEBAR-HIDE: show and hide sidebar sections from View ▸ Sidebar Sections and their headers
view.sidebarSection / view.sidebarReset; the same list opens from a section
header's and the My Photos title's context menu. A new album brings a hidden
Albums section back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:29:28 -04:00