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
| Field | Default | Meaning |
|---|---|---|
DetectionModel | ch_PP-OCRv3_det_infer.onnx | DB detection model |
RecognitionModel | ch_PP-OCRv3_rec_infer.onnx | Any compatible PP-OCRv3 or PP-OCRv4 CTC recognition model |
ClassificationModel | ch_ppocr_mobile_v2.0_cls_infer.onnx | Optional text orientation model |
CharacterDictionary | ppocr_keys_v1.txt | A UTF-8 dictionary with no BOM, ordered as the model expects |
UseAngleClassifier | True | When disabled, no classification model is required or initialised |
RightToLeft | False | Sequence detected boxes right to left within horizontal rows; the Arabic preset turns this on |
Threads | 1 | ONNX CPU thread count, 1 to 64, capped at the logical processor count |
MaxPixels | 16777216 | Input pixel limit, 1 to 67,108,864 |
TimeoutMilliseconds | 60000 | Cooperative 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 directory | Languages | Common accepted aliases |
|---|---|---|
ch | Simplified Chinese and English | zh, zh-CN, zh-Hans, chi_sim |
chinese_cht | Traditional Chinese | zh-TW, zh-HK, zh-Hant, chi_tra |
en | English | en, en-US, en-GB, eng |
latin | French, German, Spanish, Portuguese, Italian, Dutch and Turkish | fr, de, es, pt-BR, it, nl, tr |
japan | Japanese | ja, ja-JP, jpn |
korean | Korean | ko, ko-KR, kor |
cyrillic | Russian, Ukrainian, Bulgarian and Belarusian | ru, ru-RU, rus, uk, bg, be |
arabic | Arabic, Persian and Urdu | ar, fa, ur, ara, fas, urd |
devanagari | Hindi, Marathi and Nepali | hi, 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