What's new
Size-constrained merge (MergeWithOptions)
Control the output size of merged PDFs with three oversize behaviors:
OversizeFail— merge normally, return*OversizeErrorif output exceeds limitOversizeTruncate— include as many pages as fit within the limitOversizeShrink— two-pass optimization: lossless first (stream dedup + metadata stripping), then JPEG recompression at ratio-derived quality to hit the target
res, err := m.MergeWithOptions(pdf.MergeOptions{
MaxSize: 20 * 1024 * 1024, // 20 MB
OversizeBehavior: pdf.OversizeShrink,
})Optimizations applied automatically
- Stream deduplication — SHA-256 content hashing across all sources; identical fonts, logos, and images are written once
- Metadata stripping — removes XMP metadata, structure trees, thumbnails, output intents
- JPEG recompression — decodes and re-encodes DCTDecode images at a quality derived from
maxSize / actualSize; skips images where recompression would produce a larger result or the source is < 4KB
Real-world results (63 PDFs, 94 pages)
| Mode | Pages | Size | Savings |
|---|---|---|---|
| Raw merge | 94 | 33.34 MB | — |
| Lossless (dedup + strip) | 94 | 21.76 MB | 34.8% |
| Shrink → 20 MB | 94/94 | 17.88 MB | 46.4% |
| Truncate → 20 MB | 85/94 | 19.92 MB | — |
Other changes
WritergainsLen(), checkpoint/restore for truncation rollbackMerger.Addcaches the*Readerto avoid double-parsing- Extracted
buildMergedPDFandfilterNameshelpers estimateFinishedSizemoved to Writer method- 10 new tests covering all behaviors and edge cases