Table of Contents

Reading and rendering PDFs

DocWright reads existing PDF files, including ones it didn't write. It renders their pages to images, reports page facts, and re-assembles pages into new PDFs. It doesn't convert a PDF back into an editable Word document: Load does not accept PDF.

The quick route

ConvertPdfToImages takes the same ImageRenderOptions as Word documents:

using DocWright;
using DocWright.Renderers.Imaging;

// The simple route: any PDF to PNGs, through the converter you already have.
var images = new ImageRenderOptions
{
    Dpi = 96,
    PageEncoded = (page, png) => File.WriteAllBytes($"report-page-{page}.png", png),
};

using (FileStream pdf = File.OpenRead("report.pdf"))
{
    converter.ConvertPdfToImages(pdf, images);
}

It is safe to call from many threads at once, because each call opens and disposes its own reader. From ConvertOptions it uses Pages, Password, Limits, Diagnostics, Progress and StrictMode.

Opening the document yourself

Use PdfDocument (namespace DocWright.Formats.Pdf) when you want the page facts before deciding what to render:

using DocWright.Core.Primitives;
using DocWright.Formats.Pdf;
using DocWright.Formats.Pdf.Raster;

// The reader itself: page facts first, then render only what you need.
using PdfDocument document = PdfDocument.Open("encrypted-statement.pdf", new PdfReadOptions
{
    Password = "secret",        // user or owner password
});

Console.WriteLine($"{document.PageCount} page(s), PDF {document.Version}, repaired: {document.WasRepaired}");
foreach (PdfPageInfo page in document.Pages)
{
    Console.WriteLine($"  page {page.PageNumber}: {page.DisplayWidthPoints:0.#} x {page.DisplayHeightPoints:0.#} pt");
}

var raster = new PdfRasterOptions { Dpi = 110, Format = PdfImageFormat.Png, Pages = PageRange.Single(1) };
foreach (PdfRenderedPage rendered in PdfRasterizer.Render(document, raster))
{
    File.WriteAllBytes($"statement-{rendered.PageNumber}.png", rendered.Bytes);
}

Output

1 page(s), PDF 1.7, repaired: False
  page 1: 595.3 x 841.9 pt
Wrong password.
encrypted-statement.pdf · page 1, RC4-128, produced by LibreOffice
The first page of an encrypted PDF produced by LibreOffice, rendered after decryption
  • WidthPoints and HeightPoints are the page as authored. The Display… values have the page's rotation applied and match what the renderer produces.
  • Use one PdfDocument per thread. It caches parsed objects on itself. PdfRasterizer is static and stateless.

Passwords and permissions

All standard PDF encryption is supported: RC4 40 and 128-bit, AES-128 and AES-256. Either the user or the owner password opens a file.

using DocWright.Core;
using DocWright.Formats.Pdf;

try
{
    using var locked = PdfDocument.Open("encrypted-statement.pdf", new PdfReadOptions { Password = "guess" });
}
catch (InvalidPasswordException)
{
    Console.WriteLine("Wrong password.");
}
Situation Exception
No password works InvalidPasswordException
An encryption scheme DocWright doesn't implement (certificate-based security) DocumentEncryptedException

Permission flags such as "printing not allowed" are advisory, and are not enforced by default. Set PdfReadOptions.EnforcePermissions = true if you must honour them: a document that forbids printing then throws UnsupportedFeatureException (DXP8009). DocWright doesn't write encrypted PDFs.

Damaged files

A damaged PDF is repaired where possible, and the repair is reported rather than hidden:

Damage Repair Code
Missing or broken cross-reference table Rebuilt by scanning the file DXP8003
Wrong stream length Found by scanning for the stream's end DXP8004
Broken page tree Pages recovered in object order DXP8003

PdfDocument.WasRepaired tells you whether any of this happened. PdfReadOptions.StrictMode = true turns every repair into an InvalidDocumentException instead.

What renders

Paths and clipping, every shading type, patterns, all 16 blend modes, transparency, images at every bit depth with their masks, form XObjects, annotation appearances, optional content, and text in embedded TrueType and CFF fonts, plus the standard 14 fonts.

Not supported, each reported with a diagnostic rather than skipped silently: soft masks in graphics states (DXP8001), Type 1 and Type 3 fonts (DXP8006, DXP8002), predefined CJK CMaps, and CCITT, JBIG2 and JPEG 2000 images (DXP8005). Colour is not managed, so saturated CMYK may look different from Adobe's rendering.