Add an image to a PDF page in Rust

Embed JPEG, PNG, or WebP images at a specific position and size on any PDF page.

rust
use pdfluent::PdfDocument;
use pdfluent::parity::{ImageInsert, InsertImageFormat};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut doc = PdfDocument::open("report.pdf")?;
    let bytes = std::fs::read("logo.png")?;
    doc.insert_image(ImageInsert::new(bytes, InsertImageFormat::Png, 0, 50.0, 700.0, 120.0, 40.0))?;
    doc.save("with-logo.pdf")?;
    Ok(())
}

Step by step

1

Add PDFluent to Cargo.toml

Image embedding is in the base crate. The image feature adds format conversion helpers.

rust
# Cargo.toml
[dependencies]
pdfluent = "1.0.0-beta.8"
2

Load an image from a file or from bytes

Image::from_file() reads JPEG, PNG, or WebP. Image::from_bytes() accepts the raw image bytes if you are reading from memory or a network source.

rust
// Load the image bytes (PNG or JPEG)
let bytes = std::fs::read("logo.png")?;
println!("{} bytes loaded", bytes.len());
3

Get a mutable reference to the target page

page_mut(n) returns a mutable handle to page n. PDF page indices are zero-based.

rust
use pdfluent::parity::{ImageInsert, InsertImageFormat};

// Place on the first page (index 0). Coordinates are points from bottom-left.
let insert = ImageInsert::new(bytes.clone(), InsertImageFormat::Png, 0, 50.0, 700.0, 150.0, 60.0);
4

Position and embed the image

PDF uses a coordinate system where (0, 0) is the bottom-left corner. Measurements are in points (1 pt = 1/72 inch). A4 is 595 x 842 pt, US Letter is 612 x 792 pt.

rust
doc.insert_image(insert)?;
5

Preserve aspect ratio when sizing the image

Use ImagePosition::fit_width() to scale the image to a given width while preserving the aspect ratio.

rust
use pdfluent::parity::{ImageInsert, InsertImageFormat};

// Insert with reduced opacity (e.g. a watermark-style logo)
doc.insert_image(
    ImageInsert::new(bytes, InsertImageFormat::Png, 0, 50.0, 700.0, 150.0, 60.0)
        .with_opacity(0.85),
)?;
doc.save("document-with-logo.pdf")?;

Notes and tips

  • PDF coordinates have the origin at the bottom-left. If your image appears at the wrong position, check whether you are counting from the top or the bottom.
  • JPEG images are embedded as-is in the PDF stream (DCTDecode), with no quality loss. PNG images are embedded as FlateDecode streams.
  • Large images increase file size proportionally. Resize before embedding if the display size is much smaller than the source resolution.
  • Transparency in PNG images (alpha channel) is supported via a soft mask XObject. All compliant PDF readers render the transparency correctly.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions