1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Pluggable OCR backend trait and error types.
//!
//! Provides [`OcrBackend`] — an abstraction over OCR engines.
//!
//! Supported user-facing OCR is currently limited to:
//! - `ocr-tesseract` — system Tesseract via `tesseract-rs`.
//!
//! Experimental scaffolding is kept separate and is not exposed as a supported
//! CLI backend:
//! - `ocr-onnx` — generic tract/CTC helper with no stable model contract yet.
//! - `ocr-neural` — placeholder Candle backend; `load()` returns a clear
//! unsupported-backend error until a concrete model implementation lands.
//!
//! [`OcrBackend`]: crate::ocr::OcrBackend
use crate::pixmap::Pixmap;
use crate::text::TextLayer;
/// Error type for OCR operations.
#[derive(Debug, thiserror::Error)]
pub enum OcrError {
/// The OCR engine failed to initialize.
#[error("OCR init failed: {0}")]
InitFailed(String),
/// Recognition failed on a page image.
#[error("OCR recognition failed: {0}")]
RecognitionFailed(String),
/// The specified language or model is not available.
#[error("OCR model/language not found: {0}")]
ModelNotFound(String),
/// I/O error (e.g. loading model file).
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
}
/// Configuration for an OCR run.
#[derive(Debug, Clone)]
pub struct OcrOptions {
/// Languages to recognize (e.g. "eng", "rus+eng").
pub languages: String,
/// Page DPI (helps OCR engines scale internally).
pub dpi: u32,
}
impl Default for OcrOptions {
fn default() -> Self {
Self {
languages: "eng".into(),
dpi: 300,
}
}
}
/// Trait for pluggable OCR backends.
///
/// Implementations receive a rendered page pixmap and return a structured
/// text layer that can be written back into the DjVu file as a TXTz chunk.
pub trait OcrBackend {
/// Recognize text in the given page image.
///
/// Returns a [`TextLayer`] whose bounding boxes are in the pixmap's
/// coordinate system (top-left origin).
///
/// **Minimum granularity guarantee.** Callers may rely only on a populated
/// top-level [`TextLayer`]`::text` string and at least one page-level zone;
/// the richer `page -> line -> word` hierarchy is best-effort and
/// backend-dependent. The Tesseract backend produces the full hierarchy;
/// the experimental `ocr-onnx`/`ocr-neural` backends (see the module docs)
/// may emit a coarser tree or none at all. Consumers that need word-level
/// rects (e.g. the hOCR/ALTO exporters) must tolerate a flatter layer.
fn recognize(&self, pixmap: &Pixmap, options: &OcrOptions) -> Result<TextLayer, OcrError>;
}