From 3906dcdff535c8e10b9ab9888c1849cc6ab52ffd Mon Sep 17 00:00:00 2001 From: DWAA1660 Date: Sat, 10 Oct 2026 14:31:41 -0600 Subject: [PATCH] Exported images keep their transparency, JPEG cut-outs included (#645) (#763) * M10: exported images keep their transparency, JPEG cut-outs included (#645) Export all images and Save image as wrote a JPEG with a soft mask as the bare JPEG and dropped soft masks of another size, JPEG-compressed soft masks, stencil /Mask images and colour-key /Mask arrays, so cut-out images came out on a solid white or black background. - An image with transparency (/SMask, stencil /Mask, colour-key /Mask) is written as a PNG with it as alpha, JPEG images included (decoded with the image crate's JPEG decoder, already in the tree). JPEGs without transparency are still written byte for byte. - Soft and stencil masks of another size are scaled to the image's size; /Decode inversion is honoured and /Matte pre-blending is undone. - Image sizes are checked (positive, at most 100 Mpx) before use, so a negative /Width no longer overflows in Save image as. - Regression tests: JPEG + soft mask, scaled soft mask, stencil mask, colour key, matte, and damaged masks/sizes (all fail or panic on main). Fixes #645 Co-Authored-By: Claude Opus 5.5 * M10: use as_chunks for colour-key pairs (clippy 1.99 chunks_exact_to_as_chunks) (#645) Rust 1.99's clippy denies chunks_exact with a constant size, which failed the Clippy step on all CI targets. as_chunks::<2> also drops the indexing. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: DWAA1660 Co-authored-by: Claude Opus 5.5 Co-authored-by: Brandon Thomas --- ROADMAP.md | 1 + crates/create/Cargo.toml | 4 +- crates/create/src/extract.rs | 215 ++++++++++++++++++++++++++++++----- crates/create/src/tests.rs | 154 +++++++++++++++++++++++++ parity/acrobat-features.toml | 4 +- 5 files changed, 344 insertions(+), 34 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 470fe333..2c40b42d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -216,6 +216,7 @@ M0 → M1 → M2 → M3 → M4 must happen in order. After M4, M5–M12 can run ## Log Newest first: the date, what moved, and the new overall estimate. +- **2026-10-10 (M10, #645):** Export all images and Save image as keep transparency. A JPEG with a soft mask (the usual cut-out photo) was written as the bare JPEG, and soft masks of another size than the image, JPEG-compressed soft masks, stencil `/Mask` images and colour-key `/Mask` arrays were dropped, so cut-outs came out on solid white or black. These images are now PNG with the mask as alpha (soft masks scaled to the image, `/Matte` un-blended); JPEGs without transparency are still written byte for byte. A negative image size no longer overflows in Save image as. JPX/JBIG2/CCITT masks are still left out. Overall estimate unchanged (about 30–35%). - **2026-10-10 (M12, XFA rows and areas):** Dynamic XFA forms lay out a repeating subform inside a top-to-bottom container in positioned content (a table in an area) with all its instances, drawn and measured, instead of one; and areas no longer appear in data paths (`pdfcraft_xfa::data_path`), since they are not data scopes. Before, a form whose fields sit in an area read none of the values Adobe's viewers saved, wrote what was filled here under a new element named after the area, which Adobe's viewers would most likely not read, and a FormCalc total looping over the table's rows failed on the rows that were missing. Layout, the script tree, reading and writing the data and the engine's value and row operations share the one path rule. Synthetic tests cover the layout, the path rule and the whole round trip (rows, Adobe-written values, a FormCalc total over all rows, the written data, reopening). Still open for such forms: XFA script objects (`