A Rust library for PDF document manipulation.
A Rust library for PDF document manipulation.
A useful reference for understanding the PDF file format and the eventual usage of this library is the PDF 1.7 Reference Document. The PDF 2.0 specification is available here.
rustc --versionrustup update| Feature | Default | What it adds |
|---|---|---|
chrono-clock |
✅ | chrono plus its clock feature: conversions to and from DateTime<Local>, the reading machine's own zone. Brings iana-time-zone and its per-platform chain. |
rayon |
✅ | Parallel object-stream and cross-reference parsing. |
chrono |
Conversions to and from DateTime<FixedOffset> and DateTime<Utc>, which is all a PDF date can express. Costs chrono and num-traits, nothing else. |
|
jiff |
Conversions to and from jiff::Zoned and jiff::Timestamp. Resolves named zones, so it needs a timezone database — bundled into the binary on Windows and on any wasm target. |
|
time |
Conversions to and from time::OffsetDateTime and time::PrimitiveDateTime. |
|
serde |
Serialize/Deserialize for the object model. |
|
async |
Tokio-based asynchronous document loading. | |
embed_image |
Embedding raster images, via the image crate. |
|
font_embedding |
Embedding TrueType fonts, via skrifa. |
|
wasm_js |
Selects getrandom's wasm_js backend, needed for encryption on wasm. |
The date backends are alternatives, not layers: each supplies conversions for the same [DateTime] value, so enabling more than one only adds dependencies. Enabling none is supported too — Object::as_datetime needs no backend, and DateTime::as_str returns the raw date for a caller that would rather parse it itself.
A PDF date states a fixed offset from UT and never a named zone (ISO 32000-1, 7.9.4), so chrono without clock is enough to read one faithfully. chrono-clock is the default only because it is what earlier versions gave you.
…
…
…
…
Object streams allow multiple non-stream objects to be compressed together, significantly reducing file size.
…
…
For more examples, see:
examples/object_streams.rs - Creating PDFs with object streamsexamples/compress_existing_pdf.rs - Compress existing PDFsexamples/analyze_object_streams.rs - Analyze object stream usagelopdf now includes full support for creating and reading PDF object streams (PDF 1.5+ feature). Object streams provide significant file size reduction by compressing multiple non-stream objects together.
…
Not all objects can be compressed into object streams. The following objects are excluded:
All other objects, including structural objects (Catalog, Pages, Page) and trailer-referenced objects (except encryption), can be compressed.
When using save_modern() or enabling use_xref_streams(true), lopdf creates binary cross-reference streams instead of traditional ASCII cross-reference tables. This provides additional space savings and is part of the PDF 1.5+ specification.
The SaveOptions builder provides fine-grained control over PDF compression:
use lopdf::SaveOptions;
let options = SaveOptions::builder()
.use_object_streams(true) // Enable object streams (default: false)
.use_xref_streams(true) // Enable xref streams (default: false)
.max_objects_per_stream(200) // Max objects per stream (default: 100)
.compression_level(9) // zlib level 0-9 (default: 6)
.build();
lopdf now includes enhanced support for reading encrypted PDF documents. The library can automatically decrypt PDFs that use empty passwords, which is common for many protected documents.
When loading an encrypted PDF, lopdf:
Encrypt entry in the trailer…
authenticate_password method)For more examples, see:
examples/test_decryption.rs - Testing decryption functionalityexamples/verify_decryption.rs - Comprehensive decryption verificationtests/decryption.rs - Decryption test suiteWhy does the library keep everything in memory as high-level objects until finally serializing the entire document?
Normally, a PDF document won't be very large, ranging from tens of KB to hundreds of MB. Memory size is not a bottle neck for today's computer. By keeping the whole document in memory, the stream length can be pre-calculated, no need to use a reference object for the Length entry. The resulting PDF file is smaller for distribution and faster for PDF consumers to process.
Producing is a one-time effort, while consuming is many more.
How do object streams affect memory usage?
Object streams actually help reduce memory usage during document creation. When enabled, multiple small objects are grouped and compressed together, reducing the overall memory footprint. The compression happens during the save operation, so the in-memory representation remains the same until save_with_options() or save_modern() is called.
What PDF versions support object streams?
Object streams were introduced in PDF 1.5. When using save_modern() or object streams, lopdf automatically ensures the document version is at least 1.5. For maximum compatibility with older PDF readers, you can use the traditional save() method.
Can I analyze existing PDFs to see if they use object streams?
Yes! lopdf can read and parse object streams from existing PDFs. Use the Document::load() method to open any PDF, and lopdf will automatically handle object streams if present. See the examples directory for analysis tools.
lopdf is available under the MIT license, with the exception of the Montserrat font.
No open issues yet, or sync has not completed.