RapidOCR Native DLL Adapter

HPDFRapidOCRRecognition exposes an in-process IHPDFOCREngine backed by HotPDFRapidOCR.dll, offering the same public API across Delphi, C++Builder and Windows FPC/Lazarus Win32 and Win64 builds

The DLL runs CPU ONNX inference straight off memory snapshots and holds the initialised models until the engine interface is released; deploying it at run time means shipping the matching native DLL plus compatible local models and dictionary

The existing Python process adapter stays available with its original factory overloads

Factory and options

function HPDFCreateRapidOCRDLLOCREngine(const LibraryPath,
  ModelDirectory: string): IHPDFOCREngine; overload;
function HPDFCreateRapidOCRDLLOCREngine(const LibraryPath,
  ModelDirectory: string; const Options: THPDFRapidOCRDLLOptions): IHPDFOCREngine; overload;

THPDFRapidOCRDLLOptions = record
  DetectionModel: string;
  RecognitionModel: string;
  ClassificationModel: string;
  CharacterDictionary: string;
  UseAngleClassifier: Boolean;
  RightToLeft: Boolean;
  Threads: Integer;
  MaxPixels: Integer;
  TimeoutMilliseconds: Cardinal;
  class function Default: THPDFRapidOCRDLLOptions; static;
  class function ForLanguage(const Language: string): THPDFRapidOCRDLLOptions; static;
end;

Set your starting point with THPDFRapidOCRDLLOptions.Default; the defaults reference the following local files

FieldDefaultMeaning
DetectionModelch_PP-OCRv3_det_infer.onnxDB detection model
RecognitionModelch_PP-OCRv3_rec_infer.onnxAny compatible PP-OCRv3 or PP-OCRv4 CTC recognition model
ClassificationModelch_ppocr_mobile_v2.0_cls_infer.onnxOptional text orientation model
CharacterDictionaryppocr_keys_v1.txtA UTF-8 dictionary with no BOM, ordered as the model expects
UseAngleClassifierTrueWhen disabled, no classification model is required or initialised
RightToLeftFalseSequence detected boxes right to left within horizontal rows; the Arabic preset turns this on
Threads1ONNX CPU thread count, 1 to 64, capped at the logical processor count
MaxPixels16777216Input pixel limit, 1 to 67,108,864
TimeoutMilliseconds60000Cooperative recognition deadline, 1 to 3,600,000 milliseconds

Relative filenames are resolved against ModelDirectory; absolute paths may pick out separately provisioned files

The factory checks file availability, options, required exports and the ABI version before initialising any model; invalid configuration raises EArgumentException, whilst model loading failures raise EInvalidOperation carrying a native diagnostic

Model initialisation happens in the factory and sits outside the recognition deadline; the dictionary's class count must match the recognition model, and matching class counts on their own prove nothing about character order or preprocessing compatibility

The supplied pipeline runs DB detection with a maximum detection side of 1,024 pixels and 50 pixels of white padding; the recogniser takes compatible NCHW models with a fixed input height of 32 or 48, using 48 where the height is dynamic

Recognition keeps the aspect ratio for dynamic-width models and normalises padded inputs to a minimum width of 320; a fixed-width model caps the resized crop width, which can squeeze a long text line

Angle classification preserves crop aspect ratio within its model input width and fills unused pixels with normalised zeroes; a crop rotates by 180 degrees only when the upside-down score exceeds 0.9, preventing weak direction predictions from flipping short text

The dictionary has to match the model's character order and output class count; CRLF line endings in the dictionary are fine, but a UTF-8 BOM is refused

Where the model embeds character metadata, the factory also checks every dictionary entry and its ordering; a size match on its own will not do

Chinese, Russian, and common languages

THPDFRapidOCRDLLOptions.ForLanguage picks a recognition model and matching dictionary beneath the local model directory whilst keeping the shared detector, classifier, thread, pixel and timeout defaults

The method takes case-insensitive language aliases, converts underscores to hyphens and trims surrounding whitespace; an empty or unsupported tag raises EArgumentException before any model is loaded

