Page Rendering

Render PDF pages to PNG, JPEG, and WebP images, generate document previews, export to SVG, and convert images to PDF. FolioPDF uses two rendering pipelines: Skia for documents you create, and PDFium for existing PDFs you load.

Overview

FolioPDF provides two image rendering paths, each optimized for its use case:

PathEntry PointBackendUse Case
Layout-to-Image document.GenerateImages(settings) Skia Render pages from documents you build with Document.Create
PDF-to-Image page.RenderToPng(dpi) PDFium + Skia encoder Render pages from existing PDFs loaded with PdfiumDocument

Both paths use Skia for the final image encoding (PNG, JPEG, WebP) — there is a single encoder for each format across the entire library.

Render Existing PDF Pages

Render to PNG

using FolioPDF.Toolkit.Pdfium;

using var doc = PdfiumDocument.Load(File.ReadAllBytes("report.pdf"));
using var page = doc.GetPage(0);

// Default 150 DPI
byte[] png = page.RenderToPng();
File.WriteAllBytes("page1.png", png);

// High-resolution 300 DPI
byte[] hiRes = page.RenderToPng(dpi: 300);
File.WriteAllBytes("page1_hires.png", hiRes);

// Exact pixel dimensions (e.g. for a thumbnail)
byte[] thumb = page.RenderToPng(widthPx: 200, heightPx: 282);
File.WriteAllBytes("page1_thumb.png", thumb);

Render to JPEG

// Default 150 DPI, quality 85
byte[] jpeg = page.RenderToJpeg();

// Custom DPI and quality
byte[] jpeg = page.RenderToJpeg(dpi: 200, quality: 90);

// Exact pixel dimensions
byte[] jpeg = page.RenderToJpeg(widthPx: 800, heightPx: 1131, quality: 80);

Render to Raw Bitmap

For custom processing, render to a raw BGRA32 pixel buffer:

var bitmap = page.Render(width: 800, height: 1131);

Console.WriteLine($"Size:   {bitmap.Width}x{bitmap.Height}");
Console.WriteLine($"Stride: {bitmap.Stride} bytes per row");
Console.WriteLine($"Pixels: {bitmap.Pixels.Length} bytes total");

// Process pixels directly (BGRA32 layout)
for (int y = 0; y < bitmap.Height; y++)
{
    for (int x = 0; x < bitmap.Width; x++)
    {
        int offset = y * bitmap.Stride + x * 4;
        byte b = bitmap.Pixels[offset];
        byte g = bitmap.Pixels[offset + 1];
        byte r = bitmap.Pixels[offset + 2];
        byte a = bitmap.Pixels[offset + 3];
    }
}

RenderToPng / RenderToJpeg API Reference

MethodParametersReturns
RenderToPng(int dpi = 150) DPI resolution. Page is rendered at (Width * dpi / 72) by (Height * dpi / 72) pixels. byte[] — PNG-encoded image.
RenderToPng(int widthPx, int heightPx) Exact pixel dimensions. The page is scaled to fill these bounds. byte[] — PNG-encoded image.
RenderToJpeg(int dpi = 150, int quality = 85) DPI resolution and JPEG quality (1-100). byte[] — JPEG-encoded image.
RenderToJpeg(int widthPx, int heightPx, int quality = 85) Exact pixel dimensions and JPEG quality. byte[] — JPEG-encoded image.
Render(int width, int height) Pixel dimensions. PdfiumBitmap — raw BGRA32 pixels, width, height, stride.

Render All Pages

Render every page in a document to PNG:

using var doc = PdfiumDocument.Load(File.ReadAllBytes("report.pdf"));

int pageIndex = 0;
foreach (byte[] png in doc.RenderAllPagesToPng(dpi: 200))
{
    File.WriteAllBytes($"page_{pageIndex}.png", png);
    pageIndex++;
}

Generate Images from Layout Documents

When creating PDFs with Document.Create, you can generate images directly without producing a PDF first:

using FolioPDF;
using FolioPDF.Fluent;
using FolioPDF.Helpers;

var document = Document.Create(doc =>
{
    doc.Page(page =>
    {
        page.Size(PageSizes.A4);
        page.Margin(50);
        page.Content().Text("Quarterly Report").FontSize(24).Bold();
    });
});

// Generate PNG images (one per page)
var images = document.GenerateImages(new ImageGenerationSettings
{
    ImageFormat = ImageFormat.Png,
    RasterDpi = 200
});

int i = 0;
foreach (byte[] imageBytes in images)
{
    File.WriteAllBytes($"page_{i}.png", imageBytes);
    i++;
}

ImageGenerationSettings

PropertyTypeDefaultDescription
ImageFormat ImageFormat Png Output format: Png, Jpeg, or Webp.
RasterDpi int 150 Resolution in dots per inch. Higher values produce larger, sharper images.
Quality int 90 Compression quality for JPEG and WebP (1-100). Ignored for PNG.

Save Images to Files Directly

document.GenerateImages(
    filePathCallback: index => $"output/page_{index}.png",
    settings: new ImageGenerationSettings
    {
        ImageFormat = ImageFormat.Png,
        RasterDpi = 300
    });

JPEG and WebP Output

// JPEG with custom quality
var jpegImages = document.GenerateImages(new ImageGenerationSettings
{
    ImageFormat = ImageFormat.Jpeg,
    RasterDpi = 150,
    Quality = 85
});

// WebP (modern format, smaller files)
var webpImages = document.GenerateImages(new ImageGenerationSettings
{
    ImageFormat = ImageFormat.Webp,
    RasterDpi = 150,
    Quality = 80
});

SVG Export

Export each page as a self-contained SVG document. Text is emitted as SVG <text> elements with embedded font data; images as inline base64 <image> elements.

var document = Document.Create(doc =>
{
    doc.Page(page =>
    {
        page.Size(PageSizes.A4);
        page.Content().Column(col =>
        {
            col.Item().Text("Vector Output").FontSize(20);
            col.Item().Text("This renders as native SVG elements.");
        });
    });
});

// Get SVG strings (one per page)
IReadOnlyList<string> svgs = document.GenerateSvg();
for (int i = 0; i < svgs.Count; i++)
{
    Console.WriteLine($"Page {i}: {svgs[i].Length} characters");
    File.WriteAllText($"page_{i}.svg", svgs[i]);
}

// Or save directly to files
document.GenerateSvg(index => $"output/page_{index}.svg");

SVG is layout-engine only. SVG export works with documents built via Document.Create. To get an SVG from an existing PDF, render it to a high-DPI PNG and embed that in an SVG wrapper, or use a dedicated PDF-to-SVG converter.

Image to PDF Conversion

Convert raster images (PNG, JPEG, WebP, BMP, GIF) to PDF documents. Each image becomes one page.

Basic Conversion

using FolioPDF.Toolkit;

// Single image
byte[] pdf = ImageToPdfConverter.Convert("photo.jpg");
File.WriteAllBytes("photo.pdf", pdf);

// Multiple images = multi-page PDF
byte[] pdf = ImageToPdfConverter.Convert("scan1.jpg", "scan2.jpg", "scan3.jpg");
File.WriteAllBytes("scanned-document.pdf", pdf);

From Byte Arrays

byte[] image1 = File.ReadAllBytes("page1.png");
byte[] image2 = File.ReadAllBytes("page2.png");

byte[] pdf = ImageToPdfConverter.Convert(new[] { image1, image2 });
File.WriteAllBytes("combined.pdf", pdf);

Save Directly to File

ImageToPdfConverter.ConvertToFile("output.pdf", "photo1.jpg", "photo2.jpg");

With Layout Options

By default, each page is sized to the image's natural dimensions (pixels become PDF points at 72 DPI). Use ImageToPdfOptions to fit images to a specific page size:

using FolioPDF.Helpers;

