The six PSD PRs merged one by one leave #1131's test calling samples()/to_rgb(), which #1139
replaced; vangel76's integration draft #1149 has the adapted version.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The 2^28 pixel limit applied per image; one composite or layer decode kept
the ZIP output, a Vec<f32> per channel and the result alive together, and the
bake size came from the file's quad. A decode now charges every buffer
against a byte budget (4 GiB, 1 GiB on 32-bit), checks its whole expected peak
before allocating, writes channels straight into the result and returns an
error when over budget. Bakes are at most 4x the document across and 2^24
pixels.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Raw channels are borrowed, ZIP planes are un-predicted in place in the inflated buffer,
the 32-bit un-predictor uses one scratch row, the layer mask tests the rect per row
instead of per pixel (and skips a constant factor of 1.0), and a placed-layer bake
solves the quad once and hoists per-triangle invariants. Output is bit-identical;
tests compare against the replaced implementations and count the avoided work.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Psd::parse drops the layers, records Psd::warnings and keeps the header and
merged image; the importer then imports the flattened image as one layer and
reports 'Layers could not be read'. Header damage and a missing merged image
stay hard errors.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
One decode_plane for raw/RLE/ZIP (decode_channel and composite), placed::eight and
quad_from for the SoLd/PlLd transforms, the writer's big-endian and UTF-16 helpers
from descriptor.rs, one delimiter const in engine_data.rs, and the dead binding in
write.rs. No behaviour change; adds ZIP and RLE composite tests.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Psd::tree flattens groups nested deeper than MAX_GROUP_DEPTH into their depth-64 parent, keeping every layer, so the importer recursion and the tree's Drop/Clone/PartialEq are bounded. The import result reports how many groups were flattened.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
cargo +1.95 clippy --workspace --all-targets --release -- -D warnings
stopped on seven `if` blocks that clippy wants folded into their match
arm (psd, text, effects x2, pdf x2, render). Each becomes a match guard.
The behaviour is unchanged: when a guard is false the value falls through
to arms that can't match it and then to `_ => {}`. The one exception is
the PDF PostScript calculator, where a `{` past the nesting limit would
fall through to the operator arm; it keeps its own no-op arm, so it is
still skipped rather than pushed as an operator.
The descriptor depth limit restarted at 0 inside every nested descriptor (Objc / GlbO /
ObAr), so a crafted file of 100 000 nested descriptors (2.4 MB) recursed until the stack
overflowed and aborted the app. The depth now carries through nested descriptors.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Layer bounds come straight from the file as four i32s. Rect::width/height subtracted them in
i32 (overflow: a panic in debug builds, garbage sizes in release), and layer_pixels allocated
width x height pixels before reading any data, so a 100-byte file claiming a 2^31-square layer
hit "capacity overflow" (or an out-of-memory abort). Widths are now computed in i64 and
clamped, every decoded image is capped at 2^28 pixels (Error::Unsupported beyond that), zlib
data is inflated with a limit of the expected size, RLE count tables and UTF-16 strings
reserve no more than the remaining bytes, and the per-pixel copy only visits the part of the
layer that lands in the output. Denies the panic lints in the crate.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
nonAffineTransform and the warp descriptor (named styles with bend / distortion, custom
envelope quilt meshes via ObAr meshPoints) are baked as placed over the placed bounds
(SourceLayer::placed), at up to 4x resolution.
Co-Authored-By: Claude Opus 5.5 <[email protected]>