Commit Graph
464 Commits
Author SHA1 Message Date
aiongg 56c842d8fe Merge track r3-t09
# Conflicts:
#	docs/parity-checklist.md
#	docs/raw-parity.md
#	docs/ui-parity.md
#	docs/whats-new.md
2026-10-31 02:31:25 +00:00
aiongg e05c4f7e7c Merge track r3-t08
# Conflicts:
#	crates/meta/README.md
#	crates/ui-egui/locales/cs.json
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/fi.json
#	crates/ui-egui/locales/fr.json
#	crates/ui-egui/locales/id-formats.json
#	crates/ui-egui/locales/id.json
#	crates/ui-egui/locales/it.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/ka-formats.json
#	crates/ui-egui/locales/ka.json
#	crates/ui-egui/locales/pl.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/sv-formats.json
#	crates/ui-egui/locales/sv.json
#	crates/ui-egui/locales/uk.json
#	crates/ui-egui/locales/vi.json
#	crates/ui-egui/locales/zh-hans.json
#	crates/ui-egui/locales/zh-hant.json
#	crates/ui-egui/src/panels/grid.rs
#	crates/ui-egui/tests/it/main.rs
#	docs/gaps.md
#	docs/library-shortcuts.md
#	docs/parity-checklist.md
#	docs/raw-parity.md
#	docs/user/guides/export-photos.md
#	docs/whats-new.md
2026-10-31 02:31:16 +00:00
aiongg a261544b77 Integration: #3400 move the framing test's doc line back above its test 2026-10-31 02:10:32 +00:00
aiongg 3c228ae23e Merge PR #3400: Never crash: a Samsung encryption key past i64::MAX doesn't overflow keyed() 2026-10-31 02:10:25 +00:00
aiongg b38bb32185 Merge PR #3386: Never crash: strip byte counts near u64::MAX don't overflow their sum in ORF, SRW, ARW and PEF
docs/whats-new.md: both entries under 2026-10-30
2026-10-31 02:10:25 +00:00
aiongg 1d10bc70e1 Merge PR #3321: LR-IMP-FORMATS: decode compressed RAF 13–17 % faster with a buffered bit reader 2026-10-31 02:10:18 +00:00
aiongg eb5b91f238 Merge PR #2750: Never crash: tiles far larger than the image are refused before decoding (#2554) 2026-10-31 02:10:18 +00:00
aiongg ce01d4b7d0 Merge PR #2740: Never crash: ARW and SRW strips shorter than declared are refused before allocating (#2561) 2026-10-31 02:10:18 +00:00
aiongg acf0f6b938 Merge PR #2698: LR-IMP-FORMATS: AHD blends its candidates where noise alone would pick one, no maze in noisy raws (#2094)
docs/whats-new.md: both entries kept
2026-10-31 02:10:17 +00:00
aiongg 4c1fdedd48 Merge PR #2628: raw: CR3 preview box scan checks 32-bit lengths for overflow (#2569) 2026-10-31 02:10:08 +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 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
aiongg e0d393c732 Merge PR #2777: LR-EDIT-OPTICS-PROFILE: Fujifilm X-S20 embedded lens corrections and spectral matrices 2026-10-31 02:08:57 +00:00
aiongg c03c567f5e Merge PR #2732: LR-EDIT-OPTICS-PROFILE: Sony ILCE-6700 in-file distortion
docs/gaps.md: main's header, gap 9 and revision rows kept; gap 8 row and header carry the ILCE-6700 mention; the PR's revision row added.
2026-10-31 02:08:57 +00:00
Brandon Thomas b854bbb94e Merge PR #2835 2026-10-30 15:24:59 -04:00
Brandon Thomas 13711ace2b Merge PR #2155 2026-10-30 15:24:41 -04:00
samueliliandAntigravity 8ffe73cc3c fix raw lens and vignette corrections
- X-S20 lens distortion and vignetting scale fixes
- X-S20 / X-S10 / X-M5 spectral sensor mappings
- Add Samuel Li to contributors/people.toml

Co-Authored-By: Antigravity <noreply@google.com>

- address review concerns

- update RENDER_CACHE_VERSION value in docs/camera-preview-colour.md

