ocr 0.1.0

A minimalist OCR library for Rust — from scratch, no external engine
Documentation
# ARCHITECTURE

## Overview

The `ocr` crate implements OCR **without Tesseract or any external OCR binary**. The pipeline is deterministic template matching over a built-in 5×7 bitmap font.

```
┌─────────────────────────────────────────────────────────┐
│                     ocr (library)                       │
│  ┌─────────┐ ┌───────────┐ ┌─────────┐ ┌────────────┐  │
│  │ engine  │ │ preprocess│ │ segment │ │ recognize  │  │
│  │ (orche-  │ │ (otsu     │ │ (lines, │ │ (template  │  │
│  │  strate) │ │  binarize)│ │  chars) │ │  matching) │  │
│  └─────────┘ └───────────┘ └─────────┘ └─────┬──────┘  │
│         ┌──────────────────────────────────────┘       │
│         │  font (glyphs), types, error                  │
└─────────┴──────────────────────────────────────────────┘
              │                    │
     ┌────────▼────────┐   ┌───────▼────────┐
     │  ocr (binary)   │   │  ocr-mcp      │
     │  clap CLI       │   │  rmcp server  │
     └─────────────────┘   └───────────────┘
```

## Crate structure

### Library (`ocr`)

Core logic lives in modules under `src/`. The crate does not shell out to external OCR tools.

| Module       | Responsibility |
|-------------|----------------|
| `engine`    | `OcrEngine`: load image, optional preprocess, run binarize → segment → recognize per line |
| `preprocess`| Grayscale, Otsu binarization, optional `preprocess` shortcut, small-component noise cleanup |
| `segment`   | Horizontal projection (lines), vertical projection (character columns), gap stats for spaces |
| `recognize` | Normalize character crops to 5×7, score against glyph templates, small disambiguation rules |
| `font`      | Glyph bitmap definitions and supported character set |
| `render`    | Text → synthetic grayscale test images (used by tests and examples) |
| `types`     | `OcrResult`, `OcrWord`, `BoundingBox` |
| `error`     | `Error` enum (`thiserror`) |

### Binaries

| Target     | Role |
|-----------|------|
| `ocr`     | Thin CLI: open file, call engine, print text or JSON |
| `ocr-mcp` | MCP server: `ocr_image`, `ocr_base64` tools via rmcp (stdio) |

## Data flow

```
Image (path / bytes / memory)
  Optional preprocessing (grayscale + fixed threshold)
  Binarize (Otsu) → boolean grid
  Clean tiny connected components (noise)
  find_lines (horizontal projection; merge thin vertical gaps for i/j-style glyphs)
  Per line: find_chars (vertical projection) → gaps → insert word spaces (median-based threshold)
  Per segment: crop patch, normalize to template size, best template + targeted corrections (e.g. 3/j, x/k, '/t)
  OcrResult { text, words, confidence }
```

## Design decisions

1.  **No subprocess / FFI OCR** - Keeps installs simple (no system Tesseract), reproducible behavior, and a fully Rust dependency graph for the recognition core.

2.  **Template matching** - Fast and adequate for the bundled monospace-style font and test images; not a substitute for ML OCR on arbitrary fonts or handwriting.

3.  **Builder-style `OcrEngine`** - `.language` is reserved for future use; recognition today is driven by the fixed glyph set (English-oriented).

4.  **MCP errors as strings** - Tools return human-readable error lines so all clients can surface failures without relying on MCP error object support.

## Future expansion (see TODO.md)

- Richer glyph / language support
- Stronger segmentation or learned matchers
- Optional HTTP transport for MCP
- PDF and batch workflows