Tesseract OCR Adapters

HPDFTesseractRecognition provides 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;

Provide 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 must match the application: a Win32 application loads a 32-bit DLL, while a Win64 application loads a 64-bit DLL

Keep required dependency DLLs beside the chosen library or in standard Windows loader directories; the adapter loads the explicit library path without changing the current directory or process search path

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

No OCR runtime or models are bundled or downloaded automatically

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

The native FPC adapter reads the current LCL raw image, including pixels written through scanlines, and preserves Unicode words independently 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 supported by the selected language models
TimeoutMilliseconds60000A request deadline from 1 through 3,600,000 milliseconds; the DLL cooperates with cancellation, while the CLI worker is terminated on timeout
MaxPixels16777216The input pixel budget, configurable from 1 through 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 perform no word recognition and are rejected by the adapter; tpsAutoOSD and tpsSparseTextOSD additionally require osd.traineddata

Use tpsSingleLine for one text line, tpsSingleBlock for a uniform block, or tpsSparseText for scattered text; these modes do not repair a scan's perspective or provide a general layout guarantee

temLSTMOnly requires LSTM models, while legacy modes require corresponding legacy model components; unsupported combinations fail during native initialization

Searchable PDF example

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

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, forwards the request DPI, and recognizes through a request-local native API instance

Words retain native reading order, validated UTF-8 Unicode text, top-left pixel bounds, and confidence scaled from 0 through 100 into 0 through 1; supplementary characters consume two UTF-16 units

Available word baselines are passed through with both endpoints; when a baseline is unavailable, the existing text-layer geometry fallback applies

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 return False, clear all partial words, and populate the diagnostic

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

Limits and cancellation

Input dimensions must each be at most 32,767 pixels and fit MaxPixels; recognized text must fit the request's MaxTextCodeUnits budget and the adapter's 1,048,576 UTF-16 unit limit, and word count must fit MaxWords

The adapter checks cancellation and elapsed time during bitmap conversion and result iteration, and supplies a native monitor with the remaining deadline and a cancellation callback during recognition

Native cancellation is cooperative: Tesseract's monitor covers word recognition and does not interrupt every initialization or layout-analysis step; these calls may finish before a requested cancellation or expired deadline is reported

Pixel and output budgets do not impose a hard limit on the native library's model or recognition memory use; use the process adapter when the application needs a separately terminable worker

ApplyLoadedOCRTextLayer validates all results and publishes every selected page atomically, so an adapter failure leaves the loaded document unchanged

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 recognized words, and clears all results if malformed output follows an otherwise valid word

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