#![cfg_attr(
feature = "img",
doc = r##"
# Usage
The most basic usage is shown below:
```rust
use image;
# fn main() -> Result<(), Box<dyn ::std::error::Error>> {
// Load on image to search, convert it to grayscale
let img = image::open("tests/data/github.gif")?.to_luma8();
// Prepare for detection
let mut img = rqrr::PreparedImage::prepare(img);
// Search for grids, without decoding
let grids = img.detect_grids();
assert_eq!(grids.len(), 1);
// Decode the grid
let (meta, content) = grids[0].decode()?;
assert_eq!(meta.ecc_level, 0);
assert_eq!(content, "https://github.com/WanzenBug/rqrr");
# Ok(())
# }
```
If you have some other form of picture storage, you can use
[`PreparedImage::prepare_from_*`](struct.PreparedImage.html). This allows
you to define your own source for images.
"##
)]
pub use self::decode::{MetaData, RawData, Version, MAX_PAYLOAD_SIZE};
pub(crate) use self::detect::{capstones_from_image, CapStone};
pub use self::identify::Point;
pub(crate) use self::identify::SkewedGridLocation;
pub use self::prepare::PreparedImage;
use std::error::Error;
use std::io::Write;
mod decode;
mod detect;
pub(crate) mod geometry;
mod identify;
mod prepare;
mod version_db;
#[derive(Debug, Clone)]
pub struct Grid<G> {
pub grid: G,
pub bounds: [Point; 4],
}
impl<G> Grid<G>
where
G: BitGrid,
{
pub fn new(grid: G) -> Self {
Grid {
grid,
bounds: [
Point { x: 0, y: 0 },
Point { x: 0, y: 0 },
Point { x: 0, y: 0 },
Point { x: 0, y: 0 },
],
}
}
pub fn decode(&self) -> DeQRResult<(MetaData, String)> {
let mut out = Vec::new();
let meta = self.decode_to(&mut out)?;
let out = String::from_utf8(out)?;
Ok((meta, out))
}
pub fn get_raw_data(&self) -> DeQRResult<(MetaData, RawData)> {
decode::get_raw(&self.grid, false)
}
pub fn decode_to<W>(&self, writer: W) -> DeQRResult<MetaData>
where
W: Write,
{
decode::decode(&self.grid, writer)
}
}
pub trait BitGrid {
fn size(&self) -> usize;
fn bit(&self, y: usize, x: usize) -> bool;
#[cfg(feature = "img")]
fn write_grid_to(&self, p: &str) {
let mut dyn_img = image::GrayImage::new(self.size() as u32, self.size() as u32);
for y in 0..self.size() {
for x in 0..self.size() {
let color = match self.bit(y, x) {
true => 0,
false => 255,
};
dyn_img.get_pixel_mut(x as u32, y as u32).0[0] = color;
}
}
dyn_img.save(p).unwrap();
}
}
pub struct MirroredGrid<'a>(&'a dyn BitGrid);
impl BitGrid for MirroredGrid<'_> {
fn size(&self) -> usize {
self.0.size()
}
fn bit(&self, y: usize, x: usize) -> bool {
self.0.bit(x, y)
}
}
#[derive(Debug, Clone)]
pub struct SimpleGrid {
cell_bitmap: Vec<u8>,
size: usize,
}
impl SimpleGrid {
pub fn from_func<F>(size: usize, fill_func: F) -> Self
where
F: Fn(usize, usize) -> bool,
{
let mut cell_bitmap = vec![0; (size * size + 7) / 8];
let mut c = 0;
for y in 0..size {
for x in 0..size {
if fill_func(x, y) {
cell_bitmap[c >> 3] |= 1 << (c & 7) as u8;
}
c += 1;
}
}
SimpleGrid { cell_bitmap, size }
}
}
impl BitGrid for SimpleGrid {
fn size(&self) -> usize {
self.size
}
fn bit(&self, y: usize, x: usize) -> bool {
let c = y * self.size + x;
self.cell_bitmap[c >> 3] & (1 << (c & 7) as u8) != 0
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DeQRError {
IoError,
DataUnderflow,
DataOverflow,
UnknownDataType,
DataEcc,
FormatEcc,
InvalidVersion,
InvalidGridSize,
EncodingError,
}
type DeQRResult<T> = Result<T, DeQRError>;
impl Error for DeQRError {}
impl From<::std::string::FromUtf8Error> for DeQRError {
fn from(_: ::std::string::FromUtf8Error) -> Self {
DeQRError::EncodingError
}
}
impl ::std::fmt::Display for DeQRError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let msg = match self {
DeQRError::IoError => "IoError(Could not write to output)",
DeQRError::DataUnderflow => "DataUnderflow(Expected more bits to decode)",
DeQRError::DataOverflow => "DataOverflow(Expected less bits to decode)",
DeQRError::UnknownDataType => "UnknownDataType(DataType not known or not implemented)",
DeQRError::DataEcc => "Ecc(Too many errors to correct)",
DeQRError::FormatEcc => "Ecc(Version information corrupt)",
DeQRError::InvalidVersion => "InvalidVersion(Invalid version or corrupt)",
DeQRError::InvalidGridSize => "InvalidGridSize(Invalid version or corrupt)",
DeQRError::EncodingError => "Encoding(Not UTF8)",
};
write!(f, "{msg}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rqrr() {
let grid = [
[
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1,
],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
],
[
1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0,
],
[
1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1,
],
[
0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
],
[
1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1,
],
[
0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1,
],
[
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1,
],
];
let img = crate::SimpleGrid::from_func(21, |x, y| grid[y][x] == 1);
let mut buf = vec![0; img.size() * img.size() / 8 + 1];
for y in 0..img.size() {
for x in 0..img.size() {
let i = y * img.size() + x;
if img.bit(y, x) {
buf[i >> 3] |= 1 << ((i & 7) as u8);
}
}
}
let mut vec = Vec::new();
crate::decode::decode(&img, &mut vec).unwrap();
assert_eq!(b"rqrr".as_ref(), &vec[..])
}
#[test]
fn test_github() {
let grid = [
[
1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1,
1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0,
1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0,
1,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1,
1,
],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0,
],
[
1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1,
0,
],
[
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0,
1,
],
[
1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1,
1,
],
[
1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1,
0,
],
[
0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1,
1,
],
[
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0,
1,
],
[
1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1,
1,
],
[
1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1,
0,
],
[
1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1,
1,
],
[
0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
1,
],
[
1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1,
1,
],
[
0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,
0,
],
[
1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
0,
],
[
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1,
1,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1,
1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0,
0,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0,
1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1,
0,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1,
1,
],
];
let img = crate::SimpleGrid::from_func(29, |x, y| grid[y][x] == 1);
let mut buf = vec![0; img.size() * img.size() / 8 + 1];
for y in 0..img.size() {
for x in 0..img.size() {
let i = y * img.size() + x;
if img.bit(y, x) {
buf[i >> 3] |= 1 << ((i & 7) as u8);
}
}
}
let mut vec = Vec::new();
crate::decode::decode(&img, &mut vec).unwrap();
assert_eq!(b"https://github.com/WanzenBug/rqrr".as_ref(), &vec[..])
}
#[test]
fn test_number() {
let grid = [
[
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1,
1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0,
1,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,
1,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1,
1,
],
[
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0,
],
[
1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0,
0,
],
[
1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0,
1,
],
[
0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1,
0,
],
[
0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
1,
],
[
0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1,
0,
],
[
0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0,
1,
],
[
0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1,
0,
],
[
1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1,
1,
],
[
0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1,
0,
],
[
1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0,
1,
],
[
1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
0,
],
[
1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0,
0,
],
[
1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
0,
],
[
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
1,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1,
0,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0,
0,
],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1,
0,
],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1,
0,
],
[
1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,
0,
],
];
let img = crate::SimpleGrid::from_func(29, |x, y| grid[y][x] == 1);
let mut buf = vec![0; img.size() * img.size() / 8 + 1];
for y in 0..img.size() {
for x in 0..img.size() {
let i = y * img.size() + x;
if img.bit(y, x) {
buf[i >> 3] |= 1 << ((i & 7) as u8);
}
}
}
let mut vec = Vec::new();
crate::decode::decode(&img, &mut vec).unwrap();
assert_eq!(b"1234567891011121314151617181920".as_ref(), &vec[..])
}
}