PDF merging
View SourceNativeElixirPdfUtilities.Merge combines a non-empty list of PDF binaries and
returns a new PDF.
alias NativeElixirPdfUtilities.Merge
with {:ok, first} <- File.read("first.pdf"),
{:ok, second} <- File.read("second.pdf"),
{:ok, merged} <- Merge.merge([first, second]),
:ok <- File.write("merged.pdf", merged) do
:ok
endInput order determines page order. merge/1 accepts PDF binaries rather than
paths so callers control file access, storage, and error handling.
Supported inputs
Merging uses the shared PDF reader and therefore supports:
- classic cross-reference tables
- cross-reference streams and object streams
- incremental revisions and hybrid-reference files
- active object generations and free entries
- inherited page
Resources,MediaBox,CropBox, andRotatevalues, including indirectly referenced page rectangles - the stream filters and resource limits described in the PDF reader guide
Malformed, encrypted, unsupported, or resource-intensive inputs fail through the shared diagnostic contract. The merger does not decrypt PDFs.
Output behavior
The merger emits a PDF 1.7 document with a new cross-reference table,
trailer, catalog, and flat page tree. Active input objects receive new object
numbers, their indirect references are rewritten, and stream bytes and filter
declarations are preserved. Effective inherited page resources, media and crop
boxes, and rotation values are written onto the merged pages where required.
Existing page-level entries such as BleedBox, TrimBox, ArtBox, and
UserUnit remain on copied page dictionaries.
If required page geometry is missing or malformed, the merger returns a
diagnostic that identifies the problem. It does not invent a page size.
The merger combines page content and appends each input's top-level outline items in input order. Outline destinations are remapped to the corresponding output pages. It rebuilds the top-level catalog, so it does not carry metadata, viewer preferences, portfolios, or AcroForm configuration into the output.
Internal links are remapped to the corresponding pages from their own input, including names resolved through legacy destination dictionaries or name trees. Resolvable named links become explicit destinations in the merged PDF; unresolved named links are omitted. External URI links remain.
Outline item and aggregate title-byte limits apply to the combined output, even when each input outline individually fits within its limits. Assembly also reserves object capacity for the generated outline tree. See PDF outlines and bookmarks for preservation and limit rules.
Errors
An empty input list and invalid PDF input return diagnostics:
case Merge.merge(pdf_binaries) do
{:ok, merged_pdf} ->
merged_pdf
{:error, {_reason, diagnostic}} ->
Logger.warning(diagnostic.message)
endSee Diagnostics for the common error shape and the fields available for logging and support.