Yomu

pub package license analyze codecov

Pure Dart QR Code & Barcode Reader Library

Yomu is a zero-dependency pure Dart implementation of a QR code and barcode reader library. It works in any Dart environment including Flutter, Dart CLI applications, and server-side Dart.

✨ Why Yomu?

  • πŸ“¦ Zero Dependencies: No external package dependencies. Keep your app's dependency graph clean.
  • 🎯 Pure Dart: No C++/Native code. Works instantly on Web (Wasm/JS), Desktop, and Mobile without build issues.
  • πŸš€ High Performance: Full HD in ~4.4ms, 4K in ~9ms on M4 MacBook Air (AOT). Fast enough for real-time scanning.
  • πŸ›‘οΈ Robust & Tested: Comprehensive test coverage. Tested against hundreds of distorted, noisy, and unevenly lit images.

πŸš€ Quick Start

QR Code + All Barcodes

import 'package:yomu/yomu.dart';

void main() {
  // Create a YomuImage container
  final image = YomuImage.rgba(
    bytes: imageBytes,
    width: 300,
    height: 300,
  );

  // Decode QR codes and all barcode formats
  final result = Yomu.all.decode(image);
  print('Decoded: ${result.text}');
}

QR Code Only

// For QR code only scanning
final result = Yomu.qrOnly.decode(YomuImage.rgba(
  bytes: imageBytes,
  width: width,
  height: height,
));

πŸ“– API Reference

Yomu Class

The main entry point class.

Constructor / Static Description
Yomu.all QR codes + all barcode formats
Yomu.qrOnly QR codes only
Yomu.barcodeOnly 1D barcodes only
Yomu.realtime All formats, tryHarder off (per-frame scanning)
Yomu({enableQRCode, barcodeScanner}) Custom configuration
Method Description
decode() Decode the first QR code or barcode in an image
decodeAll() Detect and decode all QR codes in an image

Detection vs Latency (tryHarder)

decode() runs escalating retry strategies by default (tryHarder: true) when the fast path fails: corner grid search, despeckle, tolerant finder and a full-resolution retry. This significantly improves the detection rate for noisy, dirty, perspective-distorted and small codes, while successful scans pay nothing. decodeAll() applies the same strategy to multi-code sheets: detected-but-undecodable codes get the corner rescue, and a pass that finds nothing escalates to despeckle and full resolution.

The retries only cost time on images that fail the fast path (roughly +8ms on a Full HD frame without a code, AOT). Pick by use case:

  • Single images (photos, uploaded pictures): keep the default. A slower failure is better than a missed code.
  • Real-time camera streams: use Yomu.realtime (or tryHarder: false). Frames without a code fail as fast as possible; a code missed on one frame is caught on a later one.

YomuImage Class

A platform-agnostic container for image data.

Factory Description
YomuImage.rgba() Create from RGBA bytes (4 bytes/pixel)
YomuImage.bgra() Create from BGRA bytes (4 bytes/pixel)
YomuImage.grayscale() Create from grayscale bytes (1 byte/pixel)
YomuImage.yuv420() Create from Y-plane of YUV420 camera image

πŸ”§ Support Status

Supported Image Classes

Yomu targets modern capture sources: printed codes, on-screen codes, and ordinary camera scans. Instead of relying on era-specific photo corpora, the test fixtures are generated to bracket the capability boundary of each distortion axis from both sides (see scripts/generate_stress_qr.py):

Distortion axis Decodes Does not decode
Salt & pepper noise 25% 30%
Low-light (Gaussian) noise Οƒ=110 Οƒ=120
Gray dirt occlusion 30% 35%
Gaussian blur radius 5.0 radius 6.0
Perspective (top squeeze) 0.3 0.4
Perspective (side squeeze) 0.6 β€” (saturates)
JPEG artifacts quality 1 β€” (no boundary)
Specular glare full saturation β€” (EC absorbs it)
Screen moire amplitude 0.7 amplitude 0.8
Composite casual scanΒΉ blur 5.0 blur 5.5

ΒΉ Mild perspective (0.2) + lighting gradient + blur. Each component alone is well inside its single-axis boundary.

Degradations outside these definable classes β€” arbitrary surface curvature, finder patterns cut out of the frame, damage beyond the error-correction capacity β€” are out of scope; that long tail is the domain of ML-based detectors.

Encoding Modes (QR)

Mode Support
Numeric βœ…
Alphanumeric βœ…
Byte (Latin-1/UTF-8) βœ…
Kanji βœ…
ECI ❌ Not Supported

1D Barcode Support

Format Support Description
EAN-13 βœ… International retail (includes JAN)
EAN-8 βœ… Small products
UPC-A βœ… North American retail
Code 128 βœ… Logistics, high-density
Code 39 βœ… Industrial, alphanumeric
ITF βœ… Interleaved 2 of 5, logistics
Codabar βœ… Libraries, blood banks

🎯 Performance

Run the benchmark suite:

uv run scripts/benchmark_runner.py

Standard Images (≀1000px)

  • Environment: M4 MacBook Air (2024), AOT Compiled
Mode Avg Decode Time
AOT ~0.92ms
JIT ~1.30ms

Large Images (Fused Downsampling)

Images >1MP are automatically processed with a fused conversion step for optimal performance.

Resolution Avg Decode Time
4K (3840Γ—2160) ~9.0ms
Full HD (1920Γ—1080) ~4.4ms

License

MIT License - see LICENSE for details.

Libraries

yomu
Yomu - Pure Dart QR Code and Barcode Reader Library