Profile directoryLanguagesCommon accepted aliases
chSimplified Chinese and Englishzh, zh-CN, zh-Hans, chi_sim
chinese_chtTraditional Chinesezh-TW, zh-HK, zh-Hant, chi_tra
enEnglishen, en-US, en-GB, eng
latinFrench, German, Spanish, Portuguese, Italian, Dutch and Turkishfr, de, es, pt-BR, it, nl, tr
japanJapaneseja, ja-JP, jpn
koreanKoreanko, ko-KR, kor
cyrillicRussian, Ukrainian, Bulgarian and Belarusianru, ru-RU, rus, uk, bg, be
arabicArabic, Persian and Urduar, fa, ur, ara, fas, urd
devanagariHindi, Marathi and Nepalihi, mr, ne, hin, mar, nep

Every profile uses <profile>/recognition.onnx and <profile>/dictionary.txt; profile names are accepted as given, and the regional aliases on offer are defined explicitly rather than guessed from an arbitrary prefix

Install the model sets you need before deployment using the SHA256-pinned provisioning helper

& tools/Install-RapidOCRModels.ps1 `
  -Destination C:/OCR/models `
  -Language ch,chinese_cht,en,latin,japan,korean,cyrillic,arabic,devanagari

-Language All installs every one of the nine profiles; -SkipClassifier leaves out the optional classifier, in which case set UseAngleClassifier := False when creating the engine

The helper verifies pinned SHA256 hashes and installs a shared multilingual detector and classifier under the root filenames Default expects; recognition runs offline and never downloads a missing model of its own accord

Choose the engine language per page or per region; a single engine neither detects the language automatically nor combines separate recognisers across scripts

The pinned packages carry compatible PP-OCRv3 and PP-OCRv4 models; accuracy depends on model, font, resolution and crop, and the Latin model can mix up accents such as ñ even on clean input

Newer PP-OCRv5 models may demand a newer ONNX Runtime than the static libraries the DLL was built against; an unsupported model format fails during initialisation with a diagnostic

Detection models must accept a single float32 image tensor and produce a float32 probability map with shape [1, 1, H, W] at the resized input resolution; incompatible types, dimensions, non-finite values, or probabilities outside [0, 1] by more than four float32 machine epsilons fail with a diagnostic before detection results are used

Tiny sigmoid rounding errors within that tolerance are clamped to [0, 1] before thresholding and contour scoring so valid models can retain their normal detection behaviour

Chinese example

uses SysUtils, HPDFDoc, HPDFRapidOCRRecognition;

procedure AddNativeRapidOCRText(PDF: THotPDF);
var
  Engine: IHPDFOCREngine;
  Models: THPDFRapidOCRDLLOptions;
  Layer: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  Models := THPDFRapidOCRDLLOptions.ForLanguage('zh-CN');
  Models.UseAngleClassifier := False;
  Engine := HPDFCreateRapidOCRDLLOCREngine(
    'C:\OCR\Win64\HotPDFRapidOCR.dll', 'C:\OCR\models', Models);
  Layer := THPDFOCRTextLayerOptions.Default;
  if not PDF.ApplyLoadedOCRTextLayer([0], Engine, Layer, Info) then
    raise Exception.Create('Native RapidOCR text layer was not added');
end;

Hold on to the engine interface across requests so its models get reused; pick a DLL matching the calling application's architecture and place its dependencies alongside it or in the standard Windows loader directories

Russian example

procedure AddRussianRapidOCRText(PDF: THotPDF);
var
  Engine: IHPDFOCREngine;
  Models: THPDFRapidOCRDLLOptions;
  Layer: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  Models := THPDFRapidOCRDLLOptions.ForLanguage('ru-RU');
  Engine := HPDFCreateRapidOCRDLLOCREngine(
    'C:\OCR\Win64\HotPDFRapidOCR.dll', 'C:\OCR\models', Models);
  Layer := THPDFOCRTextLayerOptions.Default;
  if not PDF.ApplyLoadedOCRTextLayer([0], Engine, Layer, Info) then
    raise Exception.Create('Russian RapidOCR text layer was not added');
end;

ru, ru-RU and rus all select the same cyrillic recognition model and dictionary

Results and lifetime

The adapter copies the current bitmap into an independent top-down BGR snapshot; dimensions and the pixel budget are checked before allocation, and the borrowed bitmap itself is never modified

The native pipeline emits one result per recognised text line, carrying original-image pixel bounds and the mean character confidence; each line takes one MaxWords slot, and no native baseline is provided