- made sure diagonal scales are exact match
2026-10-30 08:40:55 -07:00
Bruno-Alumn 7597810299 SRW: a huge encryption key doesn't overflow keyed()
The maker note's key (0xa020) can be LONG8, so a value past i64::MAX
made `-1 * key` overflow: a panic in debug and test builds. Use a
wrapping multiply; only the low 32 bits are kept, so real files decode
the same.
2026-10-30 16:25:20 +01:00
Bruno-Alumn 1c906ea3db Never crash: strip byte counts near u64::MAX don't overflow their sum in ORF, SRW, ARW and PEF
The TIFF reader accepts LONG8 (type 16) StripByteCounts in classic
TIFF, so a file can declare strips of u64::MAX and 1 bytes. The ORF,
SRW, ARW and PEF decoders added the strip lengths with
Iterator::sum::<u64>(), which panics on overflow in debug builds. They
now add them with a saturating fold, as raw/src/lib.rs already does,
so such a file is refused or read as far as its data go.

The tests rewrite a synthetic file of each decoder into two strips
with LONG8 counts [u64::MAX, 1] (vendor::tests::huge_strip_counts);
PEF is checked for the Huffman-coded and the uncompressed path.
2026-10-30 13:37:16 +01:00
radialmonsterandClaude Opus 5.5 29f9c19046 test(raw): spell control bytes in CR3 preview literals as escapes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-29 21:48:04 -04:00
Christian BramandClaude Opus 5.5 42e54b5bb0 LR-IMP-FORMATS: decode compressed RAF 13-17 % faster with a buffered bit reader
The Fujifilm entropy reader read each unary prefix one bit at a time and refilled
its accumulator a byte at a time. It now keeps up to 64 bits buffered and counts a
prefix's zeros with leading_zeros, failing exactly where reading bit by bit would
(escape limit, end of stream). A property test checks it against reading bit by bit.

