Commit Graph
2648 Commits
Author SHA1 Message Date
Brandon Thomas 2c60d2ab27 Merge PR #1778: Model downloads: Time out and cancel the name lookup (#1532) 2026-10-18 09:22:41 -04:00
Brandon Thomas 4b6db59ade Merge PR #1903: LRC-PRINT-PAGE: Page Options print page numbers, page info and crop marks (gap 15)
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-18 09:22:40 -04:00
Brandon ThomasandClaude Opus 5.5 cbdbd50f84 Merge main into #1919 (main already dropped the drop(write) line)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 09:21:51 -04:00
Brandon ThomasandClaude Opus 5.5 1e4aa93d58 LRC-PRINT-PAGE: the preview draws no Page Options for a package, as the print doesn't
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 09:21:12 -04:00
Brandon Thomas 2983a40385 Merge PR #1960: Merged develop settings are kept in range, as XMP import keeps them 2026-10-18 09:20:45 -04:00
Brandon Thomas 583e3ceefc Merge PR #2091: Reject trailing text after a bracketed IPv6 host in Url::parse 2026-10-18 09:20:43 -04:00
Brandon Thomas 5b66a4825e Merge PR #2150: Keep face index records aligned after a torn or failed append 2026-10-18 09:20:42 -04:00
Brandon Thomas dee8358c38 Merge PR #1838: Drop out-of-range GPS coordinates read from XMP 2026-10-18 09:20:40 -04:00
Brandon Thomas 8d41bf69f7 Merge PR #1894: HEIF: max_pixels on uncropped SPS sizes and grid totals (#1518) 2026-10-18 09:20:39 -04:00
Brandon Thomas f4e7d07e9b Merge PR #1989: TIFF: read strips and tiles larger than 128 MiB 2026-10-18 09:20:37 -04:00
Brandon Thomas 4e77935e6e Merge PR #2070: Show the applied profile when hovering it in the profile browser (#2057) 2026-10-18 09:20:36 -04:00
Brandon Thomas 7134099101 Merge PR #1691: LR-EXP-TYPE: omit redundant alpha from opaque 8-bit exports (#1670) 2026-10-18 09:20:34 -04:00
Brandon Thomas ad22d059db Merge PR #1844: fix(import): keep Lightroom luminance ranges open at white, report unmapped local sliders
# Conflicts:
#	contributors/people.toml
2026-10-18 09:20:33 -04:00
Brandon Thomas 29384a0404 Merge PR #1898: LR-MERGE-HEADLESS: merge dialogs remember the last settings per kind 2026-10-18 09:20:21 -04:00
Brandon Thomas 70100a34c5 Merge PR #2144: Strip XML 1.0-forbidden characters from XMP sidecar output 2026-10-18 09:20:19 -04:00
Brandon Thomas 363dbbdd9f Merge PR #2224: X-Trans CMOS 4 bodies take the X-T3's spectral matrices 2026-10-18 09:20:17 -04:00
Brandon Thomas 80e2d0e64a Merge PR #1884: AI denoise: support 102 MP Bayer raws (#1880) 2026-10-18 09:20:16 -04:00
Brandon Thomas c9f383b368 Merge PR #2040: Ignore zero or negative ISO when importing XMP 2026-10-18 09:19:45 -04:00
Brandon Thomas 389be0f6a9 Merge PR #2105: l10n: unify zh-hant library term and contact sheet wording 2026-10-18 09:19:43 -04:00
Brandon Thomas f819c8439b Merge PR #2151: Make TIFF chunk-length inference and header-plan merging fast 2026-10-18 09:19:42 -04:00
Brandon Thomas e6a7501adc Merge PR #1416: Localize Info Overlay mode-change notices 2026-10-18 09:19:29 -04:00
Brandon Thomas 0a0cb19011 Merge PR #1893: JPEG XL: check dimensions during loading & bound tracked allocations (#1517) 2026-10-18 09:19:27 -04:00
Brandon Thomas d43889145b Merge PR #2046: Start crop drags in the zone the cursor showed at the press 2026-10-18 09:19:24 -04:00
Brandon Thomas 592cb335cb Merge PR #1935: raw: alias Canon EOS R6 Mark II to EOS R6m2 2026-10-18 09:18:21 -04:00
Brandon Thomas d6a9a2e8f9 Merge PR #1845: Match f:/aperture:/focal: search tokens at f32 precision 2026-10-18 09:18:19 -04:00
Brandon Thomas 11308a5c8a Merge PR #2035: Reject out-of-range start in photo.rename and photo.renamePreview 2026-10-18 09:18:17 -04:00
Brandon Thomas 9bf08f6ce6 Merge PR #2083: Reject signed hex digits in #rrggbb colour parsing 2026-10-18 09:18:16 -04:00
Brandon Thomas 5c85bc3ee4 Merge PR #2149: Refuse catalog snapshots with an out-of-range seq 2026-10-18 09:18:14 -04:00
Hamza 0c3c500ea4 Georgian: a symbol Noto Sans Georgian cannot paint
`cargo xtask ci` fails with the craft-fonts input supplied, which CLAUDE.md says
releases always build with:

    ka in Proportional (faces: ["Noto Sans Georgian"]) lack glyphs: ✕

