Recursive AI

Convert a PDF to an image in C#

All oneimage recipes

Add the RecursiveAI.OneImage.Pdf package, register PdfFormat in the load options, and load the PDF: each page is a frame. Save Frames[i].ToImage() as .png or .jpg. There is no PDFium, Ghostscript or other native binary to deploy. The program below renders every page of the IRS Form W-9, a public six-page PDF.

Terminal
dotnet new console -o PdfToImage && cd PdfToImage
dotnet add package RecursiveAI.OneImage.Pdf --version 1.10.4
curl -LO https://www.irs.gov/pub/irs-pdf/fw9.pdf

OneImage needs the .NET 10 SDK. Put this in Program.cs and run dotnet run:

C#
using OneImage;
using OneImage.Pdf;
 
// PDF is an add-on format: register it, drawn at 150 dpi.
var options = new LoadOptions
{
    Configuration = new ImageConfiguration()
        .Add(new PdfFormat(new PdfRenderOptions { Dpi = 150 })),
};
 
Image pdf = Image.Load("fw9.pdf", options);   // reads the structure, draws nothing
Console.WriteLine($"{pdf.FrameCount} pages");
 
for (int i = 0; i < pdf.FrameCount; i++)
{
    Image page = pdf.Frames[i].ToImage();
    page.Save($"page-{i + 1}.png");
    Console.WriteLine($"page-{i + 1}.png: {page.Width}x{page.Height}");
}
Text
6 pages
page-1.png: 1275x1650
page-2.png: 1275x1650
page-3.png: 1275x1650
page-4.png: 1275x1650
page-5.png: 1275x1650
page-6.png: 1275x1650

A US Letter page is 612×792 points, so at 150 dpi it is 1275×1650 pixels: points × dpi ÷ 72. Pages are drawn on opaque white, as viewers show them. The output format follows the extension, so .jpg and .webp work the same way.

One page at 300 dpi, and a thumbnail

To render only some pages, set FirstPage (zero-based) and PageCount. A resize right after the load draws the page at the final size instead of drawing it large and shrinking it:

C#
using OneImage;
using OneImage.Pdf;
 
// Page 1 only, at 300 dpi, as JPEG.
var page1 = new LoadOptions
{
    Configuration = new ImageConfiguration().Add(new PdfFormat(
        new PdfRenderOptions { Dpi = 300, FirstPage = 0, PageCount = 1 })),
};
Image.Load("fw9.pdf", page1).Save("page-1-300dpi.jpg", new SaveOptions
{
    EncoderOptions = new JpegEncoderOptions { Quality = 85 },
});
 
// A 300 px wide WebP thumbnail of the first page.
Image.Thumbnail("fw9.pdf", 300, loadOptions: page1).Save("cover.webp");
 
foreach (string file in new[] { "page-1-300dpi.jpg", "cover.webp" })
{
    ImageInfo info = Image.Identify(file);
    long kb = new FileInfo(file).Length / 1024;
    Console.WriteLine($"{file}: {info.Width}x{info.Height}, {kb} KB");
}
Text
page-1-300dpi.jpg: 2550x3300, 1186 KB
cover.webp: 300x388, 21 KB
DpiUS Letter in pixelsTypical use
72612×792Previews
150 (default)1275×1650Readable page images
3002550×3300OCR and print-quality archives

PdfRenderOptions also sets the page box, whether annotations are drawn, a transparent Background, and the Password of an encrypted file.

Limits

  • It renders pixels only. To get the text out of a PDF, see Extract text from a PDF in OnePDF.
  • Untrusted files are bounded. File size, page size, image pixels and nesting depth are checked from the file before memory is allocated; a file over a limit throws ImageLimitException. The limits table has the defaults.
  • JPEG and BMP hold one page. Saving the whole document as .jpg writes page 1 only; loop over Frames, or save a multipage TIFF.
  • .NET 10 only. PDFtoImage (MIT) wraps native PDFium and supports older frameworks.

How pages are drawn and checked is in the OneImage.Pdf docs.