This guide shows developers how to perform core PDF operations with PDFluent. It covers rendering PDFs to images, editing documents, and processing annotations.
Convert PDF pages to PNG, JPEG, or WebP with sub-pixel accuracy. Runs server-side, in Lambda, or via WASM.
use pdfluent::{PdfDocument, ImageFormat};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = PdfDocument::open("document.pdf")?;
let png = doc.render_page(0, 150, ImageFormat::Png)?;
std::fs::write("page-1.png", png)?;
Ok(())
}Convert first pages or any pages to JPEG/PNG thumbnails. Batch process document libraries without a display server.
use pdfluent::{PdfDocument, ImageFormat};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = PdfDocument::open("document.pdf")?;
for i in 0..doc.page_count() {
let png = doc.render_page(i, 72, ImageFormat::Png)?;
std::fs::write(format!("thumb-{}.png", i + 1), png)?;
}
Ok(())
}PDFluent compiles to WASM. Process PDFs client-side without uploading files to a server.
// Install: npm install @pdfluent/sdk-wasm
import init, { PdfluentSdk } from '@pdfluent/sdk-wasm';
async function renderFirstPage(file) {
await init(); // loads pdfluent_bg.wasm (~6 MB uncompressed, ~2 MB Brotli-compressed; cached after first load)
const sdk = new PdfluentSdk();
const bytes = new Uint8Array(await file.arrayBuffer());
const doc = sdk.openBytes(bytes);
const image = doc.renderPage(0, {
format: 'png',
dpi: 96,
});
const blob = new Blob([image], { type: 'image/png' });
document.getElementById('preview').src = URL.createObjectURL(blob);
doc.free();
}Parse, create, and modify comments, highlights, stamps, and ink annotations. Compliant with PDF spec section 12.5.
use pdfluent::{Sdk, Annotation, HighlightAnnotation, Rect, Color};
fn main() -> pdfluent::Result<()> {
let sdk = Sdk::new()?;
let mut doc = sdk.open("input.pdf")?;
let annot = HighlightAnnotation::builder()
.page(0)
.rect(Rect::new(72.0, 680.0, 300.0, 695.0))
.color(Color::rgb(1.0, 0.93, 0.0))
.author("Alice")
.contents("Key clause")
.build();
doc.page_mut(0)?.add_annotation(annot)?;
doc.save("annotated.pdf")?;
Ok(())
}Modify text, add elements, fill forms, and update metadata — without re-generating the document from scratch. Pure Rust, no Adobe SDK, no Java.
use pdfluent::{PdfDocument, Font, Position, Metadata};
fn stamp_and_update(input: &[u8]) -> Vec<u8> {
let mut doc = PdfDocument::from_bytes(input)?;
// Add text to the first page
let page = doc.page_mut(0)?;
page.add_text(
"APPROVED — Finance Team",
Font::helvetica_bold(12),
Position::new(50.0, 50.0),
);
// Update document metadata
let mut meta = doc.metadata();
meta.set_author("Finance Team");
meta.set_keywords("approved, processed, 2026");
meta.set_custom("x-workflow-status", "approved");
doc.set_metadata(meta);
doc.save_bytes()
}Apply text watermarks, image overlays, and stamps to single pages or entire documents. Batch watermark with per-document variable data.
use pdfluent::{PdfDocument, WatermarkOptions};
fn main() -> pdfluent::Result<()> {
let mut doc = PdfDocument::open("document.pdf")?;
let opts = WatermarkOptions::centered()
.font_size(64.0)
.rotated(45.0)
.opacity(0.15)
.color(0.6, 0.0, 0.0);
doc.add_watermark("CONFIDENTIAL", opts)?;
doc.save("watermarked.pdf")?;
Ok(())
}PDF text extraction with 97.5% pass rate. Preserve layout, reading order, and font metadata.
use pdfluent::PdfDocument;
fn main() -> pdfluent::Result<()> {
let doc = PdfDocument::open("document.pdf")?;
// Plain text
println!("{}", doc.extract_text()?);
// Positioned text blocks: text + bounding box + page
for block in doc.text_with_layout()? {
println!("p{} {:?} {}", block.page, block.bbox, block.text);
}
Ok(())
}