Rust
PDF parsing and rendering in pure Rust.
pdfboss is a workspace of focused crates sharing one version: a clean-room parser built from ISO 32000 with readers for forms, bookmarks, page labels and attachments, layout analysis to text and Markdown, an anti-aliased rasterizer, in-tree JPEG 2000, JBIG2, CCITT and ICC codecs, async range-fetching I/O, and a deterministic writer that also merges, splits, rotates, watermarks and encrypts existing documents. Safe Rust, no C dependencies, no bindings to another engine.
Install
Add only what you use.
pdfboss-core alone parses; the others build on it. Optional features stay off by default in the library crates: substitute-fonts on pdfboss-render bundles replacement faces for PDFs that do not embed theirs, predefined-cmaps on pdfboss-core compiles in the CJK CMap set, and http on pdfboss-aio enables remote documents over HTTP range requests.
$ cargo add pdfboss-core pdfboss-output pdfboss-render
# optional: pdfboss-text pdfboss-write pdfboss-markdown pdfboss-aio
$ cargo add pdfboss-aio --features httpQuickstart
Open, extract, rasterize.
render_page returns an RGBA Pixmap; save_png and encode_png turn it into a file or bytes. render_page_reporting returns the same pixels plus every dropped or approximated item. Page indexes are 0-based.
use pdfboss_core::Document;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = Document::open("report.pdf")?;
println!("{} pages", doc.page_count());
let page = doc.page(0)?;
let text = pdfboss_output::extract_text(&doc, &page)?;
println!("{text}");
let pixmap = pdfboss_render::render_page(&doc, &page, 2.0)?;
pixmap.save_png("page.png")?;
Ok(())
}Structure and editing
Read forms and bookmarks, assemble documents.
Document reads the interactive form (form_fields, interactive_form), the bookmark tree (outline), page labels, named destinations, embedded files and viewer preferences; each has an async _with twin over any object source. pdfboss_write assembles through an Importer that renumbers each source object once: merge_documents, split_document, rewrite_document, encrypt_document and decrypt_document, while Update appends an incremental section for rotation, metadata and watermarks.
use pdfboss_core::{Document, Permissions};
use pdfboss_write::{encrypt_document, merge_documents, WriteOptions};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = Document::open("form.pdf")?;
for field in doc.form_fields() {
println!("{} = {:?}", field.name, field.value);
}
for item in doc.outline() {
println!("{} ({} children)", item.title, item.children.len());
}
for file in doc.embedded_files() {
std::fs::write(&file.name, doc.embedded_file_data(&file)?)?;
}
let appendix = Document::open("appendix.pdf")?;
let inputs = [(&doc, None), (&appendix, Some(&[0usize, 1][..]))];
let merged = merge_documents(&inputs, WriteOptions::default())?;
let permissions = Permissions { modify: false, ..Permissions::all() };
let locked = encrypt_document(
&Document::load(merged)?,
"s3cret",
"",
permissions,
WriteOptions::default(),
)?;
std::fs::write("locked.pdf", locked)?;
Ok(())
}The workspace
Thirteen crates on crates.io, one implementation.
No borrowed decoders and no C. Each crate’s API reference lives on docs.rs; the Rust reference chapter says where to start for reading, extracting, rasterizing, creating, editing, composing Markdown, async sources and element iteration.
pdfboss-core
The clean-room parser: objects, filters, cross-references, forms, outline, page labels, attachments.
pdfboss-text
Fonts, encodings and text extraction.
pdfboss-output
Layout analysis to plain text and Markdown.
pdfboss-render
The anti-aliased rasterizer: pages and annotations to PNG, PPM, BMP or JPEG.
pdfboss-write
PDF creation and editing: canvas, elements, the Importer, incremental updates, AES-256.
pdfboss-markdown
CommonMark+GFM composed into PDFs.
pdfboss-style
CSS-subset themes for composition.
pdfboss-aio
Async, range-fetching I/O over files and HTTP.
pdfboss-jpx
JPEG 2000 decoding, ITU-T T.800.
pdfboss-icc
ICC color profiles.
pdfboss-encoding
Font encoding tables and glyph names.
pdfboss-cli
The command line.
pdfboss-tui
The terminal explorer.
pdfboss-py
PyO3 bindings, shipped as the pdfboss wheel.
Design
What the crates promise.
- Lenient reading: broken cross-reference tables are reconstructed, wrong stream lengths tolerated, garbage operators skipped, and every dropped or approximated item is reported.
- Lazy page trees: opening a document reads its declared page count instead of parsing every page dictionary up front.
- Deterministic output from pdfboss-write: the same composition always serializes to the same bytes.
- Clean-room codecs implemented from their specifications: ITU-T T.800 for JPEG 2000, T.88 for JBIG2, T.4 and T.6 for CCITT, ICC.1:2010 for color.
- A conformance ledger in Lean: every clause of ISO 32000-1 carries a status, and CI proves each claim against citations in the source and the tests.