1use std::env::{args_os};
2use std::ffi::{OsStr};
3
4use qr_encoder::cell::{Cell, Color};
5use qr_encoder::config::{QRConfig, ECLevel, EncodingMode};
6
7
8#[derive(Copy, Clone, Debug)]
10pub struct ECCodeWordCount(usize, usize, usize, usize);
11
12#[derive(Copy, Clone, Debug)]
14pub struct CodeWordBlock(usize, usize, usize, usize);
15
16#[derive(Debug)]
17pub struct CodeWord {
18 pub ecc_codeword_count: usize,
19 pub block_count: usize,
20 pub capacity: usize
21}
22
23const CODEWORD_COUNT: [usize; 41] = [
24 0, 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
25 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,
26 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,
27 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706
28];
29
30const CODEWORD_BLOCKS: [CodeWordBlock; 40] = [
31 CodeWordBlock(1, 1, 1, 1),
33 CodeWordBlock(1, 1, 1, 1),
34 CodeWordBlock(1, 1, 2, 2),
35 CodeWordBlock(1, 2, 2, 4),
36 CodeWordBlock(1, 2, 4, 4),
37 CodeWordBlock(2, 4, 4, 4),
38 CodeWordBlock(2, 4, 6, 5),
39 CodeWordBlock(2, 4, 6, 6),
40 CodeWordBlock(2, 5, 8, 8),
41 CodeWordBlock(4, 5, 8, 8),
42 CodeWordBlock(4, 5, 8, 11),
43 CodeWordBlock(4, 8, 10, 11),
44 CodeWordBlock(4, 9, 12, 16),
45 CodeWordBlock(4, 9, 16, 16),
46 CodeWordBlock(6, 10, 12, 18),
47 CodeWordBlock(6, 10, 17, 16),
48 CodeWordBlock(6, 11, 16, 19),
49 CodeWordBlock(6, 13, 18, 21),
50 CodeWordBlock(7, 14, 21, 25),
51 CodeWordBlock(8, 16, 20, 25),
52 CodeWordBlock(8, 17, 23, 25),
53 CodeWordBlock(9, 17, 23, 34),
54 CodeWordBlock(9, 18, 25, 30),
55 CodeWordBlock(10, 20, 27, 32),
56 CodeWordBlock(12, 21, 29, 35),
57 CodeWordBlock(12, 23, 34, 37),
58 CodeWordBlock(12, 25, 34, 40),
59 CodeWordBlock(13, 26, 35, 42),
60 CodeWordBlock(14, 28, 38, 45),
61 CodeWordBlock(15, 29, 40, 48),
62 CodeWordBlock(16, 31, 43, 51),
63 CodeWordBlock(17, 33, 45, 54),
64 CodeWordBlock(18, 35, 48, 57),
65 CodeWordBlock(19, 37, 51, 60),
66 CodeWordBlock(19, 38, 53, 63),
67 CodeWordBlock(20, 40, 56, 66),
68 CodeWordBlock(21, 43, 59, 70),
69 CodeWordBlock(22, 45, 62, 74),
70 CodeWordBlock(24, 47, 65, 77),
71 CodeWordBlock(25, 49, 68, 81)
72];
73
74const EC_CODEWORD_TABLE: [ECCodeWordCount; 40] = [
75 ECCodeWordCount(7, 10, 13, 17),
76 ECCodeWordCount(10, 16, 22, 28),
77 ECCodeWordCount(15, 26, 36, 44),
78 ECCodeWordCount(20, 36, 52, 64),
79 ECCodeWordCount(26, 48, 72, 88),
80 ECCodeWordCount(36, 64, 96, 112),
81 ECCodeWordCount(40, 72, 108, 130),
82 ECCodeWordCount(48, 88, 132, 156),
83 ECCodeWordCount(60, 110, 160, 192),
84 ECCodeWordCount(72, 130, 192, 224),
85 ECCodeWordCount(80, 150, 224, 264),
86 ECCodeWordCount(96, 176, 260, 308),
87 ECCodeWordCount(104, 198, 288, 352),
88 ECCodeWordCount(120, 216, 320, 384),
89 ECCodeWordCount(132, 240, 360, 432),
90 ECCodeWordCount(144, 280, 408, 480),
91 ECCodeWordCount(168, 308, 448, 532),
92 ECCodeWordCount(180, 338, 504, 588),
93 ECCodeWordCount(196, 364, 546, 650),
94 ECCodeWordCount(224, 416, 600, 700),
95 ECCodeWordCount(224, 442, 644, 750),
96 ECCodeWordCount(252, 476, 690, 816),
97 ECCodeWordCount(270, 504, 750, 900),
98 ECCodeWordCount(300, 560, 810, 960),
99 ECCodeWordCount(312, 588, 870, 1050),
100 ECCodeWordCount(336, 644, 952, 1110),
101 ECCodeWordCount(360, 700, 1020, 1200),
102 ECCodeWordCount(390, 728, 1050, 1260),
103 ECCodeWordCount(420, 784, 1140, 1350),
104 ECCodeWordCount(450, 812, 1200, 1440),
105 ECCodeWordCount(480, 868, 1290, 1530),
106 ECCodeWordCount(510, 924, 1350, 1620),
107 ECCodeWordCount(540, 980, 1440, 1710),
108 ECCodeWordCount(570, 1036, 1530, 1800),
109 ECCodeWordCount(570, 1064, 1590, 1890),
110 ECCodeWordCount(600, 1120, 1680, 1980),
111 ECCodeWordCount(630, 1204, 1770, 2100),
112 ECCodeWordCount(660, 1260, 1860, 2220),
113 ECCodeWordCount(720, 1316, 1950, 2310),
114 ECCodeWordCount(750, 1372, 2040, 2430)
115];
116
117#[derive(Debug, Clone)]
118pub struct BlockContent {
119 pub blocks: usize,
120 pub codewords_per_block: usize
121}
122
123impl CodeWord {
124 pub fn get_data_codeword_length(&self) -> usize {
125 self.capacity - self.ecc_codeword_count
126 }
127
128 pub fn get_block_count_for_groups(&self) -> (usize, usize) {
129 let group_two = self.capacity % self.block_count;
130 let group_one = self.block_count - group_two;
131
132 (group_one, group_two)
133 }
134
135 pub fn get_data_cw_total_for_groups(&self) -> (BlockContent, BlockContent) {
136 let (group_one_blocks, group_two_blocks) = self.get_block_count_for_groups();
141
142 let data_capacity = self.capacity - self.ecc_codeword_count;
143 let group_one_capacity = data_capacity / self.block_count;
144
145 let group_two_capacity = if group_two_blocks > 0 {
146 (data_capacity - (group_one_capacity * group_one_blocks)) / group_two_blocks
147 } else {
148 0
149 };
150
151 (
152 BlockContent { blocks: group_one_blocks, codewords_per_block: group_one_capacity },
153 BlockContent { blocks: group_two_blocks, codewords_per_block: group_two_capacity }
154 )
155 }
156}
157
158pub fn codeword_info(version: usize, err_correction_level: &ECLevel) -> CodeWord {
159 let ecc_settings: ECCodeWordCount = EC_CODEWORD_TABLE[version - 1];
160 let block_count = CODEWORD_BLOCKS[version - 1];
161 let capacity = CODEWORD_COUNT[version];
162
163 let (ec_cw_count, blocks): (usize, usize) = match err_correction_level {
164 &ECLevel::Low => (ecc_settings.0, block_count.0),
165 &ECLevel::Medium => (ecc_settings.1, block_count.1),
166 &ECLevel::Q => (ecc_settings.2, block_count.2),
167 &ECLevel::High => (ecc_settings.3, block_count.3)
168 };
169
170 CodeWord {
171 ecc_codeword_count: ec_cw_count,
172 capacity: capacity,
173 block_count: blocks
174 }
175}
176
177
178pub fn get_pixel_points(cell: &Cell) -> Vec<(u32, u32, Color)> {
179 let i = ((cell.point.0 * 20) as u32) + 80;
180 let j = ((cell.point.1 * 20) as u32) + 80;
181 let mut pixels: Vec<(u32, u32, Color)> = vec![];
182 for row in i..(i + 20) {
183 for col in j..(j + 20) {
184 pixels.push((col, row, Color { g: cell.color.g, b: cell.color.b, r: cell.color.r }));
185 }
186 }
187
188 pixels
189}
190
191pub fn get_index_value(index: isize, modifiers: (isize, isize), canvas_size: isize) -> Option<usize> {
192 let x = index / canvas_size;
193 let y = index % canvas_size;
194 let cx = x + modifiers.0;
195 let cy = y + modifiers.1;
196
197 if (cx > -1 && cx < canvas_size) && (cy > -1 && cy < canvas_size) {
198 Some((cx * canvas_size + cy) as usize)
199 } else {
200 None
201 }
202}
203
204pub fn square_count(version: usize) -> usize {
205 (((version - 1) * 4) + 21)
206}
207
208pub fn set_color(index: usize) -> Color {
209 match index {
211 0 => Color { r: 255, g: 120, b: 16 },
212 1 => Color { r: 205, g: 120, b: 16 },
213 2 => Color { r: 155, g: 120, b: 16 },
214 3 => Color { r: 105, g: 120, b: 16 },
215 4 => Color { r: 55, g: 120, b: 16 },
216 5 => Color { r: 5, g: 120, b: 16 },
217 6 => Color { r: 255, g: 175, b: 16 },
218 7 => Color { r: 0, g: 0, b: 0 },
219 _ => Color { r: 255, g: 255, b: 0 }
220 }
221}
222fn get_ec_level(level: &str) -> ECLevel {
245 match level {
246 "l" => ECLevel::Low,
247 "q" => ECLevel::Q,
248 "h" => ECLevel::High,
249 _ => ECLevel::Medium
250 }
251}
252
253pub fn args() -> QRConfig {
254 let mut qr_args = args_os();
265 let mut version = 14usize;
266 let mut data: Option<Vec<u8>> = None;
267 let mut ec_level: ECLevel = ECLevel::Medium;
268 let mut arg = qr_args.next();
270 let mut debug_mode = false;
271
272 while arg.is_some() {
273 let value = arg.unwrap();
274 if value == OsStr::new("-v") {
275 version = match qr_args.next() {
276 Some(n) => {
277 let x = n.to_str().unwrap().parse::<usize>();
278 match x {
279 Ok(nx) if nx < 81 => nx, Ok(_) => 21usize,
281 Err(_) => 21usize
282 }
283 },
284 None => 21usize
285 }
286 } else if value == OsStr::new("-m") {
287 data = match qr_args.next() {
288 Some(msg) => {
289 let string = String::from(msg.to_str().unwrap());
290 Some(string.into_bytes())
291 },
292 None => panic!("sdasd")
293 }
294 } else if value == OsStr::new("-ec") {
295 ec_level = match qr_args.next() {
296 Some(ec) => {
297 let ec = ec.to_str().unwrap();
298 get_ec_level(&ec)
299 },
300 None => ECLevel::Medium
301 }
302 } else if value == OsStr::new("-DEBUG") {
303 debug_mode = true;
304 }
305
306
307 arg = qr_args.next();
308 }
309
310 let mut data = data.unwrap();
311 let codeword_properties = codeword_info(version, &ec_level);
312 data.truncate(codeword_properties.capacity - codeword_properties.ecc_codeword_count);
313
314 QRConfig {
315 version: version,
316 data: data,
317 codewords: vec![],
318 codeword_properties: codeword_properties,
319 mask: 1,
320 encoding: 4u8,
321 encoding_mode: EncodingMode::Byte,
322 debug_mode: debug_mode,
323 requires_alignment: version > 1,
324 err_correction_level: ec_level,
325 size: (((version - 1) * 4) + 21),
326 finder_points: [
327 (0, 0),
328 ((square_count(version) - 7), 0),
329 (0, (square_count(version) - 7))
330 ]
331 }
332}
333
334pub fn get_indices_for_dimensions(start: isize, step: isize, step_modifier: isize) -> Vec<usize> {
344 let mut index = start;
345 let mut indices: Vec<usize> = vec![];
346
347 for _ in 0..18 {
348 index += step;
349 indices.push(index as usize);
350
351 if indices.len() % 3 == 0 {
352 index += step_modifier;
353 }
354 }
355
356 indices
357}