Skip to content

Commit 4dec7a2

Browse files
committed
Prepare ErrorCorrector
1 parent 2a7fec3 commit 4dec7a2

File tree

4 files changed

+515
-65
lines changed

4 files changed

+515
-65
lines changed

qr-generator/src/encoder.rs

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use crate::{
2-
error_correction::CorrectionLevels, qr_errors::EncodingError, QRError, QRGenerator,
3-
QRSymbolTypes,
2+
error_correction::CorrectionLevels, qr_errors::EncodingError, sizer::Sizer, QRError,
3+
QRGenerator, QRSymbolTypes,
44
};
55
use bitvec::{prelude::*, vec::BitVec};
66
use core::iter::Peekable;
7-
use std::collections::HashMap;
87
use itertools::Itertools;
8+
use std::collections::HashMap;
99

1010
#[derive(Eq, PartialEq, Clone, Copy, PartialOrd, Debug)]
1111
pub enum EncodingModes {
@@ -77,14 +77,16 @@ impl<'a> Encoder<'a> {
7777
// EncodingModes::Byte => self.encode_byte_run(&mut input_iter),
7878
_ => unreachable!(),
7979
};
80-
self.output_data.append(&mut self.sequence_preamble(current_encoding, char_count));
80+
self.output_data
81+
.append(&mut self.sequence_preamble(current_encoding, char_count));
8182
self.output_data.append(&mut bit_run);
8283
current_encoding = next_encoding;
8384
}
8485

8586
self.output_data.append(&mut self.terminator());
86-
self.output_data.append(&mut self.padding_to_codeword_boundary());
87-
// self.output_data.append(&mut self.padding_codewords());
87+
self.output_data
88+
.append(&mut self.padding_to_codeword_boundary());
89+
self.output_data.append(&mut self.padding_codewords()?);
8890
Ok(())
8991
}
9092

@@ -247,22 +249,22 @@ impl<'a> Encoder<'a> {
247249
EncodingModes::AlphaNumeric => 1,
248250
EncodingModes::Byte => 2,
249251
EncodingModes::Kanji => 3,
250-
_ => unreachable!()
252+
_ => unreachable!(),
251253
})
252254
}
253255
sequence_preamble.append(&mut mode_indicator);
254-
},
256+
}
255257
Some(QRSymbolTypes::QRCode) => {
256258
let mut mode_indicator: BitVec<u8, Msb0> = match encoding {
257259
EncodingModes::Numeric => bitvec![u8, Msb0; 0, 0, 0, 1],
258260
EncodingModes::AlphaNumeric => bitvec![u8, Msb0; 0, 0, 1, 0],
259261
EncodingModes::Byte => bitvec![u8, Msb0; 0, 1, 0, 0],
260262
EncodingModes::Kanji => bitvec![u8, Msb0; 1, 0, 0, 0],
261-
_ => unreachable!()
263+
_ => unreachable!(),
262264
};
263265
sequence_preamble.append(&mut mode_indicator);
264-
},
265-
_ => unreachable!()
266+
}
267+
_ => unreachable!(),
266268
};
267269

