All formats

pdfium-render

LanguageRust
LicenseMIT or Apache-2.0 (PDFium itself is BSD-3-Clause)
Repositorygithub.com/ajrcarey/pdfium-render
Documentationdocs.rs/pdfium-render, examples
Depends ona PDFium shared library at run time (or static linking); the image crate (enabled by the default image_latest feature) for as_image()
Read / writeyes / 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#

Shell
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#

Rust
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#

Rust
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#

Rust
let metadata = document.metadata();
if let Some(title) = metadata.get(PdfDocumentMetadataTagType::Title) {
    println!("Title: {}", title.value());
}

How to merge and split PDFs#

Rust
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#

Rust
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#

Rust
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#

Rust
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#