Detected boxes follow horizontal row reading order — left to right by default, right to left once RightToLeft is enabled; the Arabic preset switches this option on

Angle classification corrects individual text crops; it does not determine whole-page orientation or reorder an upside-down page's separate detection boxes into logical reading order

Recognised text stays in the model's logical Unicode order; the adapter neither reverses Arabic strings automatically nor applies bidirectional shaping

The adapter validates UTF-8, Unicode control characters, bounds, confidence and the request's MaxTextCodeUnits limit, with a hard ceiling of 1,048,576 UTF-16 units on text; supplementary characters consume two units each

An empty page succeeds with an empty result array; a failure clears partial results, and searchable PDF publication keeps the existing atomic page transaction behaviour

Calls on one engine are serialised; whilst waiting for the engine lock, cancellation and the recognition deadline are checked every 25 milliseconds

Native callbacks test cancellation and deadlines before and after detection, classification and each recognised line; a single ONNX inference call cannot be interrupted forcibly, so cancellation may only take effect once the current stage has finished

The input and text limits bound what the adapter allocates and accepts, but they set no hard cap on model, detection, crop or inference memory

Building and ABI

Native/RapidOCR holds the C++ bridge, the compatible model recogniser, a versioned C header, the export definition and the CMake project; provision compatible CPU network sources exposing DbNet, AngleNet and OcrUtils, together with matching ONNX Runtime and OpenCV libraries

Build with Windows MSVC under C++17, a Windows SDK and CMake 3.20 or later; the default build links the static release CRT, which must match the provisioned libraries

& tools/Build-HotPDFRapidOCR.ps1 `
  -NativeSourceDirectory C:/OCR/native-sources `
  -OnnxRuntimeDirectory C:/OCR/onnxruntime/windows-x64 `
  -OpenCVDirectory C:/OCR/opencv/x64/vc16/staticlib `
  -Platform Win64

OnnxRuntimeDirectory has to contain OnnxRuntimeConfig.cmake, and OpenCVDirectory must point at the architecture-specific library configuration; choose Win32 with matching x86 libraries for a 32-bit DLL

The build helper writes Lib/Native/RapidOCR/<Platform>/HotPDFRapidOCR.dll; build placement and the Visual Studio generator can be overridden through -BuildDirectory, -OutputDirectory and -Generator

The bridge catches C++ exceptions internally and exposes ABI version 1 through HPDFRapidOCRAbiVersion, HPDFRapidOCRCreate, HPDFRapidOCRRecognize and HPDFRapidOCRDestroy; all four use cdecl, 32-bit status values and explicit UTF-8 byte lengths

ABI version 1 additionally defines the optional HPDFRapidOCRSetReadingDirection export; the adapter demands it only when RightToLeft is enabled, so older DLLs keep serving left-to-right requests

Callbacks lend their text only for the duration of the call; the adapter copies validated text before returning, and the engine destructor tears down the models before unloading the DLL

Validation

With the Python onnx package and a native BUILD_TESTING build, run python tools/test_rapidocr_detector.py <build>/Release/NativeDetectorTests.exe to check valid blank output, invalid tensor ranks, channels and types, mismatched spatial dimensions, and invalid probabilities through the DLL ABI; multiple runner paths can validate both architectures in one invocation

Add -RapidOCRLanguageModelDirectory plus one or both native DLL library parameters to the Delphi or FPC adapter runner to exercise every installed preset against Chinese, Russian, Japanese, Korean, common Latin, Arabic and Hindi samples; Russian and Traditional Chinese additionally go through searchable PDF save, reload, text extraction and pixel comparison

The Delphi and FPC adapter runners cover persistent model lifetime, BGR row layout, Unicode and supplementary characters, ABI checks, invalid results, budgets, cooperative cancellation, serialised lock waiting and cleanup

Hand -RapidOCRNativeWin32Library, -RapidOCRNativeWin64Library and -RapidOCRNativeModelDirectory to Tests/Delphi/Run-TesseractRecognitionTests.ps1 or Tests/Delphi/Run-TesseractFPCRecognitionTests.ps1 for real model validation, empty pages, damaged model handling, English and Chinese recognition, and searchable PDF round trips that leave rendered pixels untouched

Turn to Searchable OCR Text Layers for page rendering, Unicode PDF text mapping, optional-content grouping and conformance constraints