Files
pdfcraft/crates/create
dd065b39bb M4, #569: Combine files takes images and text files (#1032)
* M10: refuse a PNG whose header claims more than 2 GiB of pixels before allocating

The png crate's limits don't cover the caller's frame buffer, which png_image sized from the
header alone: a few-KB PNG claiming 60000x60000 RGBA made Create allocate and fill 14.4 GB.
Apply the 2 GiB ceiling TIFF pages already have. Reached from Create, Insert pages and (with
#569) Combine files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* M4, #569: Combine files takes images and text files

PNG, JPEG, TIFF, GIF, BMP, JPEG 2000 and .txt files become PDFs as they join the Combine files
list (Add files…, drops, folder scans), so each is an ordinary row or card with its pages,
thumbnails and page range. Session::as_pdf does the conversion; PDFs pass through unread
(Combine reads them itself, with their passwords), as does a file named .pdf without a header,
which the reader may still open. doc_combine accepts the same file types, and a converted
file's bookmark drops its extension.

A file that can't be read (a damaged image or PDF, a type that can't be converted) no longer
is refused at the door: it joins the list with why in its Warnings (a red card in the grid).
Combine then asks "Leave out files that can't be read?", naming them; Combine the rest goes on
without them, Cancel changes nothing. Password-protected files still block Combine until
unlocked.

The picker offers "PDF, images and text", and the empty state, folder tooltips and folder
notices say what is accepted; translated in every full catalog (catalog hashes updated).

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>
2026-10-11 12:04:10 -04:00
..

pdfcraft-create

Layer L4. Create a PDF (Acrobat's Create a PDF tool), execution plan M10.2:

  • blank(width, height, pages): an empty document;
  • from_images(&[(name, bytes)]): one page per image, sized from the image's resolution (PNG pHYs, JPEG JFIF density; 72 dpi when absent). JPEG data is embedded as is (/DCTDecode, grey, RGB or Adobe-inverted CMYK); PNG is decoded and stored with Flate, with transparency as a soft mask. An ICC profile in the file (JPEG APP2 ICC_PROFILE, PNG iCCP) that matches the image's colour space is kept as an /ICCBased colour space with the device space as /Alternate; images with the same profile share one profile object. JPEG metadata scanning skips marker fill bytes and reads application segments after the frame header, stopping at the first scan or end marker. Broken or mismatched ICC profiles still fall back to the device colour space;
  • from_images_with_resolution(images, ImageResolution::Dpi(dpi)): override the page resolution (1–1200 dpi), without resampling or recompressing image pixels. Use 72 dpi for one point per pixel, or ImageResolution::Embedded for the same behavior as from_images. The largest page side is still capped at 14,400 points;
  • from_text(text, …): plain text set in Helvetica, wrapped and paginated.

Every function returns a pdfcraft_cos::Document; the caller writes it.