PD4ML PDF COS
PD4ML PDF COS is a Java API for working with an existing PDF at the level of its objects: dictionaries, arrays, streams, names and the references between them (the COS, Carousel Object Structure). It parses a PDF into an object model you can navigate and query, and writes changes back as an incremental update that leaves the original bytes untouched. Use it to inspect a PDF's structure, read values the higher-level tools do not expose, or make targeted edits. The package is com.pd4ml.pdf.cos; the PD4ML Merge, Optimizer, Signing and XFDF tools are built on it.
Available from PD4ML v4.1.1. Part of pd4ml.jar, which also contains the coscli command-line tool.
What you can do with it
- Parse a PDF into a
COSDocumentwithCOSParser.load(...)and reach the trailer, the catalog and every indirect object. - Query the object graph with COS paths, a filesystem-like syntax such as
/Root/Pages/Kids[0]/MediaBox, throughCOSPathEvaluator.evaluate(returnsCOSNull.NULLon a miss) orevaluateStrict(throwsCOSPathExceptionnaming the failed step). - Walk the page tree by page index with
PageTree.findPage(catalog, index). - Decode streams:
COSStream.getDecodedBytes()applies the/Filterchain;isFullyDecodable()tells you in advance whether it reaches the end. - Read encrypted PDFs: given the right password, strings and streams are decrypted while the document is parsed.
- Edit an existing PDF as an incremental update with
IncrementalUpdateWriter: change, add or remove a key or array element of an indirect object, add new objects, and append them to the original file. - Build a PDF from scratch from the object model and serialize it with
COSDocumentWriter. - Do all of this from the command line with
coscli:inspect,list,pages,dump,setanddelete.
Quick start
Read a value with a COS path, then rotate the first page and save the change as an incremental update:
byte[] pdfBytes = Files.readAllBytes(Paths.get("report.pdf"));
COSDocument document = COSParser.load(pdfBytes);
// Read: number of pages
COSBase count = COSPathEvaluator.evaluate(document, "/Root/Pages/Count");
System.out.println("Pages: " + count);
// Edit: the target must be an indirect object (it has its own object number)
COSBase page = COSPathEvaluator.evaluateStrict(document, "/Root/Pages/Kids[0]");
((COSDictionary) page).setItem("Rotate", COSInteger.get(90));
IncrementalUpdateWriter update = new IncrementalUpdateWriter(pdfBytes, document);
update.writeObject(page);
Files.write(Paths.get("out.pdf"), update.finish());
The same from the command line:
java -cp pd4ml.jar com.pd4ml.pdf.cos.cli.CosCli inspect report.pdf "/Root/Pages/Count"
java -cp pd4ml.jar com.pd4ml.pdf.cos.cli.CosCli set report.pdf out.pdf "/Root/Pages/Kids[0]" Rotate 90 --type=int
set and delete refuse encrypted input: the writer does not encrypt what it appends.
When to use it
Use PD4ML PDF COS when you need direct access to a PDF's objects: to inspect or validate its structure, extract a value or a stream, or change a specific key. For common whole-document tasks, the tools built on it are a better fit:
| Task | Tool |
|---|---|
| Combine page ranges from several PDFs into one | PD4ML PDF Merge |
| Remove unreachable objects and collapse incremental-update history | PD4ML PDF Optimizer |
| Sign, timestamp, certify, add PAdES-LT validation data | PD4ML PDF Signing |
| Export or import annotations and form field values as XFDF | PD4ML PDF XFDF |
In this section
- PD4ML COS API - Programmer's Manual: the object model, parsing, COS-path syntax, writing and the edit recipe, page tree, filters, encrypted input and known limits.
- Examples: eight runnable example classes from the
pd4ml-examplesrepository, from parsing to building a document from scratch. - coscli - Command-Line Reference: every
cosclicommand and flag, exit codes and troubleshooting. - Javadoc: reference for
com.pd4ml.pdf.cosand its subpackages.
