How-to guides/Watermarks & Stamps

Add a text watermark to a PDF in Rust

Stamp each page with a diagonal text watermark. Control font, size, colour, opacity, rotation, and position.

rust
use pdfluent::{PdfDocument, WatermarkOptions};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open("report.pdf")?;
    doc.add_watermark("DRAFT", WatermarkOptions::centered().opacity(0.3))?;
    doc.save("watermarked.pdf")?;
    Ok(())
}

Step by step

1

Open the PDF

Open the document with a mutable binding.

rust
use pdfluent::PdfDocument;

let mut doc = PdfDocument::open("contract.pdf")?;
2

Build a TextWatermark

Create a TextWatermark with the text you want to stamp. Use the builder methods to set style properties.

rust
use pdfluent::WatermarkOptions;

let opts = WatermarkOptions::centered()
    .font_size(72.0)
    .opacity(0.12)          // 12% opacity
    .rotated(45.0)          // degrees
    .color(0.6, 0.0, 0.0);  // dark red, sRGB
3

Set the position

WatermarkPosition::Center places the text at the page centre. Other options include TopLeft, TopRight, BottomLeft, BottomRight, and Custom(x, y).

rust
// Watermarks are centered by default; tune size, angle, and opacity
let opts = WatermarkOptions::centered()
    .font_size(64.0)
    .rotated(45.0)
    .opacity(0.15);
4

Apply to all pages or specific pages

add_text_watermark() stamps every page. Use add_text_watermark_on_pages() to target a subset.

rust
// Apply to all pages
doc.add_watermark("DRAFT", opts)?;
5

Save the result

Save the watermarked document to disk.

rust
doc.save("contract_draft.pdf")?;

Notes and tips

  • Opacity of 0.1 to 0.2 is typical for background watermarks. Higher values produce more prominent stamps.
  • The watermark is drawn as a content stream beneath the page text so it does not obscure the document content.
  • To place the watermark on top of the content instead, use watermark.layer(WatermarkLayer::Foreground).
  • PDFluent uses the Helvetica built-in font by default. Specify a custom font path with .font_path("path/to/font.ttf").

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