Commit Graph
4107 Commits
Author SHA1 Message Date
bflatastic b01902bbae Merge PR #1091 2026-10-13 11:01:02 +07:00
bflatastic dca358d435 Merge PR #1389 2026-10-13 11:01:01 +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 3ba3120637 Merge PR #1064 2026-10-13 11:01:00 +07:00
bflatastic b56f052a59 Merge PR #1387 2026-10-13 11:00:58 +07:00
bflatastic 5388d20088 Merge PR #1125 2026-10-13 11:00:56 +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 6435019603 Merge PR #1394 2026-10-13 11:00:47 +07:00
bflatastic 99e9f25796 Merge PR #1101 2026-10-13 11:00:47 +07:00
bflatastic 179461aee3 Merge PR #1368 2026-10-13 11:00:45 +07:00
bflatastic 3e5439cc94 Merge PR #1177 2026-10-13 11:00:44 +07:00
bflatastic c9e12bd9ff Merge PR #1123 2026-10-13 11:00:41 +07:00
bflatastic cd75e11841 Merge PR #1149 2026-10-13 11:00:41 +07:00
bflatastic 5fddd79583 Merge PR #1139 2026-10-13 11:00:40 +07:00
bflatastic 035c378758 Merge PR #1052 2026-10-13 10:39:12 +07:00
Andrew FrahnandClaude Opus 5.5 93a60d4fcd MENU-FILE-PHOTOSHOP: Edit in PhotoCraft says why it didn't open, finds PhotoCraft on macOS and Linux
- Every Edit In failure toasts, from the menu, shortcut, context menu or
  control channel (the context menu dropped errors, and a failed copy step
  went unreported).
- macOS: PhotoCraft is looked for in /Applications, ~/Applications and via
  Spotlight (bundle id or bundle name); a missing app is reported instead of
  always handing `open -a PhotoCraft` the file; `open`'s exit status is
  checked and its message shown.
- Linux: a desktop entry whose Exec is a bare name on the PATH counts, and so
  does a *PhotoCraft*.AppImage in ~/Applications or ~/.local/bin.

