bardecoder/decode/qr/
decoder.rs

1use super::super::Decode;
2
3use crate::util::qr::{QRData, QRError, QRInfo};
4
5/// Decode a QR code into a resulting String
6///
7/// This decoder will, in order:
8/// * Determine QR Format information
9/// * Extract the interleaved blocks of codewords
10/// * Perform error correction
11/// * Decode the blocks into a String
12///
13/// # Optimisation
14/// The error correction process can be relatively expensive. This decoder has a fast detection of the existence of errors,
15/// allowing to bypass the correction altogether if none exist. Users of this library are encouraged to provide high quality fault-free images,
16/// speeding up the decoding process by not having to correct errors.
17pub struct QRDecoder {}
18
19impl QRDecoder {
20    /// Construct a new QRDecoder
21    pub fn new() -> QRDecoder {
22        QRDecoder {}
23    }
24}
25
26impl Decode<QRData, String, QRError> for QRDecoder {
27    fn decode(&self, data: Result<QRData, QRError>) -> Result<String, QRError> {
28        let qr_data = data?;
29
30        let format = super::format::format(&qr_data)?;
31        let blocks = super::blocks::blocks(&qr_data, &format.0, &format.1)?;
32        let block_info = super::block_info(qr_data.version, &format.0)?;
33
34        let mut all_blocks = vec![];
35
36        for (block, bi) in blocks.into_iter().zip(block_info) {
37            let corrected = super::correct::correct(block, &bi)?;
38
39            for corr in corrected.iter().take(bi.data_per as usize) {
40                all_blocks.push(*corr);
41            }
42        }
43
44        debug!("TOTAL LENGTH {}", all_blocks.len());
45
46        let data = super::data::data(all_blocks, qr_data.version)?;
47        Ok(data)
48    }
49}
50
51/// Decode a QR code into a resulting String. It also includes some information about the decoded QR Code.
52///
53/// Functions the same as QRDecoder, apart from also returning some information about the decoded QR Code.
54pub struct QRDecoderWithInfo {}
55
56impl QRDecoderWithInfo {
57    /// Construct a new QRDecoder
58    pub fn new() -> QRDecoderWithInfo {
59        QRDecoderWithInfo {}
60    }
61}
62
63impl Decode<QRData, (String, QRInfo), QRError> for QRDecoderWithInfo {
64    fn decode(&self, data: Result<QRData, QRError>) -> Result<(String, QRInfo), QRError> {
65        let qr_data = data?;
66
67        let format = super::format::format(&qr_data)?;
68        let blocks = super::blocks::blocks(&qr_data, &format.0, &format.1)?;
69        let block_info = super::block_info(qr_data.version, &format.0)?;
70
71        let mut all_blocks = vec![];
72        let mut total_errors = 0;
73
74        for (block, bi) in blocks.into_iter().zip(block_info) {
75            let (corrected, error_count) = super::correct::correct_with_error_count(block, &bi)?;
76
77            for corr in corrected.iter().take(bi.data_per as usize) {
78                all_blocks.push(*corr);
79            }
80
81            total_errors += error_count;
82        }
83
84        debug!("TOTAL LENGTH {}", all_blocks.len());
85        let total_data = (all_blocks.len() as u32) * 8;
86
87        let data = super::data::data(all_blocks, qr_data.version)?;
88        Ok((
89            data,
90            QRInfo {
91                version: qr_data.version,
92                ec_level: format.0,
93                total_data,
94                errors: total_errors,
95            },
96        ))
97    }
98}