Two strings in ka.json use ✕ (U+2715). Noto Sans Georgian has no glyph for it
and egui's bundled fonts do not either, so a Georgian reader gets a blank where
the text describes the activity stack's stop control. Without the fonts input
those twenty tests skip, so a plain `cargo xtask ci` is green and this stayed
invisible.

The two Georgian values use × (U+00D7) instead: it reads the same at text size
and every face has it. The English keys are untouched — they are the source text
from docs/whats-new.md, and the test checks values, which is the right scope. An
English reader's font covers ✕; the problem is a translation carrying it into a
script whose face does not.

`translated_catalogs_do_not_use_missing_menu_triangles` already forbids ▸ and ▾
in locale JSON for the same reason, so ✕ joins them in one list. That matters
because ✕ is in the English source of those two strings: every language that
translates them next would hit the same failure, and a cheap test now catches it
instead of the font-dependent one.
2026-10-18 18:12:18 +05:00
Claude 23f00822eb #1927: Auto Sync fits each photo's own crop under Constrain Crop
The crop fit ran before the Auto Sync delta, so a Geometry edit carried
the active photo's fitted crop rect into the delta and onto every other
selected photo, replacing (and could enlarge) their own crops. The delta
is now taken from the edit as asked, and each target fits its own crop.
Review on #1990.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-18 12:37:56 +00:00
Carlos VillanuevaandClaude Opus 5.5 ad43a976f3 Lightroom import: one warning per skip reason; skip incomplete original paths too
A catalog with many orphaned images produced one warning line each (82 in
the reported catalog). Skipped images are now listed in one warning per
reason, showing the first ten ids. An image whose original path is empty is
skipped the same way instead of failing the whole import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RhZLBHaSnSko1eMByPibfh
2026-10-18 12:33:18 +00:00
Carlos VillanuevaandClaude Opus 5.5 9c812b88a9 Lightroom import: skip images whose file record is missing instead of failing
A catalog can keep Adobe_images rows whose AgLibraryFile, AgLibraryFolder
or AgLibraryRootFolder record is gone; Lightroom ignores them, but the import
stopped at the first one with "image N: missing file record". Such images,
and their virtual copies, are now skipped with a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RhZLBHaSnSko1eMByPibfh
2026-10-18 12:19:10 +00:00
Davit MatchakhelidzeandClaude Opus 5.5 07b2f55022 fonts: Georgian UI text from craft-fonts' Noto Sans Georgian on the web
Native already appends every non-CJK craft face via ui_fallback; the wasm build
only embedded BIZ UDPGothic and Noto Sans Thai, so add Noto Sans Georgian to
that filter. Check its glyphs next to Thai and Arabic, and bump craft-fonts-ref
to a71c20e (storytold/craft-fonts#27).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-18 16:14:56 +04:00
NetterSilverandClaude Haiku 5.5 601ddce6ef Match f:/aperture:/focal: search tokens at f32 precision
Found while testing crates/catalog/src/query.rs:130

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 13:49:17 +02:00
Marco Arnulfo eabcae0fdc LR-EXP-BITDEPTH: judge a preset's bitDepth against the format the export writes
A preset without `format` lost its `bitDepth` before the call's `path` was merged in,
because it was judged against JPEG: `app.export {preset, path: a.png}` with a 16-bit
preset wrote an 8-bit PNG. Session::export_params now merges first and drops a preset's
depth only if the format written (with the caller's fallback) lacks it; a depth the call
passes is still validated. export.savePreset judges the depth at once only when the preset
has a `format`.
2026-10-18 13:45:08 +02:00
NetterSilverandClaude Haiku 5.5 6e97193b00 Reject impossible hour/minute/second in normalize_iso
Found while testing crates/catalog/src/dates.rs:58 (normalize_iso), used by crates/engine/src/cmd/manage.rs:201

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 11:36:44 +00:00
Marco Arnulfo 302faf547b LR-EXP-BITDEPTH: check bitDepth against the format a path without a known extension gets
app.export with a path like `output` or `output.xyz` and no `format` skipped the depth
check: the desktop app then wrote JPEG and the headless backend PNG, both at 8 bits.
ExportOptions::export_format resolves the format written (with the caller's fallback for
such a path), from_params_or validates against it, and both callers use it instead of
their own override.
2026-10-18 13:27:07 +02:00
Marco Arnulfo b9159b0fce TIFF: keep the default 128 MiB intermediate buffer for small pixel budgets 2026-10-18 13:18:49 +02:00
Yorgos S. 863adcac6f X-Trans CMOS 4 bodies take the X-T3's spectral matrices
An X-T30 RAF shot in Acros embeds a black-and-white camera JPEG, so the
per-file look fits only the tone curve, and the colour came from the
neutral "camera RGB ~ sRGB" fallback: a grey sky and muted colours. The
raw decode (lossless compressed) was correct.

Add a hand-kept SAME_SENSOR alias list next to the generated
rawtoaces-data table: the 26.1 MP X-Trans CMOS 4 bodies (X-T30, X-T30 II,
X-Pro3, X100V, X-S10, X-E4) use the X-T3's measured matrices, and their
white balance reads in Kelvin through them.
2026-10-18 11:46:07 +02:00
Alex Chambers 43a47e5a3b Issue #1952: clip non-finite float image samples safely (#2071) 2026-10-17 18:40:14 -06:00
NetterSilverandClaude Haiku 5.5 cebb2be4d4 Keep the zone when shifting a capture time without seconds (#2146)
Found while testing crates/catalog/src/dates.rs:52 (shift_iso, tail = iso.trim().get(19..)); used by crates/engine/src/cmd/manage.rs:222

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-17 18:39:42 -06:00
NetterSilverandClaude Haiku 5.5 f48b2ad895 Search words with an unknown field prefix as plain text (#2099)
Found while testing crates/catalog/src/query.rs:146-177 (token_matches)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-17 18:39:08 -06:00
NetterSilverandClaude Haiku 5.5 0d2c77c258 Fix Assisted Culling bursts that cross midnight at month end (#2095)
Found while testing crates/engine/src/cmd/cull.rs:17-20 (secs, used by the burst grouping at cull.rs:45)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-17 18:38:33 -06:00
NetterSilverandClaude Haiku 5.5 5589827178 Fix offline reverse geocoding for cities at longitude exactly 180 (#2061)
Found while testing crates/geocode/src/lib.rs:105-108 (cell) vs lib.rs:189-192 (reverse)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-17 18:37:42 -06:00
skylar taylor-barrick 2218d97e89 Merge pull request #2199 from skylartaylor/open-original-media-gate
Open Original: only file types LightCraft reads reach the system opener
2026-10-17 17:07:18 -06:00
FredApps d515f9affe Merge main into file-backed Lightroom catalog import (#798)
Preserve the file-backed reader and current upstream safeguards.
Resolve documentation conflicts without integrating unmerged work.
2026-10-18 00:49:15 +02:00
eliets2 01495684d9 web: Auto language follows the browser's languages (#2085)
default_language() — what the Auto setting resolves to — only read LIGHTCRAFT_LANGUAGE,
which does not exist in a browser, so the web build always started in English. ui-egui
gains an installable default (set_default_language + a pure locale_from_tags that picks
the first shippable language from BCP-47 tags via Locale::parse_tag), and the web app
installs it at startup from navigator.languages (falling back to navigator.language),
read fallibly through js_sys::Reflect so it also works from a worker. Desktop never
installs the override and is unchanged; a language stored in ui.json still wins, which is
exactly Auto semantics.

Tests: locale_from_tags takes the first shippable language (it-IT -> Italiano,
unsupported-first skips ahead, zh-TW -> zh-hant, ja_JP.UTF-8 -> Japanese, pt-BR region
variant), empty/unsupported -> En fallback.
2026-10-17 22:30:14 +03:00
eliets2 9f2052f56b raw: audit fixes — DEFLATE row bytes in u64, checked is_packed12, cap invariant documented (#2138)
The reviewer audit of the first commit found the DEFLATE arm computed row_bytes in
wrapping usize before the gate, so on wasm32 a hostile chunk header (width 2^29+1,
16-bit) could wrap cw * cpp * bits to a small value and slip a garbage chunk past the
new gate. row_bytes is now computed in u64 (the gate caps at MAX_SAMPLES, so the usize
cast is lossless on 32-bit too), checked_pixel_count takes u64 directly so no call site
can truncate before the check, is_packed12 uses a checked_mul chain instead of comparing
against a possibly-wrapped length, and the arw decode head documents the invariant the
cap provides: with w*h <= 2^30 every downstream usize product stays inside range on
32-bit targets.

Behaviour is unchanged for every input the previous commit accepted; the only shrunk
set is chunks that passed because wrapping made row_bytes small.
2026-10-17 22:20:48 +03:00
eliets2 36d22a2745 raw, codecs: checked dimension products so wasm32 cannot wrap the size gates (#2138)
On wasm32 usize is 32-bit, so 65536 x 65536 wraps to 0 and products like w * h,
w * h * cpp, fw * fh * nc and row_bytes * ch wrapped past their own validation and let
later true-dimension indexing panic (profile.web sets panic = abort). All the enumerated
sites now validate through a checked u64 gate:

- lightcraft-raw gains checked_pixel_count(width, height) (u64, capped at MAX_SAMPLES),
  used by the ARW decode head (the strip-length equality now compares the true sample
  count, not a wrapped one) and by RawImage::check's data-length validation;
- the CR2 lossless-JPEG frame size is checked in u64 on both the Full and Header paths
  (it used to be clamped AFTER wrapping), and the no-slices width fallback is checked;
- the TIFF DEFLATE chunk's inflate length is checked and capped before the cast;
- lightcraft-codecs gains checked_sample_buf_len for the finish() buffer bound, compared
  in u64 via try_from so no cast truncates on 32-bit.

Tests pin the gate arithmetic with values that would wrap 32-bit usize (65536 x 65536,
u32::MAX x 2, 2^30 x 4). cargo check --target wasm32-unknown-unknown passes for both
crates. The issue's suggested wasm32 arithmetic-side-effects clippy pass is a follow-up.
2026-10-17 22:20:48 +03:00
eliets2 555eb4c9fd tiff: bound total entries across a parse (#2136)
max_ifds (1024) x max_entries (8192) tables that overlap in the file — SubIFD pointers
shifted by one entry reuse the same bytes — could make Tiff::parse allocate ~8M Entry values
(~400 MB) from a ~100 KB input, since count-0 entries cost nothing from the value budget and
only the per-IFD entry cap existed. ParseOptions gains max_entries_total (65 536 default,
generous for real scanned TIFFs), charged per IFD before the entries Vec is allocated, so a
hostile file stops with TiffError::Limit("entry count") instead of amplifying.

Tests: a hostile overlapping-table chain stops after 8 IFDs inside one parse, and a
legitimate multi-IFD file (chain + Exif/GPS children) still parses fully.
2026-10-17 21:53:21 +03:00