Sources: own design.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 14:39:07 +11:00
bflatastic 9fe9beffbc Merge PR #1007 2026-10-13 10:38:47 +07:00
bflatastic e325de9db4 Merge PR #1018 2026-10-13 10:38:46 +07:00
bflatastic 751d25a7f7 Merge PR #1003 2026-10-13 10:38:45 +07:00
bflatastic 6a122dc684 Merge PR #990 2026-10-13 10:38:44 +07:00
bflatastic ae029e0851 Merge PR #997 2026-10-13 10:37:48 +07:00
Brandon Thomas f2a9888f75 Merge PR #1257 2026-10-12 23:31:21 -04:00
Brandon Thomas 765e94e0a1 Merge PR #1255 2026-10-12 23:31:19 -04:00
Brandon Thomas 1f1374fd46 Merge PR #1254 2026-10-12 23:31:17 -04:00
Brandon Thomas ade1a86a03 Merge PR #1253 2026-10-12 23:31:09 -04:00
Brandon Thomas 79e0e98321 Merge PR #1250 2026-10-12 23:30:47 -04:00
eliets2 a10bc04b8b smart previews: store proxies at JPEG quality 97 and version the encoding (#709)
The proxy's largest visible error against the original was the JPEG encoder's
quantised 8x8 DCT DC - each block's own mean, luma and chroma - which shows as
block steps across the frame and a small constant colour shift, and grows with
saturation. Quality 92 -> 97 shrinks those quantisers to about a third (block
-mean dE76 0.138 vs 0.202 on the fidelity test's smooth scene), at about twice
the file size; what remains is the 8-bit sRGB quantisation both encoders share,
which only a lossless proxy format can close.

The header gains an `enc` field (encode version 2) and the folder's look marker
becomes "<look> <enc>": a proxy or marker from before the encode version is
rebuilt/rescanned once, so existing libraries pick the new quality up without
any command. Old files still decode bit-identically (the scale mapping is
untouched, decode ignores `enc`), and a new proxy read by an older build is
left alone by its staleness check.

The fidelity test pins the gain with a frozen copy of the old encoder and a
block-mean dE76 metric (per-pixel dE is dominated by the shared 8-bit floor);
the 0.8 bound is the geometric midpoint between the no-op ratio 1.000 and the
0.632 floor cap the 8-bit quantisation sets on this scene.
2026-10-13 04:55:40 +03: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
Claude 4c1dfc5b0f LR-MERGE-HDR: keep the reference frame's lens corrections in HDR merges
Merged HDR DNGs lost the camera's embedded lens correction: load_frame strips the lens opcodes from each
source (frames are merged uncorrected) and write_linear_dng wrote no OpcodeList3, so Optics ▸ Enable Lens
Corrections did nothing on the result (Sony ILCE-7M3/7RM4A, Panasonic/Leica, DNGs with their own opcodes).

Each raw frame now keeps the lens corrections it applies (the DNG 1.6 skip rule already applied),
re-expressed for the default crop develop keeps by the new Opcode::cropped: the centre moves into the crop
and coefficients are rescaled for the crop's farthest corner. HdrResult carries the reference frame's and the
DNG writes them as its OpcodeList3. Frames turned before merging (mixed orientations) and panoramas carry none.

Tests: cropped corrections give the crop of the corrected whole (WarpRectilinear, WarpRectilinear2 with and
without reciprocal, FixVignetteRadial); an HDR merge of cropped, corrected brackets, upright and vertical, gives
the same profile correction as its reference photo (fails without the fix). Real brackets not measured yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015gRtdWF1E9358FfzhzYqCS
2026-10-13 01:05:26 +00:00
Marco Arnulfo 77d8558fc4 LR-CROP-STRAIGHTEN: a crop shrunk to fit by Straighten grows back as the angle returns (fixes #1388) 2026-10-13 02:55:39 +02:00
Marco Arnulfo 0fa8070647 AI Denoise: Install from file says why a model file is refused (fixes #1381) 2026-10-13 02:33:10 +02:00
dev-null-undefinedandClaude 1c70b24c74 M5.7: perf harnesses for slider latency, zoom windows and photo loading (examples only)
- drag_latency (ui-egui example): the whole app driven headless at 60 frames a second; per develop control,
  the latency of each drag tick until its draft is the loupe (or, with ZOOM, the zoom window) texture, the
  ticks never shown, the UI thread's frame time and the time to the full-quality render after release.
- drag_tick_bench (engine example): the UI-thread work of one drag tick outside the render.
- render_bench: ONLY=window (a 1:1 zoom window cut from the original: first window, pan, slider changes;
  GPU_ONLY=1, DUMP=file for pixel A/B), ONLY=load / load1 / jpeg (+ LOADONLY=1): the steps of opening a photo.
  The window rows carry no colon in their names, so `cargo xtask bench` records each of them (parser test).
- open_timeline (ui-egui example): opening raws in Detail through the real app logic, headless with the GPU.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-13 02:21:46 +02: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
Nathaniel LedfordandClaude Opus 5.5 5895918791 Issue #1184: a pull request template
.github/PULL_REQUEST_TEMPLATE.md asks for what the people merging ask for
most in their comments on past pull requests: the issue it fixes, overlap
with other open pull requests, whether existing edits render differently,
the shared version numbers it takes, where decoder and camera data came
from, and new dependencies or CI changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:08:52 -04:00
dev-null-undefinedandClaude f47fb86077 LR-BEHAV-GPU: say once when no GPU is found, instead of quietly rendering on the CPU
With GPU rendering on and no graphics adapter at all (wgpu: "no GPU adapter among …", e.g. no
Vulkan loader: a `cargo run` outside `nix develop` on NixOS), every render ran on the CPU, much
slower, and only Settings ▸ Performance, Help ▸ System Info and `perf.gpuReason` said why.

The desktop app now queues one start-up notice per session once the device has been tried
(`gpu::ready()`, never blocking): "No graphics processor found: LightCraft renders on the CPU, which
is much slower. Details in Help → System Info.", on Linux with "On NixOS, start it from `nix
develop`." (→, not ▸: no installed font paints ▸.) `panels::notices::gpu_notice` decides from the
reason: nothing when the GPU was turned off (preference, LIGHTCRAFT_GPU, LIGHTCRAFT_GPU_BACKEND=off),
only a software adapter was skipped, or it failed later. Headless sessions and tests never show it
(`app.gpu_notice` is set by the desktop app only). Translated in all nine catalogs; one README
sentence in the Nix section.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-13 01:58:40 +02:00
Marco Arnulfo 713d81d64b KEY-SLIDER-TYPE: a typed slider value keeps editing after the click is released (fixes #1362)
egui gives the opening release's click to the readout, so the field under it surrenders the focus. Only the field's first two frames took it back: a click held any longer ended the edit, and the value could only be typed while holding the button.
2026-10-13 00:51:05 +02:00
Marco Arnulfo cd3a942376 LR-EDIT-LIGHT-CURVE-POINT: ⌥-drag moves a curve point a tenth as far, for fine adjustment (fixes #1363) 2026-10-13 00:47:34 +02:00
dev-null-undefinedandClaude dead4367b0 M5.6: the pinned original no longer evicts the photo's other sources (64 MP edits decoded the raw again)
MediaCache::enforce_budget never evicts the original of the photo on screen (set_on_screen), but it still
counted it. A 64 MP original (Sony A7R VI: 9984×6656 linear float, 760 MiB) nearly fills the default cache
share (768 MiB) alone, so the loop evicted everything else instead: the photo's preview and thumbnail sources,
the rendered previews and the prefetched neighbours. Every edit at 1:1 (the whole-frame render and the
thumbnail), every zoom out and every step to the next photo then decoded the raw again.

The pinned original is now left out of what is compared with the budget. The rest still fits the share; the
original sits over it, as the first commit of this PR already allowed.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-13 00:41:09 +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
MennoandClaude Opus 5.5 60639aa677 LR-IMP-CAMERA-COVERAGE: Nikon D90 NEFs drop their filler columns (no pink band)
The D90 writes 4352 x 2868 samples whose last 42 columns (from 4310) are
filler at a flat ~254, above its dark image samples (black 0). The
masked-column test only trims columns near zero, so they stayed in the
image and developed as a pink band on the right. Measured on 10 of 550
NEFs from one body: the camera's 4288 x 2848 JPEG sits at (10, 10), and
green saturates at 3840-3851 while red and blue run on to 4095, so one
white level of 3830 keeps clipped highlights white. The D90 joins the D4
in MEASURED_BODIES; other bodies are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:25:33 +02:00
Marco Arnulfo f0d1ea9c4e Before/After wipe: the line stays in the middle of the view when zoomed in (fixes #1351)
A wipe drew its line through the middle of the photo. Zoomed in, that
point is usually off screen, so the whole view fell on one side of it
and showed only the Before (the original) or only the After. The line
now goes through the middle of the part of the photo on screen: the same
place at Fit, and in view at any zoom.
2026-10-13 00:14:43 +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 3480c99b3e macOS: closing the window ends the process in on_exit, as menu Quit does (fixes #1331)
The close button let eframe drop the window while AppKit's run loop was
still running; AccessKit restored the content view's class and AppKit's
Touch Bar KVO observer threw on the next display cycle. on_exit now ends
the process on macOS once settings and library are saved and background
work has stopped, as #444 does for Quit from the menu bar. Same fix as
storytold/gridcraft#117.
2026-10-12 23:58:13 +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
sanyamsingh001andCodex 6a82142d69 GH-251: document controller polling and edit interactions
Document polling of selection/settings/control ranges and shared edit
interactions. Clarify explicit-photo reads, empty selection and navigation,
and correct photo-tool ID descriptions and MCP initialization guidance.
Partial documentation work for issue 251;
hardware feedback remains outside this change.

Co-authored-by: Codex <codex@openai.com>
2026-10-12 20:33:21 +00:00