Tesseract OCR Adapters

HPDFTesseractRecognition offers optional Windows engines implementing IHPDFOCREngine for searchable OCR text layers

Native DLL factory

function HPDFCreateTesseractDLLOCREngine(const LibraryPath,
  TessDataDirectory, Language: string): IHPDFOCREngine; overload;
function HPDFCreateTesseractDLLOCREngine(const LibraryPath,
  TessDataDirectory, Language: string;
  const Options: THPDFTesseractOptions): IHPDFOCREngine; overload;

Supply an existing Tesseract DLL exposing the Tesseract 5 compatible C API, a tessdata directory and an ASCII language identifier or combination such as eng, chi_sim or chi_sim+eng

The library architecture has to match the application: a Win32 application loads a 32-bit DLL whilst a Win64 application loads a 64-bit DLL

Keep any required dependency DLLs next to the chosen library or in the standard Windows loader directories; the adapter loads the explicit library path without touching the current directory or the process search path

Before returning, the factory verifies every requested .traineddata file, loads the library and resolves the required exports; invalid paths, models or options, missing exports, architecture mismatches and unavailable dependencies all raise an exception

No OCR runtime or models are bundled, and nothing is downloaded automatically

Both factories ship in the Windows FPC/Lazarus package as well as the Delphi and C++Builder builds; rebuild Lib/FPC/HotPDFLaz.lpk for the target architecture before calling HPDFTesseractRecognition

The native FPC adapter reads the current LCL raw image — pixels written through scanlines included — and keeps Unicode words intact regardless of the system ANSI code page

Options

THPDFTesseractOptions = record
  PageSegMode: THPDFTesseractPageSegMode;
  EngineMode: THPDFTesseractEngineMode;
  TimeoutMilliseconds: Cardinal;
  MaxPixels: Integer;
  class function Default: THPDFTesseractOptions; static;
end;

Call THPDFTesseractOptions.Default before overriding fields; the same record can configure the native DLL factory or the local CLI options overload

FieldDefaultMeaning
PageSegModetpsAutoAutomatic page segmentation without orientation detection
EngineModetemDefaultThe engine mode the selected language models support
TimeoutMilliseconds60000A request deadline from 1 through 3,600,000 milliseconds; the DLL cooperates with cancellation, whilst the CLI worker is terminated on timeout
MaxPixels16777216The input pixel budget, settable anywhere from 1 to 67,108,864 pixels
THPDFTesseractPageSegMode = (
  tpsOSDOnly, tpsAutoOSD, tpsAutoOnly, tpsAuto, tpsSingleColumn,
  tpsSingleBlockVertical, tpsSingleBlock, tpsSingleLine, tpsSingleWord,
  tpsCircleWord, tpsSingleCharacter, tpsSparseText, tpsSparseTextOSD,
  tpsRawLine);
THPDFTesseractEngineMode = (
  temLegacyOnly, temLSTMOnly, temLegacyAndLSTM, temDefault);

tpsOSDOnly and tpsAutoOnly do no word recognition at all and are rejected by the adapter; tpsAutoOSD and tpsSparseTextOSD additionally call for osd.traineddata

Take tpsSingleLine for a single text line, tpsSingleBlock for a uniform block or tpsSparseText for scattered text; none of these modes straightens out a scan's perspective or offers any general layout guarantee

temLSTMOnly needs LSTM models whilst the legacy modes need the corresponding legacy model components; unsupported combinations fail during native initialisation

Searchable PDF example

The PDF must already be loaded, and the DLL, its dependencies and the language models must be installed at the paths shown

uses SysUtils, HPDFDoc, HPDFTesseractRecognition;

procedure AddNativeOCRText(PDF: THotPDF);
var
  Engine: IHPDFOCREngine;
  NativeOptions: THPDFTesseractOptions;
  LayerOptions: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  NativeOptions := THPDFTesseractOptions.Default;
  NativeOptions.EngineMode := temLSTMOnly;
  NativeOptions.PageSegMode := tpsAuto;
  Engine := HPDFCreateTesseractDLLOCREngine(
    'C:\OCR\libtesseract-5.dll', 'C:\OCR\tessdata',
    'chi_sim+eng', NativeOptions);
  LayerOptions := THPDFOCRTextLayerOptions.Default;
  if not PDF.ApplyLoadedOCRTextLayer([0], Engine, LayerOptions, Info) then
    raise Exception.Create(string(Info.Diagnostic));
