How PDF to Image Rendering Works with Target Dimensions in OLMocr

In OLMocr, PDF to image rendering scales pages by matching the longest side to a user-specified target pixel dimension (default 2048 px for PNG or 1024 px for WebP) while preserving aspect ratio through dynamic DPI calculation.

OLMocr is an open-source library for converting PDF documents into machine-readable formats. When performing PDF to image rendering, the library enforces pixel budget constraints by calculating a custom rasterization resolution that ensures the output image never exceeds the target size while maintaining the original page proportions.

The Three-Step Rendering Pipeline

The implementation in olmocr/data/renderpdf.py processes each PDF page through a precise sequence that bridges physical document units (points) to digital pixels.

Step 1: Extracting Physical Page Dimensions

The pipeline begins by measuring the source page using get_pdf_media_box_width_height(). This function executes the pdfinfo CLI utility to extract the MediaBox rectangle from the PDF metadata, returning the physical width and height in points (where 1 pt equals 1/72 inch).


# https://github.com/allenai/olmocr/blob/main/olmocr/data/renderpdf.py#L9-L34

longest_dim = max(get_pdf_media_box_width_height(local_pdf_path, page_num))

Step 2: Computing Dynamic Rasterization DPI

Rather than using a fixed DPI, OLMocr calculates a resolution specific to each page. Because 1 pt corresponds to 72 px, the required DPI is computed as:

[ \text{dpi} = \frac{\text{target_longest_image_dim} \times 72}{\text{longest_dim}} ]

This value is passed to pdftoppm via the -r flag, ensuring the output image's longest side equals exactly the target dimension while the shorter side scales proportionally.


# https://github.com/allenai/olmocr/blob/main/olmocr/data/renderpdf.py#L51-L53

"-r",
str(target_longest_image_dim * 72 / longest_dim),

Step 3: Rasterization and Format Encoding

The pdftoppm tool renders the selected page to a PNG stream, which is then base-64-encoded. The render_pdf_to_base64png() function handles this directly, while render_pdf_to_base64webp() adds an intermediate step that opens the PNG with Pillow and re-encodes it to WebP format before base-64 encoding.


# PNG rendering – https://github.com/allenai/olmocr/blob/main/olmocr/data/renderpdf.py#L39-L60

# WebP conversion – https://github.com/allenai/olmocr/blob/main/olmocr/data/renderpdf.py#L63-L70

Code Examples and Usage

The following examples demonstrate how to convert PDF pages with specific target dimensions:


# Example 1 – Convert page 3 of a PDF to a base-64 PNG whose longest side is 2048 px

from olmocr.data.renderpdf import render_pdf_to_base64png

pdf_path = "/data/papers/sample.pdf"
page_number = 3
png_b64 = render_pdf_to_base64png(pdf_path, page_number, target_longest_image_dim=2048)

# Example 2 – Same page, but obtain a WebP image with a 1024 px longest side

from olmocr.data.renderpdf import render_pdf_to_base64webp

webp_b64 = render_pdf_to_base64webp(pdf_path, page_number, target_longest_image_dim=1024)

# Example 3 – Quickly query the dimensions of the resulting PNG without full decode

from olmocr.data.renderpdf import get_png_dimensions_from_base64

width, height = get_png_dimensions_from_base64(png_b64)
print(f"Rendered PNG size: {width}×{height}")

Performance Optimization with Dimension Caching

The helper function get_png_dimensions_from_base64() reads image dimensions directly from the base-64 string header without fully decoding the PNG. This optimization speeds up downstream filtering when processing large batches of documents, as the pipeline can verify output sizes before expensive deserialization.

Why Scale by the Longest Dimension?

By calculating DPI based on the longest side, OLMocr guarantees that the output never exceeds the target pixel budget while keeping the original aspect ratio intact. This approach works uniformly for both portrait and landscape page orientations, ensuring consistent resolution across mixed document collections.

Summary

  • Dynamic DPI calculation: OLMocr computes a custom resolution for each page using the formula (target_longest_image_dim * 72) / longest_dim to ensure the output matches exact pixel specifications.
  • Longest-side scaling: The system measures the PDF's MediaBox via pdfinfo and scales based on the longest dimension to preserve aspect ratio across all orientations.
  • Format flexibility: The render_pdf_to_base64png() and render_pdf_to_base64webp() functions support different output formats with appropriate defaults (2048 px for PNG, 1024 px for WebP).
  • Header-only dimension queries: get_png_dimensions_from_base64() enables fast size verification without full image decoding.

Frequently Asked Questions

What is the default target dimension for PDF to image rendering in OLMocr?

By default, render_pdf_to_base64png() uses a target dimension of 2048 pixels for the longest side, while render_pdf_to_base64webp() defaults to 1024 pixels. These values can be overridden via the target_longest_image_dim parameter.

How does OLMocr preserve aspect ratio when rendering PDFs to images?

The library calculates a specific DPI value for each page based on its physical dimensions in points. By applying this DPI to pdftoppm via the -r flag, the tool scales both width and height proportionally, ensuring the longest side matches the target while the shorter side scales accordingly.

Why does OLMocr use the longest side rather than the width or height for scaling?

Scaling by the longest side provides a consistent pixel budget across both portrait and landscape orientations. This prevents landscape pages from exceeding memory constraints while ensuring portrait pages maintain sufficient resolution, as the aspect ratio remains locked during rasterization.

Can I retrieve image dimensions without decoding the entire base64 string?

Yes. The get_png_dimensions_from_base64() function parses the PNG header within the base-64 string to extract width and height dimensions without performing full base-64 decoding or image deserialization, significantly improving performance when validating large batches.

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 →