Expand description
§zenpdf

Pure Rust PDF page renderer built on hayro. Renders PDF pages to PixelBuffer<Rgba<u8>> (straight-alpha sRGB RGBA8).
#![forbid(unsafe_code)]
§Quick start
use zenpdf::{render_page, RenderBounds};
let pdf_data = std::fs::read("document.pdf").unwrap();
// Render page 0 at 150 DPI
let page = render_page(&pdf_data, 0, &RenderBounds::Dpi(150.0)).unwrap();
println!("{}x{}", page.buffer.width(), page.buffer.height());
// Fit within 1920px wide
let page = render_page(&pdf_data, 0, &RenderBounds::FitWidth(1920)).unwrap();§Render bounds
Control output pixel dimensions with RenderBounds:
| Variant | Description |
|---|---|
Scale(f32) | Multiplier on native 72 DPI dimensions. 2.0 = 144 DPI. |
Dpi(f32) | Render at a specific DPI. 72.0 is native, 300.0 for print. |
FitWidth(u32) | Scale to fit the given width, preserving aspect ratio. |
FitHeight(u32) | Scale to fit the given height, preserving aspect ratio. |
FitBox { width, height } | Scale to fit within a bounding box, preserving aspect ratio. |
Exact { width, height } | Force exact pixel dimensions (may distort). |
§Multi-page rendering
use zenpdf::{render_pages, PdfConfig, PageSelection, RenderBounds};
let config = PdfConfig {
pages: PageSelection::Range { start: 0, end: 4 },
bounds: RenderBounds::Dpi(300.0),
background: [255, 255, 255, 255], // opaque white
render_annotations: true,
..PdfConfig::default()
};
let pages = render_pages(&pdf_data, &config).unwrap();
for page in &pages {
println!("page {}: {}x{}", page.index, page.buffer.width(), page.buffer.height());
}§zencodec integration
With the zencodec feature (enabled by default), zenpdf implements zencodec::decode::DecoderConfig for use in codec-agnostic image pipelines.
Default decode renders page 0. Use with_start_frame_index() on the job to select a different page.
use std::borrow::Cow;
use zencodec::decode::{Decode, DecodeJob, DecoderConfig};
use zenpdf::{PdfDecoderConfig, RenderBounds};
let config = PdfDecoderConfig::new()
.with_bounds(RenderBounds::Dpi(150.0));
let pdf_data = std::fs::read("document.pdf").unwrap();
let output = config.job()
.decoder(Cow::Borrowed(&pdf_data), &[])
.unwrap()
.decode()
.unwrap();
println!("{}x{}", output.width(), output.height());Resource limits are enforced when set via with_limits() on the job — input size, output dimensions, and pixel count are all checked before rendering begins.
§Features
| Feature | Default | Description |
|---|---|---|
zencodec | Yes | Implements zencodec::decode::DecoderConfig for codec-agnostic pipelines |
§Dependencies
All dependencies are permissive (MIT, Apache-2.0, Zlib, BSD-3-Clause, Unicode-3.0). No copyleft in the dependency tree.
§Image tech I maintain
| State of the art codecs* | zenjpeg · zenpng · zenwebp · zengif · zenavif (rav1d-safe · zenrav1e · zenavif-parse · zenavif-serialize) · zenjxl (jxl-encoder · zenjxl-decoder) · zentiff · zenbitmaps · heic · zenraw · zenpdf · ultrahdr · mozjpeg-rs · webpx |
| Compression | zenflate · zenzop |
| Processing | zenresize · zenfilters · zenquant · zenblend |
| Metrics | zensim · fast-ssim2 · butteraugli · resamplescope-rs · codec-eval · codec-corpus |
| Pixel types & color | zenpixels · zenpixels-convert · linear-srgb · garb |
| Pipeline | zenpipe · zencodec · zencodecs · zenlayout · zennode |
| ImageResizer | ImageResizer (C#) — 24M+ NuGet downloads across all packages |
| Imageflow | Image optimization engine (Rust) — .NET · node · go — 9M+ NuGet downloads across all packages |
| Imageflow Server | The fast, safe image server (Rust+C#) — 552K+ NuGet downloads, deployed by Fortune 500s and major brands |
* as of 2026
§General Rust awesomeness
archmage · magetypes · enough · whereat · zenbench · cargo-copter
And other projects · GitHub @imazen · GitHub @lilith · lib.rs/~lilith · NuGet (over 30 million downloads / 87 packages)
§License
Dual-licensed: AGPL-3.0 or commercial.
I’ve maintained and developed open-source image server software — and the 40+ library ecosystem it depends on — full-time since 2011. Fifteen years of continual maintenance, backwards compatibility, support, and the (very rare) security patch. That kind of stability requires sustainable funding, and dual-licensing is how we make it work without venture capital or rug-pulls. Support sustainable and secure software; swap patch tuesday for patch leap-year.
Your options:
- Startup license — $1 if your company has under $1M revenue and fewer than 5 employees. Get a key →
- Commercial subscription — Governed by the Imazen Site-wide Subscription License v1.1 or later. Apache 2.0-like terms, no source-sharing requirement. Sliding scale by company size. Pricing & 60-day free trial →
- AGPL v3 — Free and open. Share your source if you distribute.
See LICENSE-COMMERCIAL for details.
§AI-Generated Code Notice
Developed with Claude (Anthropic). Not all code manually reviewed. Review critical paths before production use.
Structs§
- PdfConfig
- Configuration for PDF page rendering.
- PdfDecoder
Config - PDF decoder configuration implementing
zencodec::decode::DecoderConfig. - Render
Limits - Resource limits for PDF rendering.
- Rendered
Page - A rendered PDF page with its pixel data and source dimensions.
Enums§
- Page
Selection - Which pages to render from a PDF document.
- PdfError
- Errors from PDF rendering.
- Render
Bounds - How to size the rendered output for each page.
Statics§
- PDF_
FORMAT - PDF format definition for zencodec registry.
Functions§
- page_
count - Returns the number of pages in a PDF document.
- page_
dimensions - Returns the dimensions (in PDF points) of a specific page.
- render_
page - Renders a single page from a PDF document.
- render_
pages - Renders selected pages from a PDF document according to the given configuration.