diff --git a/src/MultiFormatReader.java b/src/MultiFormatReader.java deleted file mode 100644 index fd95d9c..0000000 --- a/src/MultiFormatReader.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.aztec.AztecReader; -import com.google.zxing.datamatrix.DataMatrixReader; -import com.google.zxing.maxicode.MaxiCodeReader; -import com.google.zxing.oned.MultiFormatOneDReader; -import com.google.zxing.pdf417.PDF417Reader; -import com.google.zxing.qrcode.QRCodeReader; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -/** - * MultiFormatReader is a convenience class and the main entry point into the library for most uses. - * By default it attempts to decode all barcode formats that the library supports. Optionally, you - * can provide a hints object to request different behavior, for example only decoding QR codes. - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class MultiFormatReader implements Reader { - - private static final Reader[] EMPTY_READER_ARRAY = new Reader[0]; - - private Map hints; - private Reader[] readers; - - /** - * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it - * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly. - * Use setHints() followed by decodeWithState() for continuous scan applications. - * - * @param image The pixel data to decode - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - @Override - public RXingResult decode(BinaryBitmap image) throws NotFoundException { - setHints(null); - return decodeInternal(image); - } - - /** - * Decode an image using the hints provided. Does not honor existing state. - * - * @param image The pixel data to decode - * @param hints The hints to use, clearing the previous state. - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - @Override - public RXingResult decode(BinaryBitmap image, Map hints) throws NotFoundException { - setHints(hints); - return decodeInternal(image); - } - - /** - * Decode an image using the state set up by calling setHints() previously. Continuous scan - * clients will get a large speed increase by using this instead of decode(). - * - * @param image The pixel data to decode - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - public RXingResult decodeWithState(BinaryBitmap image) throws NotFoundException { - // Make sure to set up the default state so we don't crash - if (readers == null) { - setHints(null); - } - return decodeInternal(image); - } - - /** - * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls - * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This - * is important for performance in continuous scan clients. - * - * @param hints The set of hints to use for subsequent calls to decode(image) - */ - public void setHints(Map hints) { - this.hints = hints; - - boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - @SuppressWarnings("unchecked") - Collection formats = - hints == null ? null : (Collection) hints.get(DecodeHintType.POSSIBLE_FORMATS); - Collection readers = new ArrayList<>(); - if (formats != null) { - boolean addOneDReader = - formats.contains(BarcodeFormat.UPC_A) || - formats.contains(BarcodeFormat.UPC_E) || - formats.contains(BarcodeFormat.EAN_13) || - formats.contains(BarcodeFormat.EAN_8) || - formats.contains(BarcodeFormat.CODABAR) || - formats.contains(BarcodeFormat.CODE_39) || - formats.contains(BarcodeFormat.CODE_93) || - formats.contains(BarcodeFormat.CODE_128) || - formats.contains(BarcodeFormat.ITF) || - formats.contains(BarcodeFormat.RSS_14) || - formats.contains(BarcodeFormat.RSS_EXPANDED); - // Put 1D readers upfront in "normal" mode - if (addOneDReader && !tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - if (formats.contains(BarcodeFormat.QR_CODE)) { - readers.add(new QRCodeReader()); - } - if (formats.contains(BarcodeFormat.DATA_MATRIX)) { - readers.add(new DataMatrixReader()); - } - if (formats.contains(BarcodeFormat.AZTEC)) { - readers.add(new AztecReader()); - } - if (formats.contains(BarcodeFormat.PDF_417)) { - readers.add(new PDF417Reader()); - } - if (formats.contains(BarcodeFormat.MAXICODE)) { - readers.add(new MaxiCodeReader()); - } - // At end in "try harder" mode - if (addOneDReader && tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - } - if (readers.isEmpty()) { - if (!tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - - readers.add(new QRCodeReader()); - readers.add(new DataMatrixReader()); - readers.add(new AztecReader()); - readers.add(new PDF417Reader()); - readers.add(new MaxiCodeReader()); - - if (tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - } - this.readers = readers.toArray(EMPTY_READER_ARRAY); - } - - @Override - public void reset() { - if (readers != null) { - for (Reader reader : readers) { - reader.reset(); - } - } - } - - private RXingResult decodeInternal(BinaryBitmap image) throws NotFoundException { - if (readers != null) { - for (Reader reader : readers) { - if (Thread.currentThread().isInterrupted()) { - throw NotFoundException.getNotFoundInstance(); - } - try { - return reader.decode(image, hints); - } catch (ReaderException re) { - // continue - } - } - if (hints != null && hints.containsKey(DecodeHintType.ALSO_INVERTED)) { - // Calling all readers again with inverted image - image.getBlackMatrix().flip(); - for (Reader reader : readers) { - if (Thread.currentThread().isInterrupted()) { - throw NotFoundException.getNotFoundInstance(); - } - try { - return reader.decode(image, hints); - } catch (ReaderException re) { - // continue - } - } - } - } - throw NotFoundException.getNotFoundInstance(); - } - -} diff --git a/src/MultiFormatWriter.java b/src/MultiFormatWriter.java deleted file mode 100644 index 19c29a4..0000000 --- a/src/MultiFormatWriter.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.aztec.AztecWriter; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.datamatrix.DataMatrixWriter; -import com.google.zxing.oned.CodaBarWriter; -import com.google.zxing.oned.Code128Writer; -import com.google.zxing.oned.Code39Writer; -import com.google.zxing.oned.Code93Writer; -import com.google.zxing.oned.EAN13Writer; -import com.google.zxing.oned.EAN8Writer; -import com.google.zxing.oned.ITFWriter; -import com.google.zxing.oned.UPCAWriter; -import com.google.zxing.oned.UPCEWriter; -import com.google.zxing.pdf417.PDF417Writer; -import com.google.zxing.qrcode.QRCodeWriter; - -import java.util.Map; - -/** - * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat - * requested and encodes the barcode with the supplied contents. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class MultiFormatWriter implements Writer { - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height) throws WriterException { - return encode(contents, format, width, height, null); - } - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, int height, - Map hints) throws WriterException { - - Writer writer; - switch (format) { - case EAN_8: - writer = new EAN8Writer(); - break; - case UPC_E: - writer = new UPCEWriter(); - break; - case EAN_13: - writer = new EAN13Writer(); - break; - case UPC_A: - writer = new UPCAWriter(); - break; - case QR_CODE: - writer = new QRCodeWriter(); - break; - case CODE_39: - writer = new Code39Writer(); - break; - case CODE_93: - writer = new Code93Writer(); - break; - case CODE_128: - writer = new Code128Writer(); - break; - case ITF: - writer = new ITFWriter(); - break; - case PDF_417: - writer = new PDF417Writer(); - break; - case CODABAR: - writer = new CodaBarWriter(); - break; - case DATA_MATRIX: - writer = new DataMatrixWriter(); - break; - case AZTEC: - writer = new AztecWriter(); - break; - default: - throw new IllegalArgumentException("No encoder available for format " + format); - } - return writer.encode(contents, format, width, height, hints); - } - -} diff --git a/src/aztec/aztec_reader.rs b/src/aztec/aztec_reader.rs index 6f43314..ba4d20f 100644 --- a/src/aztec/aztec_reader.rs +++ b/src/aztec/aztec_reader.rs @@ -40,18 +40,18 @@ impl Reader for AztecReader { * @throws NotFoundException if a Data Matrix code cannot be found * @throws FormatException if a Data Matrix code cannot be decoded */ - fn decode(&self, image: &BinaryBitmap) -> Result { + fn decode(&mut self, image: &BinaryBitmap) -> Result { self.decode_with_hints(image, &HashMap::new()) } fn decode_with_hints( - &self, + &mut self, image: &BinaryBitmap, hints: &HashMap, ) -> Result { // let notFoundException = None; // let formatException = None; - let mut detector = Detector::new(image.getBlackMatrix()?.clone()); + let mut detector = Detector::new(image.getBlackMatrix().clone()); let points; let decoderRXingResult: DecoderRXingResult; // try { @@ -134,7 +134,7 @@ impl Reader for AztecReader { Ok(result) } - fn reset(&self) { + fn reset(&mut self) { // do nothing } } diff --git a/src/binarizer.rs b/src/binarizer.rs index ee47a2c..93ccd6a 100644 --- a/src/binarizer.rs +++ b/src/binarizer.rs @@ -16,6 +16,8 @@ //package com.google.zxing; +use std::rc::Rc; + use crate::{ common::{BitArray, BitMatrix}, Exceptions, LuminanceSource, @@ -70,7 +72,7 @@ pub trait Binarizer { * @param source The LuminanceSource this Binarizer will operate on. * @return A new concrete Binarizer implementation object. */ - fn createBinarizer(&self, source: Box) -> Box; + fn createBinarizer(&self, source: Box) -> Rc; fn getWidth(&self) -> usize; diff --git a/src/binary_bitmap.rs b/src/binary_bitmap.rs index 7045342..5d0f293 100644 --- a/src/binary_bitmap.rs +++ b/src/binary_bitmap.rs @@ -16,7 +16,7 @@ //package com.google.zxing; -use std::fmt; +use std::{fmt, rc::Rc}; use crate::{ common::{BitArray, BitMatrix}, @@ -29,13 +29,14 @@ use crate::{ * * @author dswitkin@google.com (Daniel Switkin) */ +#[derive(Clone)] pub struct BinaryBitmap { - binarizer: Box, + binarizer: Rc, matrix: BitMatrix, } impl BinaryBitmap { - pub fn new(binarizer: Box) -> Self { + pub fn new(binarizer: Rc) -> Self { Self { matrix: binarizer.getBlackMatrix().unwrap(), binarizer: binarizer, @@ -80,13 +81,31 @@ impl BinaryBitmap { * @return The 2D array of bits for the image (true means black). * @throws NotFoundException if image can't be binarized to make a matrix */ - pub fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> { + pub fn getBlackMatrixMut(&mut self) -> &mut BitMatrix { // The matrix is created on demand the first time it is requested, then cached. There are two // reasons for this: // 1. This work will never be done if the caller only installs 1D Reader objects, or if a // 1D Reader finds a barcode before the 2D Readers run. // 2. This work will only be done once even if the caller installs multiple 2D Readers. - return Ok(&self.matrix); + &mut self.matrix + } + + /** + * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive + * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or + * may not apply sharpening. Therefore, a row from this matrix may not be identical to one + * fetched using getBlackRow(), so don't mix and match between them. + * + * @return The 2D array of bits for the image (true means black). + * @throws NotFoundException if image can't be binarized to make a matrix + */ + pub fn getBlackMatrix(&self) -> &BitMatrix { + // The matrix is created on demand the first time it is requested, then cached. There are two + // reasons for this: + // 1. This work will never be done if the caller only installs 1D Reader objects, or if a + // 1D Reader finds a barcode before the 2D Readers run. + // 2. This work will only be done once even if the caller installs multiple 2D Readers. + &self.matrix } /** @@ -161,6 +180,6 @@ impl BinaryBitmap { impl fmt::Display for BinaryBitmap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.getBlackMatrix().unwrap()) + write!(f, "{}", self.getBlackMatrix()) } } diff --git a/src/common/global_histogram_binarizer.rs b/src/common/global_histogram_binarizer.rs index 6d151ba..aa0e01a 100644 --- a/src/common/global_histogram_binarizer.rs +++ b/src/common/global_histogram_binarizer.rs @@ -20,6 +20,8 @@ // import com.google.zxing.LuminanceSource; // import com.google.zxing.NotFoundException; +use std::rc::Rc; + use crate::{Binarizer, Exceptions, LuminanceSource}; use super::{BitArray, BitMatrix}; @@ -140,8 +142,8 @@ impl Binarizer for GlobalHistogramBinarizer { Ok(matrix) } - fn createBinarizer(&self, source: Box) -> Box { - return Box::new(GlobalHistogramBinarizer::new(source)); + fn createBinarizer(&self, source: Box) -> Rc { + return Rc::new(GlobalHistogramBinarizer::new(source)); } fn getWidth(&self) -> usize { diff --git a/src/common/hybrid_binarizer.rs b/src/common/hybrid_binarizer.rs index 950a14c..93accce 100644 --- a/src/common/hybrid_binarizer.rs +++ b/src/common/hybrid_binarizer.rs @@ -20,6 +20,8 @@ // import com.google.zxing.LuminanceSource; // import com.google.zxing.NotFoundException; +use std::rc::Rc; + use crate::{Binarizer, Exceptions, LuminanceSource}; use super::{BitArray, BitMatrix, GlobalHistogramBinarizer}; @@ -109,8 +111,8 @@ impl Binarizer for HybridBinarizer { Ok(matrix) } - fn createBinarizer(&self, source: Box) -> Box { - Box::new(HybridBinarizer::new(source)) + fn createBinarizer(&self, source: Box) -> Rc { + Rc::new(HybridBinarizer::new(source)) } fn getWidth(&self) -> usize { diff --git a/src/datamatrix/decoder/decoded_bit_stream_parser.rs b/src/datamatrix/decoder/decoded_bit_stream_parser.rs index 017903c..f13a9cf 100644 --- a/src/datamatrix/decoder/decoded_bit_stream_parser.rs +++ b/src/datamatrix/decoder/decoded_bit_stream_parser.rs @@ -234,7 +234,6 @@ fn decodeAsciiSegment( {}, 235=> // Upper Shift (shift to Extended ASCII) upperShift = true, - 236=> {// 05 Macro result.append_string("[)>\u{001E}05\u{001D}"); resultTrailer.replace_range(0..0, "\u{001E}\u{0004}"); diff --git a/src/decode_hints.rs b/src/decode_hints.rs index f35b6e3..1ab7ac3 100644 --- a/src/decode_hints.rs +++ b/src/decode_hints.rs @@ -141,7 +141,7 @@ pub enum DecodeHintValue { * Image is known to be of one of a few possible formats. * Maps to a {@link List} of {@link BarcodeFormat}s. */ - PossibleFormats(BarcodeFormat), + PossibleFormats(Vec), /** * Spend more time to try to find a barcode; optimize for accuracy, not speed. diff --git a/src/lib.rs b/src/lib.rs index cc59847..c80d6cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,3 +87,9 @@ pub mod datamatrix; pub mod multi; pub mod oned; pub mod pdf417; + +mod multi_format_writer; +pub use multi_format_writer::*; + +mod multi_format_reader; +pub use multi_format_reader::*; diff --git a/src/maxicode/maxi_code_reader.rs b/src/maxicode/maxi_code_reader.rs index ebeb1a8..3142093 100644 --- a/src/maxicode/maxi_code_reader.rs +++ b/src/maxicode/maxi_code_reader.rs @@ -38,7 +38,10 @@ impl Reader for MaxiCodeReader { * @throws FormatException if a MaxiCode cannot be decoded * @throws ChecksumException if error correction fails */ - fn decode(&self, image: &crate::BinaryBitmap) -> Result { + fn decode( + &mut self, + image: &crate::BinaryBitmap, + ) -> Result { self.decode_with_hints(image, &HashMap::new()) } @@ -51,13 +54,13 @@ impl Reader for MaxiCodeReader { * @throws ChecksumException if error correction fails */ fn decode_with_hints( - &self, + &mut self, image: &crate::BinaryBitmap, hints: &crate::DecodingHintDictionary, ) -> Result { // Note that MaxiCode reader effectively always assumes PURE_BARCODE mode // and can't detect it in an image - let bits = Self::extractPureBits(image.getBlackMatrix()?)?; + let bits = Self::extractPureBits(image.getBlackMatrix())?; let decoderRXingResult = decoder::decode_with_hints(bits, &hints)?; let mut result = RXingResult::new( decoderRXingResult.getText(), @@ -76,7 +79,7 @@ impl Reader for MaxiCodeReader { Ok(result) } - fn reset(&self) { + fn reset(&mut self) { // do nothing } } diff --git a/src/multi_format_reader.rs b/src/multi_format_reader.rs new file mode 100644 index 0000000..5d6b1a0 --- /dev/null +++ b/src/multi_format_reader.rs @@ -0,0 +1,214 @@ +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use std::collections::HashMap; + +use crate::{ + aztec::AztecReader, maxicode::MaxiCodeReader, qrcode::QRCodeReader, BarcodeFormat, + BinaryBitmap, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, RXingResult, + Reader, +}; + +/** + * MultiFormatReader is a convenience class and the main entry point into the library for most uses. + * By default it attempts to decode all barcode formats that the library supports. Optionally, you + * can provide a hints object to request different behavior, for example only decoding QR codes. + * + * @author Sean Owen + * @author dswitkin@google.com (Daniel Switkin) + */ +pub struct MultiFormatReader { + hints: DecodingHintDictionary, + readers: Vec>, +} + +impl Reader for MultiFormatReader { + /** + * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it + * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly. + * Use setHints() followed by decodeWithState() for continuous scan applications. + * + * @param image The pixel data to decode + * @return The contents of the image + * @throws NotFoundException Any errors which occurred + */ + fn decode( + &mut self, + image: &crate::BinaryBitmap, + ) -> Result { + self.setHints(&HashMap::new()); + self.decodeInternal(image) + } + + /** + * Decode an image using the hints provided. Does not honor existing state. + * + * @param image The pixel data to decode + * @param hints The hints to use, clearing the previous state. + * @return The contents of the image + * @throws NotFoundException Any errors which occurred + */ + fn decode_with_hints( + &mut self, + image: &crate::BinaryBitmap, + hints: &crate::DecodingHintDictionary, + ) -> Result { + self.setHints(hints); + self.decodeInternal(image) + } + + fn reset(&mut self) { + // if (readers != null) { + for reader in self.readers.iter_mut() { + reader.reset(); + } + // } + } +} + +impl MultiFormatReader { + const EMPTY_READER_ARRAY: Vec> = Vec::new(); + + /** + * Decode an image using the state set up by calling setHints() previously. Continuous scan + * clients will get a large speed increase by using this instead of decode(). + * + * @param image The pixel data to decode + * @return The contents of the image + * @throws NotFoundException Any errors which occurred + */ + pub fn decodeWithState(&mut self, image: &BinaryBitmap) -> Result { + // Make sure to set up the default state so we don't crash + if self.readers.is_empty() { + self.setHints(&HashMap::new()); + } + self.decodeInternal(image) + } + + /** + * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls + * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This + * is important for performance in continuous scan clients. + * + * @param hints The set of hints to use for subsequent calls to decode(image) + */ + pub fn setHints(&mut self, hints: &DecodingHintDictionary) { + self.hints = hints.clone(); // {hint} else {HashMap::new()}; + + let tryHarder = self.hints.contains_key(&DecodeHintType::TRY_HARDER); + //@SuppressWarnings("unchecked") + let formats = hints.get(&DecodeHintType::POSSIBLE_FORMATS); + let mut readers: Vec> = Vec::new(); + if let Some(DecodeHintValue::PossibleFormats(formats)) = formats { + let addOneDReader = formats.contains(&BarcodeFormat::UPC_A) + || formats.contains(&BarcodeFormat::UPC_E) + || formats.contains(&BarcodeFormat::EAN_13) + || formats.contains(&BarcodeFormat::EAN_8) + || formats.contains(&BarcodeFormat::CODABAR) + || formats.contains(&BarcodeFormat::CODE_39) + || formats.contains(&BarcodeFormat::CODE_93) + || formats.contains(&BarcodeFormat::CODE_128) + || formats.contains(&BarcodeFormat::ITF) + || formats.contains(&BarcodeFormat::RSS_14) + || formats.contains(&BarcodeFormat::RSS_EXPANDED); + // Put 1D readers upfront in "normal" mode + if addOneDReader && !tryHarder { + unimplemented!(""); + // readers.push(new MultiFormatOneDReader(hints)); + } + if formats.contains(&BarcodeFormat::QR_CODE) { + readers.push(Box::new(QRCodeReader {})); + } + if formats.contains(&BarcodeFormat::DATA_MATRIX) { + unimplemented!(""); + // readers.push(DataMatrixReader{}); + } + if formats.contains(&BarcodeFormat::AZTEC) { + readers.push(Box::new(AztecReader {})); + } + if formats.contains(&BarcodeFormat::PDF_417) { + unimplemented!(""); + // readers.push(new PDF417Reader()); + } + if formats.contains(&BarcodeFormat::MAXICODE) { + readers.push(Box::new(MaxiCodeReader {})); + } + // At end in "try harder" mode + if addOneDReader && tryHarder { + unimplemented!(""); + // readers.push( MultiFormatOneDReader::new(hints)); + } + } + if readers.is_empty() { + if !tryHarder { + // readers.push( MultiFormatOneDReader::new(hints)); + unimplemented!(""); + } + + readers.push(Box::new(QRCodeReader {})); + // readers.push( Box::new(DataMatrixReader{})); + readers.push(Box::new(AztecReader {})); + // readers.push( PDF417Reader()); + readers.push(Box::new(MaxiCodeReader {})); + // unimplemented!(""); + + if tryHarder { + // readers.push( Box::new(MultiFormatOneDReader::new(hints))); + unimplemented!(""); + } + } + self.readers = Vec::new(); //readers.toArray(EMPTY_READER_ARRAY); + } + + pub fn decodeInternal(&mut self, image: &BinaryBitmap) -> Result { + if !self.readers.is_empty() { + for reader in self.readers.iter_mut() { + // I'm not sure how to model this in rust + // if (Thread.currentThread().isInterrupted()) { + // throw NotFoundException.getNotFoundInstance(); + // } + //try { + let res = reader.decode_with_hints(image, &self.hints); + if res.is_ok() { + return res; + } + //} catch (ReaderException re) { + // continue + //} + } + if self.hints.contains_key(&DecodeHintType::ALSO_INVERTED) { + // Calling all readers again with inverted image + let mut image = image.clone(); + image.getBlackMatrixMut().flip_self(); + for reader in self.readers.iter_mut() { + // if (Thread.currentThread().isInterrupted()) { + // throw NotFoundException.getNotFoundInstance(); + // } + let res = reader.decode_with_hints(&image, &self.hints); + if res.is_ok() { + return res; + } + // try { + // return reader.decode(image, hints); + // } catch (ReaderException re) { + // // continue + // } + } + } + } + return Err(Exceptions::NotFoundException("".to_owned())); + } +} diff --git a/src/multi_format_writer.rs b/src/multi_format_writer.rs new file mode 100644 index 0000000..c549787 --- /dev/null +++ b/src/multi_format_writer.rs @@ -0,0 +1,146 @@ +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use std::collections::HashMap; + +use crate::{aztec::AztecWriter, qrcode::QRCodeWriter, BarcodeFormat, Exceptions, Writer}; + +/** + * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat + * requested and encodes the barcode with the supplied contents. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +pub struct MultiFormatWriter; + +impl Writer for MultiFormatWriter { + fn encode( + &self, + contents: &str, + format: &crate::BarcodeFormat, + width: i32, + height: i32, + ) -> Result { + self.encode_with_hints(contents, format, width, height, &HashMap::new()) + } + + fn encode_with_hints( + &self, + contents: &str, + format: &crate::BarcodeFormat, + width: i32, + height: i32, + hints: &crate::EncodingHintDictionary, + ) -> Result { + let writer: Box = match format { + BarcodeFormat::EAN_8 => unimplemented!(""), + // writer = EAN8Writer(), + BarcodeFormat::UPC_E => unimplemented!(""), + // writer = UPCEWriter(), + BarcodeFormat::EAN_13 => unimplemented!(""), + // writer = EAN13Writer(), + BarcodeFormat::UPC_A => unimplemented!(""), + // writer = UPCAWriter(), + BarcodeFormat::QR_CODE => Box::new(QRCodeWriter {}), + BarcodeFormat::CODE_39 => unimplemented!(""), + // writer = Code39Writer(), + BarcodeFormat::CODE_93 => unimplemented!(""), + // writer = Code93Writer(), + BarcodeFormat::CODE_128 => unimplemented!(""), + // writer = Code128Writer(), + BarcodeFormat::ITF => unimplemented!(""), + // writer = ITFWriter(), + BarcodeFormat::PDF_417 => unimplemented!(""), + // writer = PDF417Writer(), + BarcodeFormat::CODABAR => unimplemented!(""), + // writer = CodaBarWriter(), + BarcodeFormat::DATA_MATRIX => unimplemented!(""), + // DataMatrixWriter{}, + BarcodeFormat::AZTEC => Box::new(AztecWriter {}), + _ => { + return Err(Exceptions::IllegalArgumentException(format!( + "No encoder available for format {:?}", + format + ))) + } + }; + + writer.encode_with_hints(contents, format, width, height, hints) + } +} + +// @Override +// public BitMatrix encode(String contents, +// BarcodeFormat format, +// int width, +// int height) throws WriterException { +// return encode(contents, format, width, height, null); +// } + +// @Override +// public BitMatrix encode(String contents, +// BarcodeFormat format, +// int width, int height, +// Map hints) throws WriterException { + +// Writer writer; +// switch (format) { +// case EAN_8: +// writer = new EAN8Writer(); +// break; +// case UPC_E: +// writer = new UPCEWriter(); +// break; +// case EAN_13: +// writer = new EAN13Writer(); +// break; +// case UPC_A: +// writer = new UPCAWriter(); +// break; +// case QR_CODE: +// writer = new QRCodeWriter(); +// break; +// case CODE_39: +// writer = new Code39Writer(); +// break; +// case CODE_93: +// writer = new Code93Writer(); +// break; +// case CODE_128: +// writer = new Code128Writer(); +// break; +// case ITF: +// writer = new ITFWriter(); +// break; +// case PDF_417: +// writer = new PDF417Writer(); +// break; +// case CODABAR: +// writer = new CodaBarWriter(); +// break; +// case DATA_MATRIX: +// writer = new DataMatrixWriter(); +// break; +// case AZTEC: +// writer = new AztecWriter(); +// break; +// default: +// throw new IllegalArgumentException("No encoder available for format " + format); +// } +// return writer.encode(contents, format, width, height, hints); +// } + +// } diff --git a/src/qrcode/qr_code_reader.rs b/src/qrcode/qr_code_reader.rs index 0035bc3..ea69252 100644 --- a/src/qrcode/qr_code_reader.rs +++ b/src/qrcode/qr_code_reader.rs @@ -47,24 +47,27 @@ impl Reader for QRCodeReader { * @throws FormatException if a QR code cannot be decoded * @throws ChecksumException if error correction fails */ - fn decode(&self, image: &crate::BinaryBitmap) -> Result { + fn decode( + &mut self, + image: &crate::BinaryBitmap, + ) -> Result { self.decode_with_hints(image, &HashMap::new()) } fn decode_with_hints( - &self, + &mut self, image: &crate::BinaryBitmap, hints: &crate::DecodingHintDictionary, ) -> Result { let decoderRXingResult: DecoderRXingResult; let mut points: Vec; if hints.contains_key(&DecodeHintType::PURE_BARCODE) { - let bits = Self::extractPureBits(image.getBlackMatrix()?)?; + let bits = Self::extractPureBits(image.getBlackMatrix())?; decoderRXingResult = decoder::decode_bitmatrix_with_hints(&bits, &hints)?; points = Vec::new(); } else { let detectorRXingResult = - Detector::new(image.getBlackMatrix()?.clone()).detect_with_hints(&hints)?; + Detector::new(image.getBlackMatrix().clone()).detect_with_hints(&hints)?; decoderRXingResult = decoder::decode_bitmatrix_with_hints(detectorRXingResult.getBits(), &hints)?; points = detectorRXingResult.getPoints().clone(); @@ -126,7 +129,7 @@ impl Reader for QRCodeReader { Ok(result) } - fn reset(&self) { + fn reset(&mut self) { // nothing } } diff --git a/src/reader.rs b/src/reader.rs index bc015e4..bee916c 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -40,7 +40,7 @@ pub trait Reader { * @throws ChecksumException if a potential barcode is found but does not pass its checksum * @throws FormatException if a potential barcode is found but format is invalid */ - fn decode(&self, image: &BinaryBitmap) -> Result; + fn decode(&mut self, image: &BinaryBitmap) -> Result; /** * Locates and decodes a barcode in some format within an image. This method also accepts @@ -57,7 +57,7 @@ pub trait Reader { * @throws FormatException if a potential barcode is found but format is invalid */ fn decode_with_hints( - &self, + &mut self, image: &BinaryBitmap, hints: &DecodingHintDictionary, ) -> Result; @@ -66,5 +66,5 @@ pub trait Reader { * Resets any internal state the implementation has after a decode, to prepare it * for reuse. */ - fn reset(&self); + fn reset(&mut self); }