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-Imagedocument.GenerateImages(settings)SkiaRender pages from documents you build with Document.Create
PDF-to-Imagepage.RenderToPng(dpi)PDFium + Skia encoderRender 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
ImageFormatImageFormatPngOutput format: Png, Jpeg, or Webp.
RasterDpiint150Resolution in dots per inch. Higher values produce larger, sharper images.
Qualityint90Compression 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
PageSizePageSize?nullTarget page size. When null, each page matches the image's natural dimensions at 72 DPI.
Marginfloat0Margin 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