Tesseract OCR for OpenHarmony / HarmonyOS
This directory ports the upstream Tesseract OCR engine (libtesseract) and its
dependency chain to OpenHarmony (OHOS), and ships a DevEco Studio demo app
that performs on-device OCR through a NAPI bridge.
The Tesseract C++ sources are unmodified — the whole port is done through the OpenHarmony NDK toolchain plus the build glue in this folder.
ohos/
├── scripts/
│ ├── env.sh # locates the OHOS NDK, sets arch/triple/clang/sysroot
│ ├── fetch-sources.sh # downloads zlib / libjpeg-turbo / libpng / leptonica
│ ├── build-deps.sh # cross-compiles the dependency chain (static, PIC)
│ ├── build-tesseract.sh # cross-compiles libtesseract.a + installs headers
│ └── build-all.sh # one-shot: fetch + deps + tesseract
├── prebuilt/<arch>/ # OUTPUT: { include/, lib/*.a } — the OCR SDK (gitignored)
└── demo/TessOcrDemo/ # DevEco Studio app that calls the engine via NAPI
1. Prerequisites
- macOS / Linux with the OpenHarmony Native NDK installed
(this port was built against API 21 / native 6.0.1.112, clang-15).
The scripts auto-detect it from
HOS_SDK_HOME,OHOS_NATIVE_HOME, or the DevEco Studio bundle. cmake(≥ 3.16) andninjaonPATH.
2. Build the engine
cd ohos
# default target is arm64-v8a (real devices)
bash scripts/build-all.sh
# or for the emulator:
OHOS_ARCH=x86_64 bash scripts/build-all.sh
Result in ohos/prebuilt/arm64-v8a/:
| Library | Purpose |
|---|---|
libtesseract.a |
OCR engine |
libleptonica.a |
image I/O used by Tesseract |
libpng16.a, libjpeg.a, libz.a |
image codecs |
All objects are aarch64-linux-ohos ELF, position-independent, ready to be
linked into an OHOS native module (.so).
3. Dependency chain
zlib ──► libpng ─┐
libjpeg-turbo ───┼─► leptonica ──► libtesseract
┘
TIFF/WEBP/GIF/OpenJPEG, the training tools (ICU/Pango/Cairo), libcurl and
libarchive are disabled — none are needed for on-device recognition, which
keeps the cross-build self-contained. PNG + JPEG cover the common image inputs;
re-enable TIFF by building libtiff first and flipping ENABLE_TIFF/DISABLE_TIFF.
4. What the port had to handle
The engine is portable C++17; OHOS uses a clang + musl + CMake toolchain very close to the Android NDK that Tesseract already supports. The only friction was in the build, not the code:
CMAKE_SYSTEM_NAME=OHOS— the toolchain setsUNIX=TRUE, so Tesseract's generic Unix path is used (and the Android-onlyCpuFeaturesNdkCompatdependency is skipped).- SIMD — on
__aarch64__, NEON is always-on at compile time, so no runtimegetauxval/android_getCpuFamilyprobing is required. - libpng cross-build — its
pnglibconfgenerator invokes clang directly and drops the toolchain target, so the per-arch musl include dir is re-injected (seebuild-deps.sh). - Leptonica TIFF probe — Tesseract runs a
try_run()to detect TIFF in Leptonica, which is illegal when cross-compiling; pre-seedingLEPT_TIFF_RESULT=1skips it (seebuild-tesseract.sh).
5. Demo app
See demo/TessOcrDemo/README.md. It loads a
bundled sample image + eng.traineddata, runs OCR off the UI thread via a
Promise-returning NAPI call, and shows the recognized text.