This document describes how to use the Delphi PDFium wrapper classes (DX.Pdf.*) in your own projects.
The DX.Pdf wrapper classes provide three layers of abstraction for working with PDF documents in Delphi:
- DX.Pdf.API - Low-level C-API bindings to PDFium
- DX.Pdf.Document - High-level object-oriented wrapper
- DX.Pdf.Viewer.FMX - Visual FMX component for displaying PDFs
Most applications will use DX.Pdf.Document for programmatic access or DX.Pdf.Viewer.FMX for visual display.
Copy the following files to your project:
src/DX.Pdf.API.pas
src/DX.Pdf.Document.pas
src/DX.Pdf.Viewer.FMX.pas (optional, only for FMX applications)
Download PDFium binaries from:
Place the appropriate library file in your application directory:
| Platform | File | Location |
|---|---|---|
| Windows 32-bit | pdfium.dll |
Same directory as .exe |
| Windows 64-bit | pdfium.dll |
Same directory as .exe |
| macOS | libpdfium.dylib |
Same directory as app bundle |
| Linux | libpdfium.so |
Same directory as executable |
| Android | libpdfium.so |
Deploy as library |
| iOS | libpdfium.a |
Link statically |
uses
DX.Pdf.Document; // For programmatic access
// or
DX.Pdf.Viewer.FMX; // For visual componentuses
DX.Pdf.Document;
procedure RenderPdfToFile(const APdfPath, AOutputPath: string);
var
LDoc: TPdfDocument;
LPage: TPdfPage;
LBitmap: TBitmap;
begin
// Load PDF document
LDoc := TPdfDocument.Create(APdfPath);
try
// Get first page
LPage := LDoc.Pages[0];
// Create bitmap
LBitmap := TBitmap.Create;
try
// Render at 150 DPI
LPage.RenderToBitmap(LBitmap, 150);
// Save to file
LBitmap.SaveToFile(AOutputPath);
finally
LBitmap.Free;
end;
finally
LDoc.Free;
end;
end;uses
DX.Pdf.Viewer.FMX;
procedure TForm1.FormCreate(Sender: TObject);
begin
// Create PDF viewer
FPdfViewer := TPdfViewer.Create(Self);
FPdfViewer.Parent := Self;
FPdfViewer.Align := TAlignLayout.Client;
// Load PDF
FPdfViewer.LoadFromFile('document.pdf');
end;
procedure TForm1.NextPageButtonClick(Sender: TObject);
begin
FPdfViewer.NextPage;
end;
procedure TForm1.PreviousPageButtonClick(Sender: TObject);
begin
FPdfViewer.PreviousPage;
end;Low-level C-API bindings. Use only if you need direct access to PDFium functions.
Key Functions:
FPDF_InitLibrary- Initialize PDFiumFPDF_DestroyLibrary- Cleanup PDFiumFPDF_LoadDocument- Load PDF from fileFPDF_CloseDocument- Close PDF documentFPDF_GetPageCount- Get number of pagesFPDF_LoadPage- Load a specific pageFPDF_ClosePage- Close a pageFPDF_RenderPageBitmap- Render page to bitmap
Example:
uses
DX.Pdf.API;
var
LDoc: FPDF_DOCUMENT;
LPageCount: Integer;
begin
FPDF_InitLibrary;
try
LDoc := FPDF_LoadDocument(PAnsiChar(AnsiString(APdfPath)), nil);
if LDoc <> nil then
begin
LPageCount := FPDF_GetPageCount(LDoc);
ShowMessage('Page count: ' + LPageCount.ToString);
FPDF_CloseDocument(LDoc);
end;
finally
FPDF_DestroyLibrary;
end;
end;High-level object-oriented wrapper with automatic resource management.
Constructor:
constructor Create(const AFilePath: string);Properties:
PageCount: Integer- Number of pages in documentPages[Index: Integer]: TPdfPage- Access pages by index (0-based)Title: string- Document title from metadataAuthor: string- Document author from metadataSubject: string- Document subject from metadataKeywords: string- Document keywords from metadataCreator: string- Application that created the documentProducer: string- PDF producerCreationDate: string- Creation dateModificationDate: string- Last modification dateVersion: string- PDF version (e.g., "1.7")IsPdfA: Boolean- True if document is PDF/A compliantPdfAVersion: string- PDF/A version if applicable
Example:
var
LDoc: TPdfDocument;
begin
LDoc := TPdfDocument.Create('document.pdf');
try
ShowMessage('Title: ' + LDoc.Title);
ShowMessage('Pages: ' + LDoc.PageCount.ToString);
ShowMessage('PDF Version: ' + LDoc.Version);
if LDoc.IsPdfA then
ShowMessage('PDF/A Version: ' + LDoc.PdfAVersion);
finally
LDoc.Free;
end;
end;Properties:
Width: Double- Page width in points (1/72 inch)Height: Double- Page height in pointsPageIndex: Integer- Zero-based page index
Methods:
procedure RenderToBitmap(ABitmap: TBitmap; ADPI: Integer = 96);Renders the page to a bitmap at the specified DPI.
Example:
var
LDoc: TPdfDocument;
LPage: TPdfPage;
LBitmap: TBitmap;
begin
LDoc := TPdfDocument.Create('document.pdf');
try
LPage := LDoc.Pages[0];
LBitmap := TBitmap.Create;
try
// Render at 300 DPI for high quality
LPage.RenderToBitmap(LBitmap, 300);
// Use bitmap...
Image1.Bitmap.Assign(LBitmap);
finally
LBitmap.Free;
end;
finally
LDoc.Free;
end;
end;Visual FMX component for displaying PDF documents.
Properties:
CurrentPage: Integer- Current page number (1-based)PageCount: Integer- Total number of pagesDocument: TPdfDocument- Underlying PDF document (read-only)ShowLoadingIndicator: Boolean- Show/hide loading animation (default: True)
Methods:
procedure LoadFromFile(const AFilePath: string);
procedure NextPage;
procedure PreviousPage;
procedure GoToPage(APageNumber: Integer);
procedure Clear;Events:
property OnPageChanged: TNotifyEvent;Fired when the current page changes.
Example:
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
FPdfViewer: TPdfViewer;
procedure OnPdfPageChanged(Sender: TObject);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FPdfViewer := TPdfViewer.Create(Self);
FPdfViewer.Parent := Self;
FPdfViewer.Align := TAlignLayout.Client;
FPdfViewer.OnPageChanged := OnPdfPageChanged;
FPdfViewer.LoadFromFile('document.pdf');
end;
procedure TForm1.OnPdfPageChanged(Sender: TObject);
begin
StatusBar1.SimpleText := Format('Page %d of %d',
[FPdfViewer.CurrentPage, FPdfViewer.PageCount]);
end;procedure ExtractAllPages(const APdfPath, AOutputDir: string);
var
LDoc: TPdfDocument;
LPage: TPdfPage;
LBitmap: TBitmap;
I: Integer;
begin
LDoc := TPdfDocument.Create(APdfPath);
try
LBitmap := TBitmap.Create;
try
for I := 0 to LDoc.PageCount - 1 do
begin
LPage := LDoc.Pages[I];
LPage.RenderToBitmap(LBitmap, 150);
LBitmap.SaveToFile(TPath.Combine(AOutputDir,
Format('page_%d.png', [I + 1])));
end;
finally
LBitmap.Free;
end;
finally
LDoc.Free;
end;
end;procedure ShowPdfInfo(const APdfPath: string);
var
LDoc: TPdfDocument;
LInfo: TStringList;
begin
LDoc := TPdfDocument.Create(APdfPath);
try
LInfo := TStringList.Create;
try
LInfo.Add('Title: ' + LDoc.Title);
LInfo.Add('Author: ' + LDoc.Author);
LInfo.Add('Subject: ' + LDoc.Subject);
LInfo.Add('Keywords: ' + LDoc.Keywords);
LInfo.Add('Creator: ' + LDoc.Creator);
LInfo.Add('Producer: ' + LDoc.Producer);
LInfo.Add('Created: ' + LDoc.CreationDate);
LInfo.Add('Modified: ' + LDoc.ModificationDate);
LInfo.Add('Version: ' + LDoc.Version);
LInfo.Add('Pages: ' + LDoc.PageCount.ToString);
if LDoc.IsPdfA then
LInfo.Add('PDF/A: ' + LDoc.PdfAVersion)
else
LInfo.Add('PDF/A: No');
ShowMessage(LInfo.Text);
finally
LInfo.Free;
end;
finally
LDoc.Free;
end;
end;procedure RenderHighQuality(const APdfPath: string; AImage: TImage);
var
LDoc: TPdfDocument;
LPage: TPdfPage;
LBitmap: TBitmap;
begin
LDoc := TPdfDocument.Create(APdfPath);
try
LPage := LDoc.Pages[0];
LBitmap := TBitmap.Create;
try
// Render at 300 DPI for print quality
LPage.RenderToBitmap(LBitmap, 300);
AImage.Bitmap.Assign(LBitmap);
finally
LBitmap.Free;
end;
finally
LDoc.Free;
end;
end;LDoc := TPdfDocument.Create(AFilePath);
try
// Use document
finally
LDoc.Free;
end;For responsive UI, render pages in background threads:
TTask.Run(
procedure
var
LBitmap: TBitmap;
begin
LBitmap := TBitmap.Create;
try
LPage.RenderToBitmap(LBitmap, 150);
TThread.Synchronize(nil,
procedure
begin
Image1.Bitmap.Assign(LBitmap);
end);
finally
LBitmap.Free;
end;
end);- Screen display: 96-150 DPI
- High-DPI displays: 150-200 DPI
- Print quality: 300 DPI
- High-quality print: 600 DPI
try
LDoc := TPdfDocument.Create(AFilePath);
try
// Use document
finally
LDoc.Free;
end;
except
on E: Exception do
ShowMessage('Error loading PDF: ' + E.Message);
end;Solution: Ensure pdfium.dll (Windows) or equivalent library is in the same directory as your executable.
Solution:
- Always use try..finally blocks
- Don't access pages after document is freed
- Don't render from multiple threads simultaneously to the same document
Solution: Increase DPI when calling RenderToBitmap:
LPage.RenderToBitmap(LBitmap, 150); // Instead of 96Solution:
- Render pages on-demand, not all at once
- Free bitmaps when no longer needed
- Use background threads to avoid UI blocking
The DX.Pdf wrapper classes are part of DX Pdfium4D and are licensed under the MIT License.
PDFium itself is licensed under the BSD-3-Clause License.
For questions, issues, or contributions:
- GitHub: https://github.com/omonien/DX-Pdfium4D
- Website: https://developer-experts.net
- Email: olaf@monien.net
Part of DX Pdfium4D - Delphi Cross-Platform Wrapper für Pdfium Copyright (c) 2025 Olaf Monien