end;

Results and ownership

The adapter copies the borrowed bitmap into a top-down grayscale buffer, passes the request DPI through and recognises via a request-local native API instance

Words keep their native reading order, validated UTF-8 Unicode text, top-left pixel bounds and confidence rescaled from 0-100 onto 0-1; supplementary characters consume two UTF-16 units

Word baselines come through with both endpoints where available; when one is not, the existing text-layer geometry fallback takes over

For a predominantly vertical baseline, the native adapter uses the word box width as TextHeightPixels; horizontal baselines use the box height, including reversed reading directions, so a vertical word's length does not become its font size

This is a dominant-axis estimate: an axis-aligned word box and baseline alone cannot recover exact text height at arbitrary skew angles

An empty page succeeds with an empty word array; malformed UTF-8, embedded control characters, invalid geometry or confidence, exhausted word or text budgets, cancellation and recognition failures all return False, clear every partial word and fill in the diagnostic

Every request releases its iterator, allocated native strings, monitor and API instance; releasing the adapter drops its library reference

Limits and cancellation

Each input dimension may be at most 32,767 pixels and must fit within MaxPixels; recognised text has to fit the request's MaxTextCodeUnits budget and the adapter's 1,048,576 UTF-16 unit ceiling, and the word count has to fit MaxWords

During bitmap conversion and result iteration the adapter checks cancellation and elapsed time, and during recognition it hands the native side a monitor carrying the remaining deadline and a cancellation callback

Native cancellation is cooperative: Tesseract's monitor covers word recognition but does not interrupt every initialisation or layout-analysis step, so those calls may run to completion before a requested cancellation or expired deadline surfaces

The pixel and output budgets set no hard limit on the native library's model or recognition memory; prefer the process adapter when the application needs a worker it can terminate independently

ApplyLoadedOCRTextLayer validates every result and publishes all selected pages atomically, so an adapter failure leaves the loaded document exactly as it was

The DLL adapter rejects invalid UTF-8, trims decoded word text, and rejects remaining C0, DEL, and C1 control characters before returning results, so malformed text fails the request instead of being silently omitted by the PDF text layer

Local CLI factory

function HPDFCreateTesseractOCREngine(const ExecutablePath,
  TessDataDirectory, Language: string;
  TimeoutMilliseconds: Cardinal = 60000): IHPDFOCREngine; overload;
function HPDFCreateTesseractOCREngine(const ExecutablePath,
  TessDataDirectory, Language: string;
  const Options: THPDFTesseractOptions): IHPDFOCREngine; overload;

The options overload forwards PageSegMode as --psm and EngineMode as --oem, uses the configured timeout, and checks MaxPixels before saving the borrowed bitmap or starting a worker

The existing timeout overload preserves automatic page segmentation and executable-selected engine mode without imposing a new adapter pixel limit; use the options overload when an explicit input limit is required

Both overloads retain requested DPI, TSV output, restricted inherited handles, cancellation polling, and worker termination on failure; the CLI has no native baseline information, limits TSV output to 64 MiB, and limits diagnostic-file output to 1 MiB

Invalid segmentation modes, engine modes, timeouts, and pixel limits raise EArgumentException when creating the configured engine; model availability, including osd.traineddata for orientation modes, and model/engine compatibility are checked by the executable during recognition

var
  CLIOptions: THPDFTesseractOptions;
  Engine: IHPDFOCREngine;
begin
  CLIOptions := THPDFTesseractOptions.Default;
  CLIOptions.PageSegMode := tpsSingleLine;
  CLIOptions.EngineMode := temLSTMOnly;
  CLIOptions.MaxPixels := 8000000;
  Engine := HPDFCreateTesseractOCREngine(
    'C:\OCR\tesseract.exe', 'C:\OCR\tessdata', 'eng', CLIOptions);
end;

Use tpsSingleWord for an isolated word, tpsSparseText for scattered text, or tpsSingleBlockVertical with a suitable vertical-text model for one vertical block; the factory does not crop pages or select models automatically

The CLI adapter strictly validates UTF-8, rejects NUL bytes and C0/C1 control characters inside recognised words, and clears all results if malformed output follows an otherwise valid word

Turn to Searchable OCR Text Layers for the CLI example, rendering options, optional-content grouping and conformance limits