Documentation page: PD4ML PDF COS. This page is also available as Markdown at pd4ml-pdf-cos.md.

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 COSDocument with COSParser.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, through COSPathEvaluator.evaluate (returns COSNull.NULL on a miss) or evaluateStrict (throws COSPathException naming the failed step).
  • Walk the page tree by page index with PageTree.findPage(catalog, index).
  • Decode streams: COSStream.getDecodedBytes() applies the /Filter chain; 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, set and delete.

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-examples repository, from parsing to building a document from scratch.
  • coscli - Command-Line Reference: every coscli command and flag, exit codes and troubleshooting.
  • Javadoc: reference for com.pd4ml.pdf.cos and its subpackages.