rxing/
multi_use_multi_format_reader.rs1use std::collections::HashSet;
18
19use crate::DecodeHints;
20use crate::common::Result;
21use crate::qrcode::cpp_port::QrReader;
22use crate::{
23 BarcodeFormat, Binarizer, BinaryBitmap, Exceptions, RXingResult, Reader, aztec::AztecReader,
24 datamatrix::DataMatrixReader, maxicode::MaxiCodeReader, oned::MultiFormatOneDReader,
25 pdf417::PDF417Reader, qrcode::QRCodeReader,
26};
27
28pub(crate) const ONE_D_FORMATS: [BarcodeFormat; 12] = [
29 BarcodeFormat::UPC_A,
30 BarcodeFormat::UPC_E,
31 BarcodeFormat::EAN_13,
32 BarcodeFormat::EAN_8,
33 BarcodeFormat::CODABAR,
34 BarcodeFormat::CODE_39,
35 BarcodeFormat::CODE_93,
36 BarcodeFormat::CODE_128,
37 BarcodeFormat::ITF,
38 BarcodeFormat::RSS_14,
39 BarcodeFormat::RSS_EXPANDED,
40 BarcodeFormat::TELEPEN,
41];
42
43#[derive(Default)]
52pub struct MultiUseMultiFormatReader {
53 hints: DecodeHints,
54 possible_formats: HashSet<BarcodeFormat>,
55 try_harder: bool,
56 one_d_reader: MultiFormatOneDReader,
57 qr_code_reader: QRCodeReader,
58 data_matrix_reader: DataMatrixReader,
59 aztec_reader: AztecReader,
60 pdf417_reader: PDF417Reader,
61 maxicode_reader: MaxiCodeReader,
62 cpp_qrcode_reader: QrReader,
63}
64
65impl Reader for MultiUseMultiFormatReader {
66 fn decode<B: Binarizer>(&mut self, image: &mut BinaryBitmap<B>) -> Result<RXingResult> {
76 self.set_hints(&DecodeHints::default());
77 self.decode_internal(image)
78 }
79
80 fn decode_with_hints<B: Binarizer>(
89 &mut self,
90 image: &mut BinaryBitmap<B>,
91 hints: &DecodeHints,
92 ) -> Result<RXingResult> {
93 self.set_hints(hints);
94 self.decode_internal(image)
95 }
96
97 fn reset(&mut self) {
98 self.one_d_reader.reset();
99 self.qr_code_reader.reset();
100 self.data_matrix_reader.reset();
101 self.aztec_reader.reset();
102 self.pdf417_reader.reset();
103 self.maxicode_reader.reset();
104 self.cpp_qrcode_reader.reset();
105 }
106}
107
108impl MultiUseMultiFormatReader {
109 pub fn decode_with_state<B: Binarizer>(
118 &mut self,
119 image: &mut BinaryBitmap<B>,
120 ) -> Result<RXingResult> {
121 if self.possible_formats.is_empty() {
123 self.set_hints(&DecodeHints::default());
124 }
125 self.decode_internal(image)
126 }
127
128 pub fn set_hints(&mut self, hints: &DecodeHints) {
136 self.hints.clone_from(hints);
137
138 self.try_harder = matches!(self.hints.TryHarder, Some(true));
139 self.possible_formats = if let Some(formats) = &hints.PossibleFormats {
140 formats.clone()
141 } else {
142 HashSet::new()
143 };
144 self.one_d_reader = MultiFormatOneDReader::new(hints);
145 }
146
147 pub fn decode_internal<B: Binarizer>(
148 &mut self,
149 image: &mut BinaryBitmap<B>,
150 ) -> Result<RXingResult> {
151 let res = self.decode_formats(image);
152 if res.is_ok() {
153 return res;
154 }
155 if matches!(self.hints.AlsoInverted, Some(true)) {
156 image.get_black_matrix_mut().flip_self();
158 let res = self.decode_formats(image);
159 if let Ok(mut r) = res {
160 r.putMetadata(
162 crate::RXingResultMetadataType::IS_INVERTED,
163 crate::RXingResultMetadataValue::IsInverted(true),
164 );
165 return Ok(r);
166 }
167 }
171 Err(Exceptions::NOT_FOUND)
172 }
173
174 fn decode_formats<B: Binarizer>(&mut self, image: &mut BinaryBitmap<B>) -> Result<RXingResult> {
175 if !self.possible_formats.is_empty() {
176 let one_d = ONE_D_FORMATS
177 .iter()
178 .any(|e| self.possible_formats.contains(e));
179 if one_d && !self.try_harder {
192 if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) {
193 return Ok(res);
194 }
195 }
196 for possible_format in self.possible_formats.iter() {
197 let res = match possible_format {
198 BarcodeFormat::QR_CODE => {
199 let a = self.cpp_qrcode_reader.decode_with_hints(image, &self.hints);
200 if a.is_ok() {
201 a
202 } else {
203 self.qr_code_reader.decode_with_hints(image, &self.hints)
204 }
205 }
206 BarcodeFormat::MICRO_QR_CODE => {
207 self.cpp_qrcode_reader.decode_with_hints(image, &self.hints)
208 }
209 BarcodeFormat::DATA_MATRIX => self
210 .data_matrix_reader
211 .decode_with_hints(image, &self.hints),
212 BarcodeFormat::AZTEC => self.aztec_reader.decode_with_hints(image, &self.hints),
213 BarcodeFormat::PDF_417 => {
214 self.pdf417_reader.decode_with_hints(image, &self.hints)
215 }
216 BarcodeFormat::MAXICODE => {
217 self.maxicode_reader.decode_with_hints(image, &self.hints)
218 }
219 _ => Err(Exceptions::UNSUPPORTED_OPERATION),
220 };
221 if res.is_ok() {
222 return res;
223 }
224 }
225 if one_d && self.try_harder {
226 if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) {
227 return Ok(res);
228 }
229 }
230 } else {
231 if !self.try_harder {
232 if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) {
233 return Ok(res);
234 }
235 }
236 if let Ok(res) = self.cpp_qrcode_reader.decode_with_hints(image, &self.hints) {
237 return Ok(res);
238 }
239 if let Ok(res) = self.qr_code_reader.decode_with_hints(image, &self.hints) {
240 return Ok(res);
241 }
242 if let Ok(res) = self
243 .data_matrix_reader
244 .decode_with_hints(image, &self.hints)
245 {
246 return Ok(res);
247 }
248 if let Ok(res) = self.aztec_reader.decode_with_hints(image, &self.hints) {
249 return Ok(res);
250 }
251 if let Ok(res) = self.pdf417_reader.decode_with_hints(image, &self.hints) {
252 return Ok(res);
253 }
254 if let Ok(res) = self.maxicode_reader.decode_with_hints(image, &self.hints) {
255 return Ok(res);
256 }
257
258 if self.try_harder {
259 if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) {
260 return Ok(res);
261 }
262 }
263 }
264
265 Err(Exceptions::UNSUPPORTED_OPERATION)
266 }
267}