1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//! Find and read QR-Codes
//!
//! This crates exports functions and types that can be used to search for QR-Codes in images and
//! decode them.
//!
//!
//! # Usage
//! The most basic usage is shown below:
//!
//! ```rust
//! use image;
//! use rqrr;
//!
//! let img = image::open("tests/data/github.gif").unwrap();
//! let codes = rqrr::find_and_decode_from_image(&img);
//! assert_eq!(codes.len(), 1);
//! assert_eq!(codes[0].val, "https://github.com/WanzenBug/rqrr");
//! ```
//!
//! If you have some other form of picture storage, you can use [`find_and_decode_from_func`]().
//! This allows you define your own source for images.

#[cfg(feature = "img")]
use image;

pub use self::decode::{decode, MetaData, Version};
pub use self::identify::{CapStone, capstones_from_image, find_groupings, Point, SearchableImage, SkewedGridLocation};

mod decode;
mod identify;
mod version_db;

/// A grid that contains exactly one QR code square.
///
/// The common trait for everything that can be decoded as a QR code. Given a normal image, we first
/// need to find the QR grids in it. See [capstones_from_image](fn.find_capstones_from_image.html),
/// [find_groupings](fn.find_groupings.html) and
/// [SkewedGridLocation](struct.SkewedGridLocation.html).
///
/// This trait can be implemented when some object is known to be exactly the bit-pattern
/// of a QR code.
pub trait Grid {
    /// Return the size of the grid.
    ///
    /// Since QR codes are always squares, the grid is assumed to be size * size.
    fn size(&self) -> usize;

    /// Return the value of the bit at the given location.
    ///
    /// `true` means 'black', `false` means 'white'
    fn bit(&self, y: usize, x: usize) -> bool;
}

/// A basic GridImage that can be generated from a given function.
///
/// # Example
///
/// ```rust
/// use 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 = rqrr::SimpleGrid::from_func(21, |x, y| {
///     grid[y][x] == 1
/// });
/// let mut result = Vec::new();
/// rqrr::decode(&img, &mut result).unwrap();
/// assert_eq!(b"rqrr".as_ref(), &result[..])
/// ```
#[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 Grid 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
    }
}


/// The decoded content of a QR-Code
///
/// The member `val` stores the decoded value of a QR-Code.
/// The member `meta` stores [MetaData](struct.MetaData.html) (Version number, ECC-Level, etc)
/// The member `position` stores the 4 'corners' of the QR code, in image coordinates.
#[derive(Debug)]
pub struct Code {
    pub meta: MetaData,
    pub val: String,
    pub position: [Point; 4],
}


/// Given a image object, locate all codes found in it
///
/// This is a convenient wrapper if you use the `image` crate already. The only requirement
/// for the image is that the 'black' parts of a QR code are 'dark', 'white' parts 'bright'.
///
/// # Example
/// ```rust
/// use image;
/// use rqrr;
///
/// let img = image::open("tests/data/github.gif").unwrap();
/// let codes = rqrr::find_and_decode_from_image(&img);
/// assert_eq!(codes.len(), 1);
/// assert_eq!(codes[0].val, "https://github.com/WanzenBug/rqrr");
/// ```
#[cfg(feature = "img")]
pub fn find_and_decode_from_image(img: &image::DynamicImage) -> Vec<Code> {
    let img = img.to_luma();
    let w = img.width() as usize;
    let h = img.height() as usize;

    find_and_decode_from_func(w, h, |x, y| {
        img.get_pixel(x as u32, y as u32).data[0]
    })
}

/// Find QR-Codes and decode them
///
/// This method expects to be given an image of dimension `width` * `height`. The data is supplied
/// via the `fill` function. The fill function will be called width coordinates `x, y`, where `x`
/// ranges from 0 to `width` and `y` from 0 to `height`. The return value is expected to correspond
/// with the greyscale value of the image to decode, 0 being black, 255 being white.
///
/// # Returns
///
/// Returns a collection of all QR-Codes that have been found. They are already decoded and contain
/// some extra metadata like position in the image as well as information about the used QR code
/// itself
///
/// # Panics
///
/// Panics if `width * height` would overflow.
///
/// # Examples
///
/// ```
/// use image;
/// use rqrr;
///
/// let img = image::open("tests/data/github.gif").unwrap().to_luma();
/// let w = img.width() as usize;
/// let h = img.height() as usize;
/// let codes = rqrr::find_and_decode_from_func(w, h, |x, y|  img.get_pixel(x as u32, y as u32).data[0]);
/// assert_eq!(codes.len(), 1);
/// assert_eq!(codes[0].val, "https://github.com/WanzenBug/rqrr");
/// ```
pub fn find_and_decode_from_func<F>(width: usize, height: usize, fill: F) -> Vec<Code> where F: FnMut(usize, usize) -> u8 {
    let mut img = SearchableImage::from_greyscale(width, height, fill);
    let caps = capstones_from_image(&mut img);
    let groups = find_groupings(caps);
    let grids: Vec<_> = groups.into_iter()
        .filter_map(|group| SkewedGridLocation::from_group(&mut img, group))
        .collect();
    let mut ret = Vec::new();
    for grid in grids {
        let mut decode_val = Vec::new();
        let position = [
            grid.c.map(0.0, 0.0),
            grid.c.map(grid.grid_size as f64 + 1.0, 0.0),
            grid.c.map(grid.grid_size as f64 + 1.0, grid.grid_size as f64 + 1.0),
            grid.c.map(0.0, grid.grid_size as f64 + 1.0),
        ];

        let grid_img = grid.into_grid_image(&img);
        let meta = match decode::decode(&grid_img, &mut decode_val) {
            Ok(x) => x,
            Err(_) => continue,
        };

        let val = match String::from_utf8(decode_val) {
            Ok(x) => x,
            Err(_) => continue,
        };

        ret.push(Code {
            meta,
            val,
            position,
        })
    }

    ret
}

/// Possible errors that can happen during decoding
#[derive(Debug)]
pub enum DeQRError {
    /// Could not write the output to the output stream/string
    IoError,
    /// Expected more bits to decode
    DataUnderflow,
    /// Expected less bits to decode
    DataOverflow,
    /// Unknown data type in encoding
    UnknownDataType,
    /// Could not correct errors / code corrupt
    DataEcc,
    /// Could not read format information from both locations
    FormatEcc,
    /// Unsupported / non-existent version read
    InvalidVersion,
    /// Unsupported / non-existent grid size read
    InvalidGridSize,
}

pub type DeQRResult<T> = Result<T, DeQRError>;