quircs
Pure-Rust QR code detection and scanning, ported from the C quirc library.
Repository Health
Technical Analysis
quircs is a pure-Rust library for detecting and decoding QR codes in images, ported from the well-known C library quirc. Given a grayscale image buffer it identifies candidate QR codes, extracts them, and decodes their payloads, all without any C dependencies. It pairs naturally with the Rust image crate for loading and converting pictures before scanning.
What You Get
- A
Quircdecoder that identifies QR codes in a grayscale image buffer - An iterator over detected codes, each of which can be extracted and decoded
- Decoded payload bytes recovered from each successfully read QR code
- A pure-Rust implementation with no C dependencies, faithful to the quirc algorithm
Common Use Cases
- Reading QR codes from photos or uploaded images in a Rust service
- Batch-scanning image sets for embedded QR payloads
- Adding QR detection to desktop or CLI image tools
Under The Hood
Architecture — The decode path splits cleanly across modules: identify.rs locates finder patterns and candidate QR grids in the image, quirc.rs holds the Quirc decoder state and the identify entry point, decode.rs reads the extracted grid into payload bytes, version_db.rs carries the QR version parameter tables, and error.rs models failures. This mirrors the structure of the original quirc C library.
Tech Stack — Rust 2018 edition (rust-version 1.68). Runtime dependencies are minimal — num-derive and num-traits for numeric enums and thiserror for errors — while the image crate is a dev-dependency used by examples and tests to load pictures. The crate builds as both an rlib and a staticlib.
Code Quality — The repo includes a tests/ directory with sample data and profiling artifacts (identify.prof, extract.prof), indicating attention to correctness and performance. Being a direct port keeps the algorithm aligned with a battle-tested reference implementation.
API Design — The three-step flow — construct Quirc, identify(width, height, &luma), then decode() per code — is small and predictable. Taking a raw luma buffer keeps the library decoupled from any particular image loader while still pairing smoothly with the image crate shown in the README.