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:
| Path | Entry Point | Backend | Use 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
| Method | Parameters | Returns |
|---|---|---|
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
| Property | Type | Default | Description |
|---|---|---|---|
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
| Property | Type | Default | Description |
|---|---|---|---|
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:
| DPI | Use Case | A4 Page Size | Approximate File Size (PNG) |
|---|---|---|---|
| 72 | Quick preview, web thumbnails | 595 x 842 px | ~100-300 KB |
| 100 | Screen display, document viewer | 827 x 1170 px | ~200-600 KB |
| 150 | General purpose (default) | 1240 x 1754 px | ~400 KB - 1 MB |
| 200 | Good quality print preview | 1654 x 2339 px | ~800 KB - 2 MB |
| 300 | High-quality print, archival | 2480 x 3508 px | ~1.5 - 4 MB |
| 600 | Professional print production | 4961 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
| Format | Compression | Alpha | Best For |
|---|---|---|---|
| PNG | Lossless | Yes | Screenshots, text-heavy pages, archival |
| JPEG | Lossy | No | Photos, quick previews, bandwidth-constrained delivery |
| WebP | Lossy/Lossless | Yes | Modern web delivery, smaller than PNG/JPEG |