Commit Graph
1453 Commits
Author SHA1 Message Date
aiongg 35d2fc957b Merge PR #3402: RAW.colour: fit the per-file look on the vignetting-corrected sensor
Conflicts: crates/engine/src/camera_preview.rs: LOOK_VERSION stays 13, all three version notes kept; docs/raw-parity.md header merged (newer date, both changes)
2026-10-31 02:10:02 +00:00
aiongg e8566e839a Merge PR #2952: LR-EDIT-COLOR-TEMP: a one-field white balance partial keeps the other field's look (#2910)
Conflicts: docs unioned
2026-10-31 02:09:50 +00:00
aiongg a517e332d4 Merge PR #2664: raw: read Canon CR3/CR2 preview colour space from the maker note (#2654)
Conflicts: crates/engine/src/camera_preview.rs: LOOK_VERSION stays 13 (one above main), both version notes kept
2026-10-31 02:09:34 +00:00
aiongg 9a41ce9b5e Merge PR #2656: LR-PROF-CAMERACOLOR: limit tone-curve steps between pixel populations (#1904) 2026-10-31 02:09:23 +00:00
aiongg 0cc014c79a Merge PR #2514: Kelvin for Fujifilm X-Trans III bodies from the RAF's own neutral pair (#730) 2026-10-31 02:09:20 +00:00
Brandon Thomas b854bbb94e Merge PR #2835 2026-10-30 15:24:59 -04:00
Brandon Thomas 273e9078de Merge PR #2969 2026-10-30 15:24:30 -04:00
Christian BramandClaude Opus 5.5 cabc9a3d21 RAW.colour: vignetting at the warp's source position; alignment skips missing pixels
Review follow-up to the vignetting fit fix:
- `proxies` applies the embedded vignetting gain before it moves the sensor
  into the camera JPEG's lens geometry, so a warped proxy pixel gets the gain
  of the position it samples, as the render applies it.
- `alignment` reads NaN pixels (outside a lens-warped proxy) as missing. The
  `max(1e-4)` turned them into black, a false edge along the border, and the
  warped candidate lost on wide-angle RAFs with barrel distortion.
- Tests: the colour fit gets the embedded lens, the vignetting is applied
  before the warp, and alignment ignores missing pixels.

27 + 60 X-S10 RAFs: mean ΔE00 unchanged (3.06, 2.55 -> 2.54), none worse by
more than 0.02.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:39:31 +01:00
Christian BramandClaude Opus 5.5 001a58e992 RAW.colour: fit the per-file look on the vignetting-corrected sensor
The RAF look fit compared the uncorrected sensor proxy with the camera
JPEG, which is already corrected for vignetting, so the tone curve learned
the brightening and the render then applied the embedded vignetting
correction a second time. Shadows and midtones came out up to 0.6 / 0.3 EV
too light on X-S10 files.

`look_proxies` applies the embedded correction to the sensor proxy of
every per-file fit (colour, monochrome, near-black fallback), as
`fit_dng_tone` already did. LOOK_VERSION 13, RENDER_CACHE_VERSION 71.

