How to Generate PDF Screenshots with Custom DPI Using LiteParse

Set the dpi field on LiteParseConfig before creating a LiteParse instance, then call screenshot() to render PDF pages at your desired resolution.

LiteParse is a Rust-based document processing library in the run-llama/liteparse repository that extracts text and generates PNG screenshots from PDFs, Word documents, and images. Controlling the output resolution through custom DPI settings is critical for producing high-quality document previews and ensuring adequate pixel density for downstream OCR tasks.

How DPI Configuration Works in LiteParse

The Configuration Structure

In [crates/liteparse/src/config.rs](https://github.com/run-llama/liteparse/blob/main/crates/liteparse/src/config.rs), the LiteParseConfig struct defines the DPI as a 64-bit floating point value:

pub struct LiteParseConfig {
    pub dpi: f64,  // Default: 72.0
    // ... other fields
}

This configuration is immutable after instantiation. The default value of 72.0 DPI matches standard web resolution, but you can increase this to 150, 300, or higher for print-quality screenshots.

The Rendering Pipeline

When you request a screenshot, the library executes a multi-stage process:

  1. The public API methods LiteParse::screenshot or screenshot_input accept file paths and page numbers
  2. These methods forward the DPI value from your configuration to the rendering layer
  3. In [crates/liteparse/src/render.rs](https://github.com/run-llama/liteparse/blob/main/crates/liteparse/src/render.rs), the render_pages_to_png function applies the DPI to PDFium's rasterization engine
  4. PDFium renders the page bitmap under a global lock (required for thread safety), which is then encoded to PNG format

Implementation Flow

The DPI parameter flows through the system in this order:

Code Examples

Rust Library Usage

Programmatically configure DPI and generate screenshots for specific pages:

use liteparse::{LiteParse, LiteParseConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Configure custom DPI (e.g., 150 for high-quality previews)
    let mut cfg = LiteParseConfig::default();
    cfg.dpi = 150.0;
    cfg.ocr_enabled = false;  // Disable OCR if only screenshots needed

    // Instantiate with custom configuration
    let lp = LiteParse::new(cfg);

    // Generate screenshots for pages 1-3
    let results = lp
        .screenshot("document.pdf", Some(vec![1, 2, 3]))
        .await?;

    // Save PNG bytes to disk
    for page in results {
        std::fs::write(
            format!("page_{}.png", page.page_num),
            page.image_bytes,
        )?;
        
        println!(
            "Page {}: {}×{} pixels at {} DPI",
            page.page_num, page.width, page.height, cfg.dpi
        );
    }
    
    Ok(())
}

Under the hood, LiteParse::screenshot calls render::render_pages_to_png, which initializes the PDFium library, loads the requested pages, and rasterizes them at the specified DPI before PNG encoding.

Command Line Interface

Override the default 72 DPI directly from the terminal:

liteparse screenshot --dpi 300 --output-dir ./screenshots document.pdf

The CLI parses the --dpi flag in [main.rs](https://github.com/run-llama/liteparse/blob/main/crates/liteparse/src/main.rs) and constructs a LiteParseConfig with your specified value before invoking the same rendering path as the library API.

Python Bindings

When using LiteParse through Python, configure the DPI via the configuration object:

from liteparse import LiteParse, LiteParseConfig

# Initialize config with custom DPI

config = LiteParseConfig()
config.dpi = 200.0

lp = LiteParse(config)

# Returns list of screenshot results

screens = lp.screenshot("document.pdf", [1, 2])

for screen in screens:
    with open(f"page_{screen['page_num']}.png", "wb") as f:
        f.write(screen["image_bytes"])

The Python wrapper forwards the configuration to the underlying Rust core, ensuring identical DPI behavior across all language bindings.

Key Source Files

Understanding these core files helps when debugging resolution issues or extending functionality:

Summary

  • Configure DPI early by setting LiteParseConfig::dpi before instantiating LiteParse; the default is 72.0 DPI
  • Thread safety is maintained through a global lock during PDFium rendering, with DPI being the primary quality control parameter
  • Multi-platform support ensures consistent DPI behavior across Rust native code, CLI tools, and Python bindings
  • Higher DPI values (150-300) significantly improve text legibility in screenshots but increase memory usage and file size proportionally
  • The rendering pipeline flows from config → parser → [render.rs](https://github.com/run-llama/liteparse/blob/main/crates/liteparse/src/render.rs) → PDFium bitmap generation

Frequently Asked Questions

What is the default DPI in LiteParse?

The default DPI is 72.0, defined in the LiteParseConfig struct within [config.rs](https://github.com/run-llama/liteparse/blob/main/crates/liteparse/src/config.rs). This matches standard screen resolution and produces smaller file sizes, but you should increase it to 150 or 300 for high-quality document previews or OCR preprocessing.

Can I specify different DPI values for individual pages in the same document?

No, DPI is configured at the LiteParseConfig level and applies uniformly to all screenshots generated during a single session. To create screenshots with different resolutions for different pages, you must create separate LiteParse instances with distinct configurations or reconfigure between calls.

Does changing the DPI affect text extraction or OCR accuracy?

DPI configuration only affects screenshot generation. Text extraction operates on the underlying PDF content streams and remains independent of rasterization resolution. However, if you enable OCR on screenshots (ocr_enabled: true), higher DPI values will improve OCR accuracy by providing more pixel data to the text recognition engine.

Why does LiteParse use a global lock during rendering?

PDFium (the underlying PDF rendering engine) requires thread synchronization to prevent concurrent access to shared library resources. In [render.rs](https://github.com/run-llama/liteparse/blob/main/crates/liteparse/src/render.rs), LiteParse acquires a global mutex before calling PDFium's render methods, ensuring that multiple threads can safely generate screenshots with custom DPI settings without causing race conditions or memory corruption.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →