#pdf #editing

lopdf

A Rust library for PDF document manipulation

32 releases (21 breaking)

✓ Uses Rust 2018 edition

0.22.0 May 13, 2019
0.20.0 Mar 8, 2019
0.19.0 Oct 24, 2018
0.15.2 Jun 8, 2018
0.1.1 Dec 27, 2016

#40 in Text processing

Download history 41/week @ 2019-01-28 41/week @ 2019-02-04 30/week @ 2019-02-11 48/week @ 2019-02-18 73/week @ 2019-02-25 98/week @ 2019-03-04 66/week @ 2019-03-11 40/week @ 2019-03-18 244/week @ 2019-03-25 58/week @ 2019-04-01 77/week @ 2019-04-08 92/week @ 2019-04-15 79/week @ 2019-04-22 57/week @ 2019-04-29 83/week @ 2019-05-06

346 downloads per month
Used in 8 crates (6 directly)

MIT license

297KB
9K SLoC

lopdf

Crates.io Build Status Docs

A Rust library for PDF document manipulation.

Example Code

  • Create PDF document
#[macro_use]
extern crate lopdf;
use lopdf::{Document, Object, Stream};
use lopdf::content::{Content, Operation};

let mut doc = Document::with_version("1.5");
let pages_id = doc.new_object_id();
let font_id = doc.add_object(dictionary! {
	"Type" => "Font",
	"Subtype" => "Type1",
	"BaseFont" => "Courier",
});
let resources_id = doc.add_object(dictionary! {
	"Font" => dictionary! {
		"F1" => font_id,
	},
});
let content = Content {
	operations: vec![
		Operation::new("BT", vec![]),
		Operation::new("Tf", vec!["F1".into(), 48.into()]),
		Operation::new("Td", vec![100.into(), 600.into()]),
		Operation::new("Tj", vec![Object::string_literal("Hello World!")]),
		Operation::new("ET", vec![]),
	],
};
let content_id = doc.add_object(Stream::new(dictionary! {}, content.encode().unwrap()));
let page_id = doc.add_object(dictionary! {
	"Type" => "Page",
	"Parent" => pages_id,
	"Contents" => content_id,
});
let pages = dictionary! {
	"Type" => "Pages",
	"Kids" => vec![page_id.into()],
	"Count" => 1,
	"Resources" => resources_id,
	"MediaBox" => vec![0.into(), 0.into(), 595.into(), 842.into()],
};
doc.objects.insert(pages_id, Object::Dictionary(pages));
let catalog_id = doc.add_object(dictionary! {
	"Type" => "Catalog",
	"Pages" => pages_id,
});
doc.trailer.set("Root", catalog_id);
doc.compress();
doc.save("example.pdf").unwrap();
  • Modify PDF document
let mut doc = Document::load("example.pdf")?;
doc.version = "1.4".to_string();
doc.replace_text(1, "Hello World!", "Modified text!");
doc.save("modified.pdf")?;

FAQ

  • Why keeping everything in memory as high-level objects until finally serializing the entire document?

    Normally a PDF document won't be very large, ranging form tens of KB to hundreds of MB. Memory size is not a bottle neck for today's computer. By keep the whole document in memory, 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.

Dependencies

~6MB
~90K SLoC