Home

Awesome

Bardecoder

Detect and decode QR Codes, written in 100% Rust.

Github Actions License Crates.io docs.rs Rustc version

Background

This library came about after perusing the Not Yet Awesome Rust list. It strives to be modular so algorithms with different strengths, speeds and robustness can be used interchangeably.

How to use

Add the following to your Cargo.toml:

[dependencies]
bardecoder = "0.5.0"
image = "0.24"

You can also use image version 0.24 but some changes in that library seem to have degraded performance of bardecoder every so slightly.

Quick

The quickest way to integrate is to use the built-in default decoder. This will work for the vast majority of cases, though please keep in mind the Tips below.

fn main() {
    let img = image::open("<<image location>>").unwrap();

    // Use default decoder
    let decoder = bardecoder::default_decoder();

    let results = decoder.decode(&img);
    for result in results {
        println!("{}", result.unwrap());
    }
}

Modified

If you want a little customizability, you can start with the default builder instead. It will be pre-populated with the default components but you are free to replace any of them with modified parameters.

use bardecoder;
use bardecoder::prepare::BlockedMean;

use image;

fn main() {
    let img = image::open("<<image location>>").unwrap();

    // Use default decoder builder
    let mut db = bardecoder::default_builder();

    // Use some different arguments in one of the default components
    db.prepare(Box::new(BlockedMean::new(7, 9)));

    // Build the actual decoder
    let decoder = db.build();

    let results = decoder.decode(&img);
    for result in results {
        println!("{}", result.unwrap());
    }
}

You can also start with a completely empty builder but be aware that the build() function will Panic! if any of the components are missing.

use bardecoder::DecoderBuilder;

let mut decoder_builder = DecoderBuilder::new();

Advanced

If you want to go absolutely nuts, you can also provide your own implementations for the various components. Use at your own risk!

use bardecoder;
use bardecoder::prepare::BlockedMean;
use bardecoder::detect::{Detect, Location};

use image;
use image::GrayImage;

struct MyDetector {}

impl MyDetector {
    pub fn new() -> MyDetector {
        MyDetector {}
    }
}

impl Detect<GrayImage> for MyDetector {
    fn detect(&self, prepared: &GrayImage) -> Vec<Location> {
        vec![]
    }
}

fn main() {
    let img = image::open("<<image location>>").unwrap();

    // Use default decoder builder
    let mut db = bardecoder::default_builder();

    // Use some different arguments in one of the default components
    db.prepare(Box::new(BlockedMean::new(7, 9)));

    // Use your homemade Detector!
    db.detect(Box::new(MyDetector::new()));

    // Build the actual decoder
    let decoder = db.build();

    let results = decoder.decode(&img);
    for result in results {
        println!("{}", result.unwrap());
    }
}

Tips

Though this library can handle all sorts of QR images, here are some tips for optimal results:

Features

Bardecoder exposes the following features for use in your project:

Support

If you find an image with a QR code that this library is unable to decode, please raise an Issue. Please include the image and the code you are trying to decode it with (especially when using the Modified method). I will try my best improve the algorithm though I cannot 100% guarantee that I will succeed, especially with more esoteric QR codes.

Contributing

If you find a small bug and manage to fix it yourself, please feel free to submit a pull request. For larger refactorings and more fundamental issues please submit a ticket outlining the problem and potential solution.