7 Commits
Author SHA1 Message Date
aiongg e235ac71e2 Merge PR #3375: LR-IMP-FORMATS: a Samsung panorama JPEG with its SEF trailer imports
docs/whats-new.md: the PR's 2026-10-30 section added above main's sections.
2026-10-31 02:11:48 +00:00
Bruno-Alumn eb5829cfb5 LR-IMP-FORMATS: a SEF trailer counts only with nonempty blocks of their entry's type, and an EOI is looked for before it (#3350) 2026-10-30 11:16:05 +01:00
Bruno-Alumn afee9df020 LR-IMP-FORMATS: a Samsung panorama JPEG with its SEF trailer imports (#3350)
Some Samsung panoramas have no end-of-image marker: the scan data runs
straight into the SEF trailer at the end of the file, so the header
check refused them as truncated, and jpeg-decoder (DCT-scaled previews)
and zune-jpeg both fail on the trailer's bytes after the scan.

When the file ends with a valid SEF trailer (SEFT, a directory length
that points at SEFH, a sane entry count, every entry's block inside the
file before SEFH) and no EOI is reached, the image is read as the bytes
before the earliest SEF block plus an EOI, for both the header and the
decode. The cut must fall in scan data after the first SOS; a JPEG cut
short without such a trailer is still refused.
2026-10-30 10:25:32 +01:00
insideTheFluxandClaude Opus 5.5 fbbf5c0c53 LR-IMP-FORMATS: GIF and BMP coverage comes from the pixel data, not the file's length (#2553)
Padding counted as pixel data: a file padded with junk could still claim a canvas up to
max_pixels, which the decoder allocates before it finds the data missing.

- Uncompressed BMP: the rows the header describes (bits per pixel, 4-byte row padding) must
  all be present after the pixel-data offset; the decoder reads every row in full.
- RLE BMP: the commands are walked as the decoder paints them (runs clipped at the row's end,
  end-of-row, delta, end-of-bitmap); bytes after the end draw nothing.
- GIF: the first frame's LZW codes are walked up to the end code, keeping only the length of
  each table string; data sub-blocks after the end code draw nothing.

A canvas the data leaves mostly blank stays limited to 4 MP. New tests: one padded file per
case (all four were accepted before), and the LZW walk against frames the encoder wrote.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TuX1qw9ieyuJ1ZFrrUxzc
2026-10-24 07:46:31 -07:00
insideTheFluxandClaude Opus 5.5 1bc7cab6c8 LR-IMP-FORMATS: GIF density from the first frame; mostly blank canvases capped at 4 MP
From echelon's review of #2607:

- A GIF's LZW data now bounds its first frame's own width x height, not the logical screen's,
  so a valid GIF with a small first frame on a larger screen imports.
- A canvas the file's data leaves mostly blank (a GIF screen larger than its first frame, or an
  RLE BMP larger than its runs could cover at 255 pixels per 2 bytes) still costs its whole size
  in from_decoder, so it is limited to 4 MP (SPARSE_MAX_PIXELS) and refused before the decoder
  allocates it. Densely coded canvases keep the max_pixels limit.

Tests: a 64-byte RLE BMP declaring 2001 x 2000 or 32000 x 32000 is refused ("mostly blank");
the RLE BMP that ends early still opens at 2000 x 2000; a GIF with a 1 x 1 first frame opens on
a 2000 x 2000 screen and is refused on a 32767 x 32767 one. The first three fail without this
change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtjHGt5gnCHXgLt4NbGorf
2026-10-23 14:37:53 -07:00
insideTheFluxandClaude Opus 5.5 2d69246d29 Merge storytold/main into fix/2553-gif-bmp-header
Picks up #2667 (the shared Linux gate) so this PR runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtjHGt5gnCHXgLt4NbGorf
2026-10-23 13:53:22 -07:00
aiongg f3bb7a9f30 CI: one test binary per crate, line tables only, one WASM check (#2710)
* CI: dev profile keeps line tables for workspace crates and no debug info for dependencies

* Control server tests: persistent_requests_and_slow_replies_outlive_the_idle_read_timeout no longer races the idle timeout

Each request (and the closing half-shutdown) reaches the socket before the
worker reads, so on a slow machine only the reply waits outlast the 100 ms
idle timeout, as the test intends. The idle test sends its input the same
way, and the no-frames test allows 5 s instead of 2 s to give up.

* CI: one integration-test binary per crate

Each crate's tests/*.rs become modules of tests/it/main.rs (51 test files
into 13 binaries, plus 6 that stay their own). Inner #![cfg] attributes
move to the mod lines. Files that change state for the whole process keep
a binary of their own: codecs jxl_tail_heap and raw sr2_heap (dhat global
allocator), gpu shutdown, shutdown_first and memory, ui-egui shutdown.
Docs, comments and the GPU probe name the new paths and targets
(--test it <module>::); the CI report names an it binary's skips after
the crate.

* CI: tests under nextest, doctests apart, one wasm check

xtask ci runs the tests with cargo nextest run --lib --bins --tests when
cargo-nextest is installed, else cargo test with the same targets and a
one-line notice; doctests run after them with cargo test --workspace --doc.
The heif and hardware GPU steps use the same runner. Examples stay out of
the test build (clippy --all-targets still checks them). Concurrent tests
under nextest follow the RUST_TEST_THREADS cap (NEXTEST_TEST_THREADS).
The wasm check is one cargo check --keep-going over the same crates, and
clippy runs with --keep-going.

* CI: tests run under cargo test by default, nextest with LIGHTCRAFT_NEXTEST=1 (per-process scene cache)
2026-10-23 13:34:30 -04:00