rxing/maxicode/
maxi_code_reader.rs1use crate::{
18 common::{BitMatrix, DetectorRXingResult, Result},
19 BarcodeFormat, Binarizer, DecodeHints, Exceptions, ImmutableReader, RXingResult,
20 RXingResultMetadataType, Reader,
21};
22
23use super::{decoder::maxicode_decoder, detector};
24
25#[derive(Default)]
29pub struct MaxiCodeReader {
30 }
32
33impl Reader for MaxiCodeReader {
34 fn decode<B: Binarizer>(
43 &mut self,
44 image: &mut crate::BinaryBitmap<B>,
45 ) -> Result<crate::RXingResult> {
46 self.decode_with_hints(image, &DecodeHints::default())
47 }
48
49 fn decode_with_hints<B: Binarizer>(
58 &mut self,
59 image: &mut crate::BinaryBitmap<B>,
60 hints: &DecodeHints,
61 ) -> Result<crate::RXingResult> {
62 self.internal_decode_with_hints(image, hints)
63 }
64}
65
66impl ImmutableReader for MaxiCodeReader {
67 fn immutable_decode_with_hints<B: Binarizer>(
68 &self,
69 image: &mut crate::BinaryBitmap<B>,
70 hints: &DecodeHints,
71 ) -> Result<RXingResult> {
72 self.internal_decode_with_hints(image, hints)
73 }
74}
75
76impl MaxiCodeReader {
77 pub const MATRIX_WIDTH: u32 = 30;
78 pub const MATRIX_HEIGHT: u32 = 33;
79
80 fn extractPureBits(image: &BitMatrix) -> Result<BitMatrix> {
87 let enclosingRectangleOption = image.getEnclosingRectangle();
88 if enclosingRectangleOption.is_none() {
89 return Err(Exceptions::NOT_FOUND);
90 }
91
92 let enclosingRectangle = enclosingRectangleOption.ok_or(Exceptions::NOT_FOUND)?;
93
94 let left = enclosingRectangle[0];
95 let top = enclosingRectangle[1];
96 let width = enclosingRectangle[2];
97 let height = enclosingRectangle[3];
98
99 let mut bits = BitMatrix::new(Self::MATRIX_WIDTH, Self::MATRIX_HEIGHT)?;
101 for y in 0..Self::MATRIX_HEIGHT {
102 let iy = (top + (y * height + height / 2) / Self::MATRIX_HEIGHT).min(height - 1);
104 for x in 0..Self::MATRIX_WIDTH {
105 let ix = left
109 + ((x * width + width / 2 + (y & 0x01) * width / 2) / Self::MATRIX_WIDTH)
110 .min(width - 1);
111 if image.get(ix, iy) {
112 bits.set(x, y);
113 }
114 }
115 }
116 Ok(bits)
117 }
118
119 fn internal_decode_with_hints<B: Binarizer>(
120 &self,
121 image: &mut crate::BinaryBitmap<B>,
122 hints: &DecodeHints,
123 ) -> Result<RXingResult> {
124 let try_harder = hints.TryHarder.unwrap_or(false);
127
128 let mut rotation = None;
129
130 let decoderRXingResult = if try_harder {
131 let result = detector::detect(image.get_black_matrix_mut(), try_harder)?;
132 rotation = Some(result.rotation());
133 let parsed_result = detector::read_bits(result.getBits())?;
134 maxicode_decoder::decode_with_hints(&parsed_result, hints)?
135 } else {
136 let bits = Self::extractPureBits(image.get_black_matrix())?;
137 maxicode_decoder::decode_with_hints(&bits, hints)?
138 };
139
140 let mut result = RXingResult::new(
143 decoderRXingResult.getText(),
144 decoderRXingResult.getRawBytes().clone(),
145 Vec::new(),
146 BarcodeFormat::MAXICODE,
147 );
148
149 let ecLevel = decoderRXingResult.getECLevel();
150 if !ecLevel.is_empty() {
151 result.putMetadata(
152 RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
153 crate::RXingResultMetadataValue::ErrorCorrectionLevel(ecLevel.to_owned()),
154 );
155 }
156
157 if let Some(rot) = rotation {
158 if rot > 0.0 {
159 result.putMetadata(
160 RXingResultMetadataType::ORIENTATION,
161 crate::RXingResultMetadataValue::Orientation(rot as i32),
162 )
163 }
164 }
165
166 Ok(result)
167 }
168}