268270
let len_indicator_len: usize = match self.generator.options.qr_type {
@@ -272,35 +274,20 @@ impl<'a> Encoder<'a> {
272274
EncodingModes::AlphaNumeric => 1 + self.generator.options.version.unwrap(),
273275
EncodingModes::Byte => 1 + self.generator.options.version.unwrap(),
274276
EncodingModes::Kanji => self.generator.options.version.unwrap(),
275-
_ => unreachable!()
277+
_ => unreachable!(),
276278
}) as usize
277-
},
278-
Some(QRSymbolTypes::QRCode) => {
279-
match encoding {
280-
EncodingModes::Numeric => HashMap::from([
281-
(9, 10),
282-
(26, 12),
283-
(40, 14)
284-
]),
285-
EncodingModes::AlphaNumeric => HashMap::from([
286-
(9, 9),
287-
(26, 11),
288-
(40, 13)
289-
]),
290-
EncodingModes::Byte => HashMap::from([
291-
(9, 8),
292-
(26, 16),
293-
(40, 16)
294-
]),
295-
EncodingModes::Kanji => HashMap::from([
296-
(9, 8),
297-
(26, 10),
298-
(40, 12)
299-
]),
300-
_ => unreachable!()
301-
}.get(&self.size_estimate).unwrap().clone() as usize
302-
},
303-
_ => unreachable!()
279+
}
280+
Some(QRSymbolTypes::QRCode) => match encoding {
281+
EncodingModes::Numeric => HashMap::from([(9, 10), (26, 12), (40, 14)]),
282+
EncodingModes::AlphaNumeric => HashMap::from([(9, 9), (26, 11), (40, 13)]),
283+
EncodingModes::Byte => HashMap::from([(9, 8), (26, 16), (40, 16)]),
284+
EncodingModes::Kanji => HashMap::from([(9, 8), (26, 10), (40, 12)]),
285+
_ => unreachable!(),
286+
}
287+
.get(&self.size_estimate)
288+
.unwrap()
289+
.clone() as usize,
290+
_ => unreachable!(),
304291
};
305292
let mut len_indicator = bitvec![u16, Msb0; 0; len_indicator_len];
306293
len_indicator[0..len_indicator_len].store(char_count);
@@ -311,17 +298,15 @@ impl<'a> Encoder<'a> {
311298

312299
fn terminator(&self) -> BitVec<u8, Msb0> {
313300
let terminator_len = match self.generator.options.qr_type {
314-
Some(QRSymbolTypes::MicroQRCode) => {
315-
match self.generator.options.version {
316-
Some(1) => 3,
317-
Some(2) => 5,
318-
Some(3) => 7,
319-
Some(4) => 9,
320-
_ => unreachable!()
321-
}
301+
Some(QRSymbolTypes::MicroQRCode) => match self.generator.options.version {
302+
Some(1) => 3,
303+
Some(2) => 5,
304+
Some(3) => 7,
305+
Some(4) => 9,
306+
_ => unreachable!(),
322307
},
323308
Some(QRSymbolTypes::QRCode) => 4,
324-
_ => unreachable!()
309+
_ => unreachable!(),
325310
};
326311

327312
bitvec![u8, Msb0; 0; terminator_len]
@@ -334,6 +319,36 @@ impl<'a> Encoder<'a> {
334319
bitvec![u8, Msb0; 0; pad_len]
335320
}
336321

322+
fn padding_codewords(&self) -> Result<BitVec<u8, Msb0>, EncodingError> {
323+
let total_codewords = Sizer::data_codeword_capacity(
324+
self.generator.options.qr_type.as_ref().unwrap(),
325+
self.generator.options.version.unwrap(),
326+
self.generator.options.correction_level.as_ref().unwrap(),
327+
);
328+
329+
// Allow up to 4 bits more than the data capacity - that would just indicate a complete-full M1 or M3 code
330+
if self.output_data.len() > (total_codewords * 8) + 4 {
331+
return Err(EncodingError::new("Too much data for specified code size."));
332+
}
333+
334+
let padding_amount = total_codewords - self.output_data.len() / 8;
335+
let mut padding_codewords = bitvec![u8, Msb0;];
336+
for pad in 0..padding_amount {
337+
if pad == padding_amount - 1 && self.generator.options.qr_type == Some(QRSymbolTypes::MicroQRCode) && (self.generator.options.version == Some(1) || self.generator.options.version == Some(3)) {
338+
padding_codewords.append(&mut bitvec![u8, Msb0; 0, 0, 0, 0]);
339+
}
340+
else {
341+
padding_codewords.append(&mut match pad % 2 {
342+
0 => bitvec![u8, Msb0; 1, 1, 1, 0, 1, 1, 0, 0],
343+
1 => bitvec![u8, Msb0; 0, 0, 0, 1, 0, 0, 0, 1],
344+
_ => unreachable!()
345+
});
346+
}
347+
}
348+
349+
Ok(padding_codewords)
350+
}
351+
337352
// Get a rough guess of how large a QR-code this will be. It doesn't need to be exact -
338353
// we only care about the thresholds <=9, <=26 and over. Assume we're going to use Byte
339354
// mode.
@@ -360,7 +375,7 @@ impl<'a> Encoder<'a> {
360375
self.size_estimate = match size_estimate {
361376
(0..=9) => 9,
362377
(10..=26) => 26,
363-
(27..) => 40
378+
(27..) => 40,
364379
};
365380
}
366381

@@ -736,7 +751,7 @@ mod tests {
736751
.chars()
737752
.zip(encoder.change_distances.iter())
738753
.peekable();
739-
let (_, encoded_run) = Encoder::encode_numeric_run(&mut input);
754+
let (_, encoded_run, _) = Encoder::encode_numeric_run(&mut input);
740755

741756
assert_eq!(
742757
encoded_run.as_bitslice(),

qr-generator/src/error_correction.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,57 @@
1-
#[derive(PartialEq, PartialOrd, Eq, Ord)]
1+
use crate::qr_errors::EncodingError;
2+
3+
#[derive(PartialEq, PartialOrd, Eq, Ord, Debug)]
24
pub enum CorrectionLevels {
35
DetectionOnly,
46
L,
57
M,
68
Q,
79
H,
810
}
11+
12+
pub(crate) struct ErrorCorrector {
13+
blocks: Vec<ErrorCorrectionBlock>
14+
}
15+
16+
#[derive(Clone, Debug)]
17+
struct ErrorCorrectionBlock {
18+
data_codeword_count: usize,
19+
error_correction_codeword_count: usize,
20+
data_codewords: Vec<u8>,
21+
ec_codewords: Vec<u8>
22+
}
23+
24+
impl From<&Vec<(usize, usize, usize)>> for ErrorCorrector {
25+
fn from(block_descriptors: &Vec<(usize, usize, usize)>) -> Self {
26+
let capacity = block_descriptors.iter().map(|descriptor| descriptor.2).sum();
27+
let mut blocks = Vec::<ErrorCorrectionBlock>::with_capacity(capacity);
28+
29+
for descriptor in block_descriptors {
30+
let exemplar = ErrorCorrectionBlock {
31+
data_codeword_count: descriptor.1,
32+
error_correction_codeword_count: descriptor.0 - descriptor.1,
33+
data_codewords: vec![],
34+
ec_codewords: vec![]
35+
};
36+
let mut blocks_repeated = vec![exemplar; descriptor.2];
37+
blocks.append(&mut blocks_repeated);
38+
}
39+
40+
Self { blocks }
41+
}
42+
}
43+
44+
impl ErrorCorrector {
45+
pub fn fill_data_into_blocks(&mut self, data_codewords: Vec<u8>) -> Result<(), EncodingError> {
46+
if data_codewords.len() != self.blocks.iter().map(|b| b.data_codeword_count).sum() {
47+
return Err(EncodingError::new("Data vs ec blocks len mismatch"));
48+
}
49+
50+
let mut data_iter = data_codewords.into_iter();
51+
self.blocks.iter_mut().for_each(|block| {
52+
block.data_codewords = (&mut data_iter).take(block.data_codeword_count).collect::<Vec<u8>>();
53+
});
54+
println!("{:?}", self.blocks);
55+
Ok(())
56+
}
57+
}

qr-generator/src/lib.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ use encoder::{Encoder, EncodingModes};
77
use error_correction::CorrectionLevels;
88
use image::{imageops, GrayImage, ImageBuffer, Luma};
99
use qr_errors::QRError;
10+
pub use qr_types::QRSymbolTypes;
1011
use qr_types::{FinderLocations, QRFactory};
1112
use sizer::Sizer;
12-
pub use qr_types::QRSymbolTypes;
13+
14+
use crate::error_correction::ErrorCorrector;
1315

1416
#[derive(Default)]
1517
pub struct Options {
@@ -46,15 +48,27 @@ impl QRGenerator {
4648

4749
// Work out how large the QR code needs to be
4850
if self.options.version.is_none() {
49-
self.options.version = Some(Sizer::calculate_version(&self.options, &data)?);
51+
self.options.version = Some(Sizer::calculate_version(&self.options, &data)?);
5052
}
5153

5254
let mut encoder = Encoder::new(&self, data);
5355
encoder.encode_data_into_byte_stream()?;
54-
let data_codewords = &encoder.output_data;
55-
println!("{:?}", data_codewords);
56+
let data_bitstream = &encoder.output_data;
57+
let data_codewords = data_bitstream.clone().into_vec();
58+
59+
println!("Version: {}, Correction: {:?}", self.options.version.unwrap(), self.options.correction_level.as_ref().unwrap());
60+
println!("{}", data_bitstream.iter().map(|b| if *b {"1"} else {"0"}).collect::<Vec<&str>>().join(""));
61+
println!("{} bits", data_bitstream.len());
62+
63+
println!("{}", data_codewords.iter().map(|&n| n.to_string()).collect::<Vec<String>>().join(" "));
64+
65+
let mut error_corrector = ErrorCorrector::from(&Sizer::error_correction_shape(
66+
self.options.qr_type.as_ref().unwrap(),
67+
self.options.version.unwrap(),
68+
self.options.correction_level.as_ref().unwrap(),
69+
));
70+
error_corrector.fill_data_into_blocks(data_codewords);
5671

57-
// let data_blocks: Vec<Vec<u8>> = split_data_into_blocks(&data_codewords);
5872
// let err_correct_blocks: Vec<Vec<u8>> = generate_err_correction(&data_blocks);
5973
// let message_sequence: Vec<u8> = interleave_data_and_err_correct(data_blocks, err_correct_blocks);
6074
let message_sequence: Vec<u8> = vec![];
@@ -65,6 +79,10 @@ impl QRGenerator {
6579
Ok("./qr_code.png".to_string())
6680
}
6781

82+
// fn split_data_into_blocks(data_codewords: &Vec<u8>) -> Vec<Vec<u8>> {
83+
84+
// }
85+
6886
fn build_qr_image(&self, message: Vec<u8>) -> GrayImage {
6987
let qr_code = QRFactory::build_code(QRSymbolTypes::QRCode, 2);
7088

0 commit comments

Comments
 (0)