pdfium-render
| Language | Rust |
|---|---|
| License | MIT or Apache-2.0 (PDFium itself is BSD-3-Clause) |
| Repository | github.com/ajrcarey/pdfium-render |
| Documentation | docs.rs/pdfium-render, examples |
| Depends on | a PDFium shared library at run time (or static linking); the image crate (enabled by the default image_latest feature) for as_image() |
| Read / write | yes / yes: render, text, images, forms, annotations, attachments, signatures (read), merge, create pages and page objects |
pdfium-render gives Rust an idiomatic API over PDFium, the PDF engine in Chrome: Pdfium loads documents, PdfDocument::pages() iterates pages, page.render_with_config() produces bitmaps (converted to image::DynamicImage), page.text() extracts text with character positions, document.form() and page annotations expose form fields, and you can create pages and add text, path and image objects. It also compiles to WebAssembly together with a WASM build of PDFium.
PDFium isn’t included. Download a prebuilt library from bblanchon/pdfium-binaries and ship it next to your executable, or bind to a system library. PDFium isn’t thread-safe; the thread_safe feature (on by default) serializes calls with a mutex.
Installation#
cargo add pdfium-render
Put pdfium.dll (Windows), libpdfium.so (Linux) or libpdfium.dylib (macOS) next to the executable, or in a system library path.
Basic usage: render pages to images#
use pdfium_render::prelude::*;
fn main() -> Result<(), PdfiumError> {
// binds to a PDFium library next to the executable, or the system library
let pdfium = Pdfium::default();
let document = pdfium.load_pdf_from_file("in.pdf", None)?; // None: no password
println!("{} pages", document.pages().len());
let config = PdfRenderConfig::new().set_target_width(1200);
for (index, page) in document.pages().iter().enumerate() {
page.render_with_config(&config)?
.as_image()? // image::DynamicImage
.into_rgb8()
.save(format!("page-{}.png", index + 1))
.map_err(|_| PdfiumError::ImageError)?;
}
Ok(())
}
To load the library from a specific folder: Pdfium::new(Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./lib/"))?).
How to extract text from a PDF#
let document = pdfium.load_pdf_from_file("in.pdf", None)?;
for (index, page) in document.pages().iter().enumerate() {
println!("--- page {} ---\n{}", index + 1, page.text()?.all());
}
page.text()?.chars() iterates characters with their bounds and font info.
How to read PDF metadata#
let metadata = document.metadata();
if let Some(title) = metadata.get(PdfDocumentMetadataTagType::Title) {
println!("Title: {}", title.value());
}
How to merge and split PDFs#
let mut merged = pdfium.create_new_pdf()?;
for path in ["a.pdf", "b.pdf"] {
let src = pdfium.load_pdf_from_file(path, None)?;
merged.pages_mut().append(&src)?;
}
merged.save_to_file("merged.pdf")?;
let src = pdfium.load_pdf_from_file("merged.pdf", None)?;
for i in 0..src.pages().len() {
let mut single = pdfium.create_new_pdf()?;
single.pages_mut().copy_page_from_document(&src, i, 0)?; // source index, destination index
single.save_to_file(&format!("page-{}.pdf", i + 1))?;
}
copy_pages_from_document(&src, "1-3,5", index) copies a page range string (1-based).
How to rotate pages#
let document = pdfium.load_pdf_from_file("in.pdf", None)?;
for mut page in document.pages().iter() {
page.set_rotation(PdfPageRenderRotation::Degrees90);
}
document.save_to_file("rotated.pdf")?;
How to fill a PDF form#
let document = pdfium.load_pdf_from_file("form.pdf", None)?;
for page in document.pages().iter() {
for mut annotation in page.annotations().iter() {
if let Some(field) = annotation.as_form_field_mut() {
if let Some(text) = field.as_text_field_mut() {
if text.name().as_deref() == Some("name") {
text.set_value("Jane Doe")?;
}
}
}
}
}
document.save_to_file("filled.pdf")?;
How to create a PDF with text#
let mut document = pdfium.create_new_pdf()?;
let mut page = document.pages_mut().create_page_at_start(PdfPagePaperSize::a4())?;
let font = document.fonts_mut().helvetica();
let mut text = PdfPageTextObject::new(&document, "Hello, PDF!", font, PdfPoints::new(24.0))?;
text.translate(PdfPoints::new(72.0), PdfPoints::new(770.0))?; // from the bottom-left corner
page.objects_mut().add_text_object(text)?;
document.save_to_file("hello.pdf")?;
Tips#
- Open encrypted files with
pdfium.load_pdf_from_file("secret.pdf", Some("password")); PDFium can’t encrypt when saving. - Enable the
staticfeature and setPDFIUM_STATIC_LIB_PATHto link PDFium into your binary instead of loading it at run time. load_pdf_from_byte_sliceandload_pdf_from_readeropen documents from memory.