60 held-out X-S10 RAFs: mean ΔE00 2.71 -> 2.55, 32 better, none worse by
more than 0.05.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:00:02 +01:00
Dylan M. Taylor 445dd3106e Update prompt shows the app icon and accent color instead of a letter (#3362)
UPDATE_APP (native builds; craft-update is a native-only dependency) carries our 128 px icon and accent (#f2a516, its colour in ArtCraft Launcher). The updater, the self-update
helper and craft-update's startup prompt all get them through crate::UPDATE_APP; the
prompt draws the icon, the accent and "by ArtCraft" (craft-update's default developer).

craft-update is pinned to storytold/craft-libs main at 1065653e7 (#434).
Clippy fixes for Rust 1.99 in untouched code (same logic):
- crates/engine/src/cmd/export.rs
- crates/ui-egui/src/dialogs/rules_editor/rules_move.rs
- crates/ui-egui/src/panels/detail.rs
2026-10-30 01:27:49 -04:00
radialmonsterandClaude Sonnet 5.5 b881b20b72 Kelvin for Fujifilm X-Trans III bodies from the RAF's own neutral pair (#730)
X-T20, X-T2, X-Pro2, X-E3, X-H1 and X100F have no measured colour matrix, so
As Shot showed on the relative scale. Their RAFs store the camera's own
neutral multipliers for Illuminant A and D65 (tag 0xf00c). Two points
give a line in (ln R/G, ln B/G); mired is linear along it, isotherms are
perpendicular, tint is scaled by the CIE locus spacing. Only the file's pair
and CIE colorimetry are used. Bodies with matrices are unchanged. The look
stays the per-file JPEG fit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:50:56 -04:00
radialmonsterandClaude Opus 5.5 0149200bd5 Test the end-of-curve choice in the tone step repair (#1904)
A step at the top of a fitted curve reaches its end; the pixel pairs pick
the free end (top knots drop to the repair slope) or the window pinned to
the top knot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:47:26 -04:00
radialmonsterandClaude Opus 5.5 3335fffb87 Limit tone-curve steps between pixel populations in the camera look fit (#1904)
The per-file look fitted from the embedded JPEG can join two pixel
populations the camera renders at different brightness for the same scene
luminance (by hue) with a near-vertical tone step. On a dark ISO 1100
D3400 frame of saturated blue and red the step had a log-log slope of
12-28 and the render's fine luminance noise in the blue area was 1.46x
that of Adobe's DNG of the same frame.

Fitted tone curves are now limited to a log-log slope of 4 between knots
(fitted looks: median steepest segment 2.1, 95th percentile 3.6). A
steeper segment is spread over the smallest window of knots whose
end-to-end slope is under the bound; a window that reaches an end of the
curve is weighed against leaving that end free at slope 2, keeping the
one closer to the fit's pairs. D3400 blue-area luminance noise drops to
0.99x Adobe's.

LOOK_VERSION 13, RENDER_CACHE_VERSION 71.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:47:14 -04:00
radialmonsterandClaude Opus 5.5 39b56219f0 raw: read Canon CR3/CR2 preview colour space from the maker note (#2654)
The default camera look is fitted to the raw's embedded JPEG, decoded in the
colour space embedded_preview_color_space reports. That function parsed the
file as TIFF, which fails on a CR3 (ISO BMFF), so a CR3 shot in Adobe RGB was
read as sRGB and the look was fitted to a desaturated target. A CR2 shot in
Adobe RGB parses, but its EXIF says ColorSpace Uncalibrated with InteropIndex
"R98" rather than Adobe RGB's "R03", so it was read as sRGB too.

Read the Canon maker-note ColorSpace (0x00b4: 1 = sRGB, 2 = Adobe RGB): for a
CR3 from its CMT3 block, else an EXIF ColorSpace of sRGB from CMT2; for a CR2
from the EXIF maker note, before the EXIF fallback.

LOOK_VERSION (13) and RENDER_CACHE_VERSION (71) are bumped so cached
smart previews and thumbnails are rebuilt with the new look. Smart previews of
preview-only raws now follow LOOK_VERSION too, since their proxy is the
embedded JPEG read in the declared colour space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:46:11 -04:00
radialmonsterandClaude Opus 5.5 953c4ee5fc raw: decode lossy single-plane (grey) JPEG XL tiles in LinearRaw DNGs
Lightroom Classic's HDR and panorama merges of monochrome raws store a
one-plane LinearRaw image as lossy (XYB) JPEG XL tiles whose codestream
declares a grey colour encoding (16-bit float with a linear curve, or
16-bit integer with the sRGB curve). Those were refused as "lossy JPEG XL
tile with a single colour plane", so the files opened preview-only.

A lossy grey tile is still coded as three XYB channels. It is now
restored like the RGB case: jxl-oxide renders linear sRGB (never the
declared encoding, which would clip), the single plane is the luminance
(CIE Y, D65) of that, then the declared transfer curve is applied.
One plane must be declared grey and three RGB; HDR curves, other white
points and intensity targets above 255 stay unsupported.

RENDER_CACHE_VERSION 70 -> 71: files that showed their embedded preview
before render from raw data now, under the same content key.

Refs #275

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:44:42 -04:00
Dylan M. Taylor 6774d1419f refactor(ui-egui): replace wildcard imports with explicit lists 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 5b5ddc3904 fix(engine): import denoise model and gpu names explicitly 2026-10-28 03:24:18 +00:00
Dylan M. Taylor c9d44f7804 style(engine): expand module imports explicitly 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 4d8369b091 test(engine): factor complex regression scenarios 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 47839a61db refactor(bench): dispatch specialized render modes 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 9e1483388f refactor(import): separate Lightroom collection staging 2026-10-28 03:24:18 +00:00
Dylan M. Taylor e8f52cc07e refactor(print): define blit rectangles 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 33252920e3 refactor(denoise): model installation requests 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 694b237f0a refactor(faces): model crop and plane shift inputs 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 2f42ff8944 refactor(pipeline): group pixel finish parameters 2026-10-28 03:24:18 +00:00
aiongg 07bc2008d9 Merge pull request #3045 from dotCooCoo/fix/local-skips-windows-hidden-folders
Local: skip offscreen folder widgets and show browsed hidden paths
2026-10-27 13:47:10 -04:00
aiongg 94ea495bdb Merge pull request #3020 from dotCooCoo/fix/windows-hard-link-write-target
Originals: on Windows a hard link to an original counts as that original
2026-10-27 13:46:50 -04:00
NetterSilverandClaude Opus 5.5 3ce8dbc55b Drop copies and libm calls from 8-bit export encoding
- finish_8bit/finish_deep hand back the render itself when there is no
  output sharpening and no watermark. Before, every export cloned the
  image (~100 MB at 24 MP) and output_sharpen built a ~290 MB float copy
  of it even for SharpenFor::None, all on one thread.
- Output sharpening's box blurs run row-parallel (par_rows); each pixel
  is computed as before.
- The parallel JPEG encoder converts each band's rows to YCbCr inside the
  band's task instead of first filling whole-image planes (~290 MB for
  4:4:4 at 24 MP, written once and read back).
- fdct_quant rounds with plain arithmetic (round_i16) instead of
  f32::round, a libm call per coefficient without SSE4.1; it equals
  `x.round() as i16` for all 2^32 inputs.

Output is byte-identical (pinned by encoded_bytes_are_pinned and
sharpened_pixels_are_pinned, whose hashes come from main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 15:43:41 +01:00
NetterSilverandClaude Opus 5.5 30d0a37051 Add a single-photo export benchmark
examples/export_bench imports the files given and runs export_photo
(decode, full-size render, encode) N times, forgetting the decoded
original between runs like a batch export does, and prints the median
and minimum wall time. OPT takes export options as app.export JSON,
PHASES=1 times render and encode separately, OUT=dir writes the files
for byte comparisons between builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 15:43:41 +01:00
dotCooCoo d826e79fa2 Skip offscreen Local rows and share hidden-folder checks
Reuse cached folder listings through Arc and allow tests to inject Local places.
Show browsed folders below hidden ancestors as session roots. Apply the same
hidden-entry checks to folder walks, browsing, import scanning, and Local.
2026-10-26 22:36:11 -07:00
dotCooCoo 0c7640f7d3 Reject unavailable Windows file identities in strict comparisons
Return an error when either file index is zero. Keep the resolved-path fallback for lenient comparisons. Test both unknown-identity orderings and distinguish identity lookup failures from known-original refusals.

Merge main at 662df66f.
2026-10-26 20:28:34 -07:00
skylar taylor-barrick 662df66f1c Preserve queued file drops across dialogs and restore Flatpak sources (#2975) 2026-10-27 03:50:41 +01:00
aiongg 8d8994ec87 refactor(lightcraft-engine): split cmd/library.rs into cmd/library/ 2026-10-26 21:39:56 +00:00
aiongg ff614cbe43 refactor(lightcraft-engine): split import.rs into import/ 2026-10-26 21:39:56 +00:00
aiongg 39d6a8d668 refactor(lightcraft-engine): split rename.rs into rename/ 2026-10-26 21:39:55 +00:00
aiongg 8942984c35 refactor(lightcraft-engine): split denoise.rs into denoise/ 2026-10-26 21:39:55 +00:00
aiongg 21304db29b refactor(lightcraft-engine): split media.rs into media/ 2026-10-26 21:08:55 +00:00
aiongg 50509093b6 refactor(lightcraft-engine): split camera_preview.rs into camera_preview/ 2026-10-26 21:08:55 +00:00
aiongg e3c594cab8 refactor(lightcraft-engine): split export.rs into export/ 2026-10-26 21:08:55 +00:00
aiongg 9b197d8215 refactor(lightcraft-engine): split files.rs into files/ 2026-10-26 21:08:55 +00:00
aiongg 658f3c26d5 refactor(lightcraft-engine): move denoise gpu_tests to denoise/gpu_tests.rs 2026-10-26 21:05:53 +00:00
aiongg 7707047684 refactor(lightcraft-engine): move media thumbnail_hash_tests to media/thumbnail_hash_tests.rs 2026-10-26 21:05:53 +00:00
aiongg d151df0149 style: cargo fmt the moved test modules 2026-10-26 18:30:36 +00:00
aiongg 73adafbae0 refactor(lightcraft-engine): move tests_slide_template.rs to slide_template/tests.rs 2026-10-26 18:28:42 +00:00
aiongg 9cc8a1c765 refactor(lightcraft-engine): move tests_*.rs to tests/ 2026-10-26 18:24:54 +00:00
aiongg c579f226ab refactor(lightcraft-engine): move print/compose.rs tests to crates/engine/src/print/compose/tests.rs 2026-10-26 18:15:58 +00:00
aiongg e6b0b386a7 refactor(lightcraft-engine): move print/layout.rs tests to crates/engine/src/print/layout/tests.rs 2026-10-26 18:15:57 +00:00
aiongg 41064fabb5 refactor(lightcraft-engine): move crs.rs tests to crates/engine/src/crs/tests.rs 2026-10-26 18:15:57 +00:00
aiongg a3ec3eadef refactor(lightcraft-engine): move rename.rs tests to crates/engine/src/rename/tests.rs 2026-10-26 18:15:57 +00:00
aiongg 89083b6c77 refactor(lightcraft-engine): move camera_preview.rs tests to crates/engine/src/camera_preview/tests.rs 2026-10-26 18:15:56 +00:00