anyd 0.1.0

From-scratch encoding and decoding of 1D and 2D barcodes with lossless round-trip and live-video detection
Documentation
# AnyDCode

A from-scratch Rust library for **decoding and encoding 1D and 2D barcodes**, aiming
for the widest possible symbology coverage while preserving every variation of a code.

## Goals

- **Lossless round-trip.** A decoded [`Symbol`] carries not just its payload but the
  exact encoding decisions β€” segmentation, version/size, error-correction level, mask.
  Feeding a decoded symbol straight back into the encoder reproduces the original
  symbol byte-for-byte.
- **Live-video ready.** A cheap per-frame *detection* pass (locate + classify) is
  separated from a heavier *analysis/decode* pass, and previous-frame hints let the
  pipeline skip re-analyzing codes it already knows.
- **Portable input.** The video boundary is a borrowed luminance buffer
  (`GrayFrame`); the caller owns capture and color conversion, so the core has no
  media dependencies.

## Status

The full symbology catalog is **modeled** in the `Symbology` enum, but
implementations land incrementally. Query `Symbology::is_implemented()` at runtime.
Legend: βœ… done Β· 🚧 in progress Β· ⬜ planned.

### 2D β€” matrix

| Symbology | Encode | Decode | Detect |
|-----------|:------:|:------:|:------:|
| QR Code (v1–40, all EC levels & masks) | βœ… | βœ… | βœ…ΒΉ |
| Data Matrix (ECC 200, square sizes, ASCII+Base256) | βœ… | βœ… | βœ…Β³ |
| Aztec (compact + full range, all modes) | βœ… | βœ… | ⬜ |
| Aztec Runes | ⬜ | ⬜ | ⬜ |
| Micro QR Code (M1–M4) | βœ… | βœ… | ⬜ |
| Rectangular Micro QR (rMQR, all 32 sizes) | βœ… | βœ… | ⬜ |
| MaxiCode (modes 2–6) | βœ… | βœ… | ⬜ |
| Han Xin · Grid Matrix · DotCode | ⬜ | ⬜ | ⬜ |

### 2D β€” stacked

| Symbology | Encode | Decode | Detect |
|-----------|:------:|:------:|:------:|
| PDF417 (Text/Byte/Numeric, EC 0–8) | βœ… | βœ… | βœ…β΄ |
| MicroPDF417 | ⬜ | ⬜ | ⬜ |
| Code 16K · Code 49 · Codablock F | ⬜ | ⬜ | ⬜ |
| GS1 DataBar Stacked / Stacked Omni / Expanded Stacked | ⬜ | ⬜ | ⬜ |

### 1D β€” linear

| Symbology | Encode | Decode | Detect |
|-----------|:------:|:------:|:------:|
| EAN-13 Β· EAN-8 Β· UPC-A Β· UPC-E | βœ… | βœ… | βœ…Β² |
| UPC/EAN add-ons: EAN-2 Β· EAN-5 | βœ… | βœ… | βœ…Β² |
| Code 128 Β· GS1-128 | βœ… | βœ… | βœ…Β² |
| Code 39 Β· Code 93 Β· Code 11 | βœ… | βœ… | βœ…Β² |
| ITF Β· Standard / IATA / Matrix 2 of 5 | βœ… | βœ… | βœ…Β² |
| Codabar Β· MSI Plessey Β· Plessey | βœ… | βœ… | βœ…Β² |
| Telepen | βœ… | βœ… | βœ…Β² |
| Pharmacode (1- & 2-track) | βœ… | βœ… | ⬜ |
| GS1 DataBar Omni (RSS-14) Β· Limited Β· Expanded | βœ… | βœ… | ⬜ |
| DX Film Edge | ⬜ | ⬜ | ⬜ |

### Postal (height-modulated)

| Symbology | Encode | Decode | Detect |
|-----------|:------:|:------:|:------:|
| POSTNET Β· PLANET Β· Intelligent Mail (IMb) | βœ… | βœ… | ⬜ |
| Royal Mail (RM4SCC) Β· Dutch KIX | βœ… | βœ… | ⬜ |
| Mailmark · Australia Post · Japan Post | ⬜ | ⬜ | ⬜ |

ΒΉ QR ships a full image sampler: Otsu binarization β†’ finder-pattern detection β†’
perspective recovery (via the bottom-right alignment pattern) β†’ sub-pixel grid
sampling β†’ decode. Robust to any-angle rotation, moderate tilt, blur and noise
(envelope documented in `tests/harness_image.rs`).