// Fit to A4 with margins
byte[] pdf = ImageToPdfConverter.Convert(
    new[] { "scan1.jpg", "scan2.jpg" },
    new ImageToPdfOptions
    {
        PageSize = PageSizes.A4,
        Margin = 40      // 40pt margin on all sides
    });

// Fit to Letter size
byte[] pdf = ImageToPdfConverter.Convert(
    new[] { "photo.jpg" },
    new ImageToPdfOptions { PageSize = PageSizes.Letter });

ImageToPdfOptions

PropertyTypeDefaultDescription
PageSize PageSize? null Target page size. When null, each page matches the image's natural dimensions at 72 DPI.
Margin float 0 Margin in PDF points applied on all sides. Only used when PageSize is set.

Practical Examples

Thumbnail Generation Service

using FolioPDF.Toolkit.Pdfium;

byte[] GenerateThumbnail(byte[] pdfBytes, int thumbWidth = 200)
{
    using var doc = PdfiumDocument.Load(pdfBytes);
    using var page = doc.GetPage(0);

    // Calculate height to maintain aspect ratio
    float aspectRatio = page.Height / page.Width;
    int thumbHeight = (int)(thumbWidth * aspectRatio);

    return page.RenderToPng(thumbWidth, thumbHeight);
}

Document Preview (All Pages)

IEnumerable<byte[]> GeneratePreview(byte[] pdfBytes, int dpi = 100)
{
    using var doc = PdfiumDocument.Load(pdfBytes);
    for (int i = 0; i < doc.PageCount; i++)
    {
        using var page = doc.GetPage(i);
        yield return page.RenderToJpeg(dpi: dpi, quality: 75);
    }
}

Scan-to-PDF Workflow

using FolioPDF.Fluent;
using FolioPDF.Helpers;
using FolioPDF.Toolkit;

// 1. Convert scanned images to a base PDF
byte[] basePdf = ImageToPdfConverter.Convert(
    new[] { "scan_001.jpg", "scan_002.jpg", "scan_003.jpg" },
    new ImageToPdfOptions
    {
        PageSize = PageSizes.A4,
        Margin = 20
    });

// 2. Post-process: add metadata, compress, linearize
PdfEditor.Open(basePdf)
    .SetTitle("Scanned Contract")
    .SetAuthor("Scanner Station 3")
    .Compress(new CompressionOptions { ImageQuality = 70 })
    .Linearize()
    .Save("scanned-contract.pdf");

Web API: Return Page Image

// ASP.NET Core example
app.MapGet("/api/pdf/{id}/page/{pageIndex}/image", (int id, int pageIndex, int? dpi) =>
{
    byte[] pdfBytes = LoadPdfFromDatabase(id);
    using var doc = PdfiumDocument.Load(pdfBytes);
    using var page = doc.GetPage(pageIndex);
    byte[] png = page.RenderToPng(dpi ?? 150);
    return Results.File(png, "image/png");
});

DPI and Resolution Guide

Choose the right DPI for your use case:

DPIUse CaseA4 Page SizeApproximate File Size (PNG)
72Quick preview, web thumbnails595 x 842 px~100-300 KB
100Screen display, document viewer827 x 1170 px~200-600 KB
150General purpose (default)1240 x 1754 px~400 KB - 1 MB
200Good quality print preview1654 x 2339 px~800 KB - 2 MB
300High-quality print, archival2480 x 3508 px~1.5 - 4 MB
600Professional print production4961 x 7016 px~5 - 15 MB

Memory considerations: A single A4 page at 600 DPI produces approximately 140 MB of uncompressed BGRA32 pixel data (4961 × 7016 × 4 bytes). Use high DPI values only when necessary, and process one page at a time to avoid large heap allocations.

Supported Image Formats

FormatCompressionAlphaBest For
PNGLosslessYesScreenshots, text-heavy pages, archival
JPEGLossyNoPhotos, quick previews, bandwidth-constrained delivery
WebPLossy/LosslessYesModern web delivery, smaller than PNG/JPEG