Sensor arrays are unchanged bit for bit: the 17 reference arrays of
corpus_fujifilm_compressed_samples, plus decode checksums of 20 X-Trans CMOS 4 files.
Decode on an Apple M2: X-S10 lossless 265 -> 226 ms, X-H2 448 -> 378 ms,
GFX 100 762 -> 644 ms (docs/raf-compression.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:36:40 +01:00
radialmonsterandClaude Opus 5.5 15a489c8a5 Kelvin presets: a stored neutral pair with equal endpoints reads as unusable
pair_temp_tint divided by the zero line length of a repeated point, so a
deserialized pair gave a non-finite temperature and tint instead of None.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:50:57 -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 63b6de336f raw: CR3 preview box scan checks 32-bit lengths for overflow (#2569)
On wasm32 a PRVW/THMB box or JPEG length near u32::MAX wrapped j + len and
start + size, so both bounds checks passed and the slice panicked (abort in
the web build). Use checked_add and bytes.get, and add a regression test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:50:04 -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 20c1f3c057 raw: test the grey JPEG XL restore through decode
The existing synthetic lossy RGB fixture tiles are re-declared grey by a
header edit (colour space RGB to Grey, dropping the 6-bit primaries field
a grey encoding does not carry, per the ColourEncoding bundle). Their XYB
frame data is unchanged, so they decode as one grey plane whose rendered
channels differ. The test checks decode against the gradient's BT.2100
luminance in the linear and sRGB curves.

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
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 ca69e74b62 fix(raw): check opcode byte counts without overflow 2026-10-28 03:24:18 +00:00
Dylan M. Taylor 2c7d98b5e2 refactor(raw): separate DNG metadata and opcode parsing 2026-10-28 03:24:18 +00:00
NetterSilverandClaude Opus 5.5 93487af3b3 Cut serial work from raw development and GPU transfers
- RawImage::develop demosaics only the default crop with AHD when there
  is no OpcodeList3 (ahd_window), instead of demosaicing the margin too
  and then copying the crop out of the full picture on one thread.
- Gpu::upload writes through queue.write_buffer_with and copies into
  the staging buffer in parallel parts. create_buffer_init zeroed a
  staging buffer and then copied over it, two single-threaded passes
  over a full-size photo's ~290 MB.
- finish_and_read copies the mapped readback out in parallel parts (one
  thread read the 91 MB of a 24 MP export at ~2 GB/s, ~45 ms).

Output is byte-identical (ahd_window_is_the_crop_of_the_whole,
uploads_read_back_exactly).

Export of a 24 MP ARW to full-size JPEG (examples/export_bench, 75
interleaved runs each on a shared 16-thread Ryzen):
main 802 ms median / 614 ms min -> this branch 647 / 525 (-19.3% / -14.5%).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 15:43:41 +01:00
strebdom 64a16f378c Merge upstream main into fix/ahd-soft-choice; RENDER_CACHE_VERSION 71 (main took 70) 2026-10-27 07:37:57 +01: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 59d1d6f0f8 refactor(xtask): point the raw corpus test and ci-quick map at the moved sources 2026-10-26 21:39:56 +00:00
aiongg f030eb4c71 refactor(lightcraft-raw): move highlight.rs tests to crates/raw/src/highlight/tests.rs 2026-10-26 18:16:09 +00:00
aiongg 5809ed4e51 refactor(lightcraft-raw): move preview.rs tests to crates/raw/src/preview/tests.rs 2026-10-26 18:16:09 +00:00
aiongg 64e4683045 refactor(lightcraft-raw): move opcodes.rs tests to crates/raw/src/opcodes/tests.rs 2026-10-26 18:16:08 +00:00
aiongg b61a981f73 refactor(lightcraft-raw): move lib.rs tests to crates/raw/src/tests.rs 2026-10-26 18:16:08 +00:00
aiongg 25768ea23a refactor(lightcraft-raw): move ljpeg.rs tests to crates/raw/src/ljpeg/tests.rs 2026-10-26 18:16:07 +00:00
aiongg 5699489a3e refactor(lightcraft-raw): move crates/raw/src/demosaic/mod.rs to crates/raw/src/demosaic.rs 2026-10-26 18:15:09 +00:00
aiongg 62514e34b8 refactor(lightcraft-raw): move crates/raw/src/vendor/mod.rs to crates/raw/src/vendor.rs 2026-10-26 18:15:09 +00:00
Michael Anderson ab3f6af82a Merge remote-tracking branch 'origin/main' into fix/2119-erf-mef-strip-length
# Conflicts:
#	crates/raw/src/vendor/mef.rs
2026-10-25 19:20:01 -05:00
Dylan M. Taylor 3022baa861 security(raw,meta): follow-ups from review
An oversized CR3 candidate is skipped without ending the search, repeated child IFD references count once toward the pending cap, deflated chunks lay their rows out as the unpacker reads them (16-bit words, 32-bit word alignment), the tile grid's nominal size is checked against the image before anything is decoded, chunk grouping saturates, and the XMP flattened-key budget is document-wide. The JPEG-header test now parses a real header.
2026-10-25 16:12:03 -04:00
Dylan M. Taylor d8ceb3a6af security/meta,merge,raw,tiff,denoise: bound memory sized by attacker-shaped inputs
XMP flattening, sparse-focus EXIF decode (plus the maker-note and TIFF value
budgets), lossy-DNG chunk staging, panorama stitch frames, the reference ONNX
executor's tensors and the denoise product reader all now reject or cap what a
malformed file can make them allocate: each result is checked before the
memory behind it is reserved, every regression carrying a test that fails
without its bound.
2026-10-25 15:42:19 -04:00
Dylan M. Taylor d00df6319c security/raw: bound hostile-memory paths in raw decoders
Sparse walkers, truncated MEF/lossy-JPEG strips, embedded JPEG sizes, the
CR3 preview marker walk, OpcodeList3 full-image passes and caller-supplied
Deflate tile edges each let a small file or one bad argument multiply
allocations or CPU work thousands of times. Each path now is bounded,
every fix with a regression test that failed (or blew up) before it, plus
a tiff::image single_chunk helper so preview extraction never builds a
descriptor vector for a hostile multi-strip layout.
2026-10-25 15:42:19 -04:00
Brandon ThomasandClaude Opus 5.5 0deec1251f Merge main into #673
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 10:14:13 -04:00
Julian ZahnowandClaude Opus 5.5 42067239b6 fix(raw): refuse the ILCE-6700 path for a default crop that isn't 3:2
The APS-C knot spacing comes from the default crop, so only the measured 3:2 shape gets a spacing
(review: CodeRabbit on #2732).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 15:37:44 +02:00
Julian Zahnow 9710a64ba2 Merge remote-tracking branch 'origin/main' into sony-ilce6700-distortion
# Conflicts:
#	docs/gaps.md
2026-10-24 13:33:21 +02:00
strebdom 08db59df29 Merge branch 'main' of https://github.com/storytold/lightcraft into fix/ahd-soft-choice
# Conflicts:
#	docs/whats-new.md
2026-10-24 12:36:00 +02:00
Brandon Thomas 0605272e69 Merge PR #2620 2026-10-23 17:21:16 -04:00
Gabriel Luís da Silva 408b3ec844 Never crash: ARW and SRW strips shorter than declared are refused before allocating (#2561)
The ARW one-byte and packed 12-bit strips and the SRW word and packed
12-bit strips sized the frame from the declared StripByteCounts, while
chunk_bytes clamps the strip to the file. A file of a few hundred bytes that
declares a large frame made the full decode allocate it (up to 2 GiB) and
unpack zeros. Both now check the bytes present against the declared strip
first and return Corrupt, as the ORF block path and RAF already did.
2026-10-23 18:02:41 -03:00