Β² 1D detection is the shared **`scan1d`** luminance front-end (edge detection β†’
run-length β†’ normalized `LinearPattern`), feeding each symbology's decoder. The
end-to-end pixel→symbol path is verified for Code 128, Code 39 and EAN-13 in
`tests/scan1d_pipeline.rs`; it applies to any standard bar/space linear code.
DataBar (finder-pattern based) and Pharmacode need dedicated samplers.

Β³ Data Matrix ships an image sampler: Otsu binarization β†’ largest-component isolation
β†’ solid-L finder + timing-edge line fitting β†’ perspective corners β†’ `imgproc` grid
sampling, with symbol size and grid chirality confirmed by Reed–Solomon. Robust to
any-angle rotation, scale, blur/noise and (size-graded) tilt; envelope in
`tests/datamatrix_image.rs`.

⁴ PDF417 (finder-less) is located by its start/stop guard columns β†’ RANSAC edge fit β†’
affine grid sampling β†’ RS-corrected decode. Handles upright, rotation ≀±10Β°, scale,
blur and noise; perspective keystoning is out of scope (no interior anchor). Envelope
in `tests/pdf417_image.rs`.

> **Naming note.** GS1 DataBar was formerly "RSS": DataBar Omnidirectional = RSS-14,
> DataBar Limited = RSS Limited, DataBar Expanded = RSS Expanded. Codabar is sometimes
> called "Coda"/NW-7. These are aliases for the same `Symbology` variants above.

## Example: QR round-trip

```rust
use anyd::codes::qr::{EcLevel, QrDecoder, QrEncoder};
use anyd::traits::{Decode, Encode};

let encoder = QrEncoder::new();
let symbol = encoder.build_text("HELLO WORLD", EcLevel::Q).unwrap();
let encoding = encoder.encode(&symbol).unwrap();

let decoded = QrDecoder::new().decode(&encoding).unwrap();
assert_eq!(decoded.text().as_deref(), Some("HELLO WORLD"));
// Re-encoding the decoded symbol yields the identical matrix.
assert_eq!(encoder.encode(&decoded).unwrap(), encoding);
```

## Command-line tool (`anyd`)

An optional binary is bundled behind the **`cli`** feature, so the library itself
stays dependency-free. It reads/writes PNG via `oxideav-png` (with default features
off β€” no codec-registry dependency) and can also emit Unicode (for the terminal) or
SVG (raw XML).

```console
$ cargo build --release --features cli      # builds target/release/anyd

# Encode β†’ PNG / SVG / terminal
$ anyd encode qr "https://example.com" --format png --out qr.png --scale 8
$ anyd encode ean13 5901234123457 --format svg --out barcode.svg
$ anyd encode qr "HELLO" --format unicode          # half-block art in the terminal

# Decode a PNG (tries QR, Data Matrix, PDF417, and the 1D front-end)
$ anyd decode qr.png
QR Code: https://example.com

$ anyd list                                        # encodable symbology names
```

Options: `--format png|unicode|svg`, `--out FILE`, `--scale N` (px/module),
`--ec L|M|Q|H` (QR/Micro QR) or `--ec 0-8` (PDF417), `--invert` (terminal colours).

## Architecture

```
Symbol  ─── the lossless currency: segments + symbology-specific meta
  β”‚
  β”œβ”€ Encode ──▢ Encoding (BitMatrix for 2D, LinearPattern for 1D)
  └─ Decode ◀── Encoding

Image pipeline (pixels β†’ symbol):
  GrayFrame ─▢ [ imgproc: binarize Β· homography Β· grid-sample ]  ─▢ BitMatrix ─▢ Decode   (2D)
  GrayFrame ─▢ [ scan1d: edge-detect Β· run-length Β· quantize   ]  ─▢ LinearPattern ─▢ Decode (1D)

Live video:  GrayFrame ──▢ Detect ──▢ Candidate ──▢ Analyze ──▢ Symbol
                              β–²                          β”‚
                              └────── Hints β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  (skip known codes)
```

Supporting modules: **`imgproc`** (Otsu/adaptive binarization, connected components,
4-point homography, sub-pixel grid sampling β€” the 2D sampler toolkit), **`scan1d`**
(generic 1D luminance front-end), **`render`** (Encoding β†’ grayscale) and
**`transform`** (rotation/perspective/blur/noise) for the test harness.

Correctness is anchored to independent reference vectors, not self-consistency: the
ISO/IEC 18004 QR example, the ISO/IEC 16022 Data Matrix example, ISO/IEC 15438 +
ZXing vectors for PDF417, BWIPP-rendered patterns for DataBar, and documented
check-digit/pattern references for the 1D codes — plus exhaustive encode→decode→
re-encode identity tests, and full image-pipeline tests (encode β†’ render β†’ transform
β†’ sample β†’ decode) for QR and the 1D front-end.

## License

MIT © Karpelès Lab Inc.