- gpu: the test modules share one GPU_LOCK, and timing and vector_mask
take it too, so one process drives one wgpu device at a time.
- ui-egui: the wgpu tests in pattern_preview_canvas, adjust_preview_gpu,
marquee_autoscroll and layout_perf take gpu_lock().
- affinity compound_limits: the child process selects its test by the
module path (compound_limits::<name>); with --exact, the bare name
matches no test and the child passes without running the check.
- xtask scorecard reads crates/io/tests/it/corpus.rs.
- Docs and comments name the new test paths and the --test it filters.
The colr nclx primaries and transfer were dropped, so a 10-bit BT.2020 HLG
HEIC opened as if its samples were sRGB. photocraft-heif now returns the
nclx (inherited from grid tiles like the ICC profile), codecs decodes PQ and
HLG to linear light in 32-bit float (BT.2100 inverse OETF + OOTF at 1000
cd/m2, 203 cd/m2 diffuse white = 1.0), and io tags the document with the
matching profile from the new photocraft_cms::builtin::cicp_rgb. BT.709/sRGB
SDR files are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
heic-rs 0.1.2 to 0.1.4 fix six panics on malformed files, found by fuzzing:
four in release builds (a uuid box too small for its extended type, a
block starting right of the picture, a conformance window larger than the
picture, and a reference row below the picture) and two with overflow
checks on (a PCM bit depth above the sample bit depth, a slice QP out of
range). The API, MSRV and output are unchanged.
Both pins move together: crates/heif and the codecs fuzz target, which
calls heic-rs directly. guarded() stays as the backstop it was meant to be.
* Open HEIC/HEIF photos (#355)
iPhones save HEIC by default and Photoshop opens it; PhotoCraft had no
HEIF code, so .heic was missing from File > Open and failed to decode.
Add Format::Heif to photocraft-codecs, decoded by heic-rs (pure Rust,
forbid(unsafe), MIT OR Apache-2.0, wasm-ready): single pictures and
grid-tiled photos, 8-bit to U8 and 10/12-bit to U16, auxiliary alpha,
ICC, EXIF and XMP. The container's irot/imir/clap are applied and EXIF
Orientation is rewritten to 1, so photos are never turned twice. Limits
are checked against the declared size before decoding. Read-only (no
pure-Rust HEVC encoder), listed in ASYMMETRIC_EXCEPTIONS.
File > Open (desktop, web) and the batch list accept heic/heif/hif.
Tests compare against Apple's own decode and a 16-bit source, cover
orientation, metadata, limits and every truncation; fixtures from
heic-rs and pillow-heif are attributed in ATTRIBUTION.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* HEIF: pin heic-rs exactly and add a decode_heif fuzz target
Review follow-up: heic-rs is young and parses untrusted files, so pin it
(=0.1.1) and fuzz the HEIF path. The target covers both orientation
paths and is meant to run with -timeout so a hang is reported, not
only a panic. It is added to the CI fuzz matrix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* HEIF: a heic-rs panic is a malformed-file error, not a crash
Fuzzing decode_heif found two out-of-range slices in heic-rs 0.1.1 on
malformed files:
- in its box parser (boxes.rs:130), reachable from a 72-byte file, even
through the metadata-only probe;
- during HEVC reconstruction (hevc/decode/recon.rs:70).
The background job path catches panics, but the synchronous ones (jobs
off, the CLI) did not. The HEIF codec now runs the decoder under
catch_unwind and reports a panic as CodecError::Malformed, as
gpu/health.rs already does around wgpu.
The fuzz target also calls heic-rs directly, so its panics still reach
the fuzzer. The 72-byte input is a regression test, which fails
without the guard.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* HEIF: move the decoder into an optional photocraft-heif crate
The heic-rs decoding from #372 now lives in `crates/heif` (photocraft-heif, standalone, depends
only on heic-rs =0.1.1): probe, decode with a pixel limit, container transforms, alpha, 8/10-bit,
ICC/EXIF/XMP and the catch_unwind guard, behind a small API of its own (Info, Options, Decoded,
Error). photocraft-codecs uses it behind a new non-default `heif` feature; the apps and
photocraft-io forward it. HEIF detection, extensions and mime stay compiled in, so without the
feature a HEIC file is still recognised and opening it is a clear "HEIC/HEIF support isn't
included in this build of PhotoCraft" error. `cargo xtask layers` allows exactly codecs -> heif
between standalone crates.
The fixtures are no longer committed: `cargo xtask corpus --heif` fetches them from heic-rs
(tests/fixtures, v0.1.1) and pillow-heif (tests/images) at pinned commits, verified against
xtask/heif-corpus.sha256 (same bytes as the PR's copies). The fixture tests run with
`--features corpus,heif` (`cargo xtask test-corpus` enables both).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Build CI and official binaries with HEIC support (--features heif)
CI test and clippy, the FreeBSD job, and the macOS, Linux (and Flatpak), FreeBSD, Windows and
web packaging all build with the `heif` feature; CI also tests codecs/io without it on Linux so
the "not in this build" path stays covered. `cargo xtask wasm` also checks photocraft-codecs with
`--features heif`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Docs: HEIC open is an optional build feature, on in official builds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>