Class PdfOptimizer
- java.lang.Object
-
- com.pd4ml.pdf.optimizer.PdfOptimizer
-
public final class PdfOptimizer extends java.lang.ObjectCleans a PDF down to exactly what's actually reachable, and collapses its cross-reference/trailer history into one fresh table -- built entirely on the pd4mlcom.pd4ml.pdf.cosobject model/parser (no PDFBox, no other PDF library), the same foundationcom.pd4ml.pdf.signandcom.pd4ml.pdf.mergeare built on.Two things accumulate in a PDF that has been edited via incremental update (e.g. by
com.pd4ml.pdf.signorCosCli'sset/delete, or by any other tool that patches a file this way rather than rewriting it from scratch):- Unreferenced objects -- an incremental update only adds
new object bodies and xref entries; when it drops a reference (e.g.
replacing a page dictionary that used to point at some content), the
object that's no longer pointed to anywhere still has a live "in use"
xref entry and its bytes are still sitting in the file.
COSParserhappily parses it into the document's object table right along with everything still actually reachable. - Trailer/xref history -- each incremental update appends its own
xref section and trailer, chained to the previous one via
/Prev.COSParseralready resolves that chain down to the current value of each object number (older, superseded bodies are simply never parsed in the first place), but the chain of old xref sections/trailers itself is still physically part of the file until something rewrites it away.
optimize(...)parses the input, then deep-clones only what's reachable by walking from the trailer's/Root(and/Info, which is otherwise unreferenced by design -- it's a trailer-only entry) into a freshCOSDocumentwith compact object numbering (seeCOSObjectImporter), and writes that out as a single, from-scratch xref table and trailer (seeCOSDocumentWriter) -- anything not reachable is simply never visited, and every old revision's xref/trailer is gone because the output isn't an incremental update at all.By default, that reachable set is then also deduplicated by content (see
ContentDeduplicator): two distinct objects with byte-identical content -- typically the same font, image, or color space embedded twice under two different object numbers -- are merged into one shared copy, every reference to the duplicate is redirected to the survivor, and a second reachability pass drops the now-unreferenced duplicate and renumbers everything compactly again. PassdeduplicateContent(false)to skip this (a large-document performance trade-off, since it hashes every reachable object's full content) and keep only the reachability cleanup.Encrypted input is supported (pass the password to the password-taking overload; the COS reader decrypts transparently while parsing). The output is not re-encrypted by default -- pass
PdfOptimizer.Options.encryptOutput(java.lang.String, java.lang.String)if the cleaned file should stay protected.Not optimized (out of scope): stream recompression -- an uncompressed or suboptimally-compressed content/image stream is copied through as-is; a size optimization orthogonal to both reachability cleanup and content dedup, not attempted here.
Thread-safety:
PdfOptimizerholds no state at all (every method isstatic); calloptimize(...)freely and concurrently from any number of threads. Each call builds its own localCOSDocument/COSObjectImporterand touches nothing shared across calls.Example
PdfOptimizeResult result = PdfOptimizer.optimize(pdfBytes); System.out.println("Removed " + result.getRemovedObjectCount() + " unreferenced object(s)"); Files.write(Paths.get("cleaned.pdf"), result.getOptimizedPdf()); - Unreferenced objects -- an incremental update only adds
new object bodies and xref entries; when it drops a reference (e.g.
replacing a page dictionary that used to point at some content), the
object that's no longer pointed to anywhere still has a live "in use"
xref entry and its bytes are still sitting in the file.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classPdfOptimizer.Options
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static PdfOptimizeResultoptimize(byte[] pdfBytes)static PdfOptimizeResultoptimize(byte[] pdfBytes, PdfOptimizer.Options options)static PdfOptimizeResultoptimize(byte[] pdfBytes, PdfOptimizer.Options options, java.io.OutputStream out)Convenience for writing straight to a destination rather than handlingPdfOptimizeResultyourself.static PdfOptimizeResultoptimize(java.io.File pdfFile)static PdfOptimizeResultoptimize(java.io.File pdfFile, PdfOptimizer.Options options)static PdfOptimizeResultoptimize(java.io.File inputFile, PdfOptimizer.Options options, java.io.File outputFile)static PdfOptimizeResultoptimize(java.io.InputStream in)static PdfOptimizeResultoptimize(java.io.InputStream in, PdfOptimizer.Options options)
-
-
-
Method Detail
-
optimize
public static PdfOptimizeResult optimize(byte[] pdfBytes) throws PdfOptimizeException
- Throws:
PdfOptimizeException
-
optimize
public static PdfOptimizeResult optimize(byte[] pdfBytes, PdfOptimizer.Options options) throws PdfOptimizeException
- Throws:
PdfOptimizeException
-
optimize
public static PdfOptimizeResult optimize(java.io.File pdfFile) throws PdfOptimizeException
- Throws:
PdfOptimizeException
-
optimize
public static PdfOptimizeResult optimize(java.io.File pdfFile, PdfOptimizer.Options options) throws PdfOptimizeException
- Throws:
PdfOptimizeException
-
optimize
public static PdfOptimizeResult optimize(java.io.InputStream in) throws PdfOptimizeException
- Throws:
PdfOptimizeException
-
optimize
public static PdfOptimizeResult optimize(java.io.InputStream in, PdfOptimizer.Options options) throws PdfOptimizeException
- Throws:
PdfOptimizeException
-
optimize
public static PdfOptimizeResult optimize(byte[] pdfBytes, PdfOptimizer.Options options, java.io.OutputStream out) throws PdfOptimizeException
Convenience for writing straight to a destination rather than handlingPdfOptimizeResultyourself.- Throws:
PdfOptimizeException
-
optimize
public static PdfOptimizeResult optimize(java.io.File inputFile, PdfOptimizer.Options options, java.io.File outputFile) throws PdfOptimizeException
- Throws:
PdfOptimizeException
-
-