diff --git a/src/RGBLuminanceSourceTestCase.rs b/src/RGBLuminanceSourceTestCase.rs index 8f9f5d4..1cf3bf7 100644 --- a/src/RGBLuminanceSourceTestCase.rs +++ b/src/RGBLuminanceSourceTestCase.rs @@ -26,13 +26,13 @@ use crate::{RGBLuminanceSource, LuminanceSource}; - static src_data : [u32;9] = [0x000000, 0x7F7F7F, 0xFFFFFF, + const SRC_DATA : [u32;9] = [0x000000, 0x7F7F7F, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0x0000FF, 0x00FF00, 0xFF0000]; #[test] fn testCrop() { - let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&src_data.to_vec()); + let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&SRC_DATA.to_vec()); assert!(SOURCE.isCropSupported()); let cropped = SOURCE.crop(1, 1, 1, 1).unwrap(); @@ -43,7 +43,7 @@ use crate::{RGBLuminanceSource, LuminanceSource}; #[test] fn testMatrix() { - let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&src_data.to_vec()); + let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&SRC_DATA.to_vec()); assert_eq!(vec![ 0x00, 0x7F, 0xFF, 0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F ], SOURCE.getMatrix()); @@ -57,7 +57,7 @@ use crate::{RGBLuminanceSource, LuminanceSource}; #[test] fn testGetRow() { - let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&src_data.to_vec()); + let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&SRC_DATA.to_vec()); assert_eq!(vec![ 0x3F, 0x7F, 0x3F ], SOURCE.getRow(2, &vec![0;3])); } diff --git a/src/aztec/EncoderTest.rs b/src/aztec/EncoderTest.rs index 9d5ffe7..7882222 100644 --- a/src/aztec/EncoderTest.rs +++ b/src/aztec/EncoderTest.rs @@ -25,7 +25,6 @@ use crate::{ shared_test_methods::{stripSpace, toBitArray, toBooleanArray}, AztecDetectorResult::AztecDetectorRXingResult, }, - common::{BitArray, BitMatrix}, BarcodeFormat, EncodeHintType, EncodeHintValue, RXingResultPoint, }; @@ -49,8 +48,8 @@ const UTF_8: EncodingRef = encoding::all::UTF_8; //StandardCharsets.UTF_8; const ISO_8859_15: EncodingRef = encoding::all::ISO_8859_15; //Charset.forName("ISO-8859-15"); const WINDOWS_1252: EncodingRef = encoding::all::WINDOWS_1252; //Charset.forName("Windows-1252"); -const DOTX: &str = "[^.X]"; -const SPACES: &str = "\\s+"; +// const DOTX: &str = "[^.X]"; +// const SPACES: &str = "\\s+"; const NO_POINTS: Vec = Vec::new(); // real life tests diff --git a/src/aztec/decoder.rs b/src/aztec/decoder.rs index 9c4c7bc..fa6fcd0 100644 --- a/src/aztec/decoder.rs +++ b/src/aztec/decoder.rs @@ -14,12 +14,11 @@ * limitations under the License. */ -use encoding::Encoding; use crate::{ common::{ reedsolomon::{ - get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonDecoder, GenericGFRef, + get_predefined_genericgf, PredefinedGenericGF, ReedSolomonDecoder, GenericGFRef, }, BitMatrix, CharacterSetECI, DecoderRXingResult, DetectorRXingResult, }, diff --git a/src/aztec/detector.rs b/src/aztec/detector.rs index c4192e7..5095389 100644 --- a/src/aztec/detector.rs +++ b/src/aztec/detector.rs @@ -19,7 +19,7 @@ use std::fmt; use crate::{ common::{ detector::{MathUtils, WhiteRectangleDetector}, - reedsolomon::{self, GenericGF, ReedSolomonDecoder}, + reedsolomon::{self, ReedSolomonDecoder}, BitMatrix, DefaultGridSampler, GridSampler, }, exceptions::Exceptions, diff --git a/src/aztec/encoder/encoder.rs b/src/aztec/encoder/encoder.rs index c3ba80f..c0cd2ed 100644 --- a/src/aztec/encoder/encoder.rs +++ b/src/aztec/encoder/encoder.rs @@ -19,7 +19,7 @@ use encoding::Encoding; use crate::{ common::{ reedsolomon::{ - get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonEncoder, GenericGFRef, + get_predefined_genericgf, PredefinedGenericGF, ReedSolomonEncoder, GenericGFRef, }, BitArray, BitMatrix, }, diff --git a/src/aztec/encoder/token.rs b/src/aztec/encoder/token.rs index 30b1032..368c835 100644 --- a/src/aztec/encoder/token.rs +++ b/src/aztec/encoder/token.rs @@ -14,8 +14,6 @@ * limitations under the License. */ -use std::rc::Rc; - use crate::common::BitArray; use super::{BinaryShiftToken, SimpleToken}; diff --git a/src/barcode_format.rs b/src/barcode_format.rs new file mode 100644 index 0000000..501f78e --- /dev/null +++ b/src/barcode_format.rs @@ -0,0 +1,77 @@ + +/* + * 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; + +/** + * Enumerates barcode formats known to this package. Please keep alphabetized. + * + * @author Sean Owen + */ +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub enum BarcodeFormat { + /** Aztec 2D barcode format. */ + AZTEC, + + /** CODABAR 1D format. */ + CODABAR, + + /** Code 39 1D format. */ + CODE_39, + + /** Code 93 1D format. */ + CODE_93, + + /** Code 128 1D format. */ + CODE_128, + + /** Data Matrix 2D barcode format. */ + DATA_MATRIX, + + /** EAN-8 1D format. */ + EAN_8, + + /** EAN-13 1D format. */ + EAN_13, + + /** ITF (Interleaved Two of Five) 1D format. */ + ITF, + + /** MaxiCode 2D barcode format. */ + MAXICODE, + + /** PDF417 format. */ + PDF_417, + + /** QR Code 2D barcode format. */ + QR_CODE, + + /** RSS 14 */ + RSS_14, + + /** RSS EXPANDED */ + RSS_EXPANDED, + + /** UPC-A 1D format. */ + UPC_A, + + /** UPC-E 1D format. */ + UPC_E, + + /** UPC/EAN extension format. Not a stand-alone format. */ + UPC_EAN_EXTENSION, +} \ No newline at end of file diff --git a/src/binarizer.rs b/src/binarizer.rs new file mode 100644 index 0000000..b0663e1 --- /dev/null +++ b/src/binarizer.rs @@ -0,0 +1,76 @@ + +/* + * Copyright 2009 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; + +use crate::{common::{BitArray, BitMatrix}, Exceptions, LuminanceSource}; + +/** + * This class hierarchy provides a set of methods to convert luminance data to 1 bit data. + * It allows the algorithm to vary polymorphically, for example allowing a very expensive + * thresholding technique for servers and a fast one for mobile. It also permits the implementation + * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +pub trait Binarizer { + //private final LuminanceSource source; + //fn new(source:dyn LuminanceSource) -> Self; + + fn getLuminanceSource(&self) -> &Box; + + /** + * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return + * cached data. Callers should assume this method is expensive and call it as seldom as possible. + * This method is intended for decoding 1D barcodes and may choose to apply sharpening. + * For callers which only examine one row of pixels at a time, the same BitArray should be reused + * and passed in with each call for performance. However it is legal to keep more than one row + * at a time if needed. + * + * @param y The row to fetch, which must be in [0, bitmap height) + * @param row An optional preallocated array. If null or too small, it will be ignored. + * If used, the Binarizer will call BitArray.clear(). Always use the returned object. + * @return The array of bits for this row (true means black). + * @throws NotFoundException if row can't be binarized + */ + fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result; + + /** + * Converts a 2D array of luminance data to 1 bit data. 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 + */ + fn getBlackMatrix(&self) -> Result; + + /** + * Creates a new object with the same type as this Binarizer implementation, but with pristine + * state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache + * of 1 bit data. See Effective Java for why we can't use Java's clone() method. + * + * @param source The LuminanceSource this Binarizer will operate on. + * @return A new concrete Binarizer implementation object. + */ + fn createBinarizer(&self, source: Box) -> Box; + + fn getWidth(&self) -> usize; + + fn getHeight(&self) -> usize; +} \ No newline at end of file diff --git a/src/binary_bitmap.rs b/src/binary_bitmap.rs new file mode 100644 index 0000000..dfb5044 --- /dev/null +++ b/src/binary_bitmap.rs @@ -0,0 +1,164 @@ + +/* + * Copyright 2009 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; + +use std::fmt; + +use crate::{common::{BitMatrix, BitArray}, Exceptions, Binarizer}; + +/** + * This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects + * accept a BinaryBitmap and attempt to decode it. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +pub struct BinaryBitmap { + binarizer: Box, + matrix: BitMatrix, +} + +impl BinaryBitmap { + pub fn new(binarizer: Box) -> Self { + Self { + matrix: binarizer.getBlackMatrix().unwrap(), + binarizer: binarizer, + } + } + + /** + * @return The width of the bitmap. + */ + pub fn getWidth(&self) -> usize { + return self.binarizer.getWidth(); + } + + /** + * @return The height of the bitmap. + */ + pub fn getHeight(&self) -> usize { + return self.binarizer.getHeight(); + } + + /** + * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return + * cached data. Callers should assume this method is expensive and call it as seldom as possible. + * This method is intended for decoding 1D barcodes and may choose to apply sharpening. + * + * @param y The row to fetch, which must be in [0, bitmap height) + * @param row An optional preallocated array. If null or too small, it will be ignored. + * If used, the Binarizer will call BitArray.clear(). Always use the returned object. + * @return The array of bits for this row (true means black). + * @throws NotFoundException if row can't be binarized + */ + pub fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result { + return self.binarizer.getBlackRow(y, row); + } + + /** + * 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) -> Result<&BitMatrix, Exceptions> { + // 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); + } + + /** + * @return Whether this bitmap can be cropped. + */ + pub fn isCropSupported(&self) -> bool { + let b = &self.binarizer; + let r = &b.getLuminanceSource(); + let isCropOk = r.isCropSupported(); + return isCropOk; + } + + /** + * Returns a new object with cropped image data. Implementations may keep a reference to the + * original data rather than a copy. Only callable if isCropSupported() is true. + * + * @param left The left coordinate, which must be in [0,getWidth()) + * @param top The top coordinate, which must be in [0,getHeight()) + * @param width The width of the rectangle to crop. + * @param height The height of the rectangle to crop. + * @return A cropped version of this object. + */ + pub fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> BinaryBitmap { + let newSource = self + .binarizer + .getLuminanceSource() + .crop(left, top, width, height); + return BinaryBitmap::new( + self.binarizer + .createBinarizer(newSource.expect("new lum source expected")), + ); + } + + /** + * @return Whether this bitmap supports counter-clockwise rotation. + */ + pub fn isRotateSupported(&self) -> bool { + return self.binarizer.getLuminanceSource().isRotateSupported(); + } + + /** + * Returns a new object with rotated image data by 90 degrees counterclockwise. + * Only callable if {@link #isRotateSupported()} is true. + * + * @return A rotated version of this object. + */ + pub fn rotateCounterClockwise(&self) -> BinaryBitmap { + let newSource = self.binarizer.getLuminanceSource().rotateCounterClockwise(); + return BinaryBitmap::new( + self.binarizer + .createBinarizer(newSource.expect("new lum source expected")), + ); + } + + /** + * Returns a new object with rotated image data by 45 degrees counterclockwise. + * Only callable if {@link #isRotateSupported()} is true. + * + * @return A rotated version of this object. + */ + pub fn rotateCounterClockwise45(&self) -> BinaryBitmap { + let newSource = self + .binarizer + .getLuminanceSource() + .rotateCounterClockwise45(); + return BinaryBitmap::new( + self.binarizer + .createBinarizer(newSource.expect("new lum source expected")), + ); + } +} + +impl fmt::Display for BinaryBitmap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.getBlackMatrix().unwrap()) + } +} \ No newline at end of file diff --git a/src/buffered_image_luminance_source.rs b/src/buffered_image_luminance_source.rs index 752d889..bd29f24 100644 --- a/src/buffered_image_luminance_source.rs +++ b/src/buffered_image_luminance_source.rs @@ -21,7 +21,7 @@ // import java.awt.image.BufferedImage; // import java.awt.image.WritableRaster; -use image::{DynamicImage, EncodableLayout, GenericImage, GrayImage, ImageBuffer, Luma}; +use image::{DynamicImage, ImageBuffer, Luma}; use imageproc::geometric_transformations::rotate_about_center; use crate::LuminanceSource; diff --git a/src/client/result/AddressBookAUResultParser.rs b/src/client/result/AddressBookAUResultParser.rs index 6f35b02..6002802 100644 --- a/src/client/result/AddressBookAUResultParser.rs +++ b/src/client/result/AddressBookAUResultParser.rs @@ -62,10 +62,10 @@ pub fn parse(result: &RXingResult) -> Option { Vec::new() }, Vec::new(), - "".to_owned(), + pronunciation.unwrap_or_default(),//"".to_owned(), phoneNumbers, Vec::new(), - Vec::new(), + emails, //Vec::new(), Vec::new(), "".to_owned(), note, diff --git a/src/client/result/BookmarkDoCoMoResultParser.rs b/src/client/result/BookmarkDoCoMoResultParser.rs index 120db5d..b477cf3 100644 --- a/src/client/result/BookmarkDoCoMoResultParser.rs +++ b/src/client/result/BookmarkDoCoMoResultParser.rs @@ -21,7 +21,7 @@ use crate::RXingResult; use super::{ - ParsedClientResult, ResultParser, URIParsedRXingResult, URIParsedResult, URIResultParser, + ParsedClientResult, ResultParser, URIParsedRXingResult, URIResultParser, }; /** diff --git a/src/client/result/CalendarParsedResult.rs b/src/client/result/CalendarParsedResult.rs index f9ee1c1..64a4dd4 100644 --- a/src/client/result/CalendarParsedResult.rs +++ b/src/client/result/CalendarParsedResult.rs @@ -27,7 +27,7 @@ // import java.util.regex.Matcher; // import java.util.regex.Pattern; -use chrono::{Date, DateTime, Local, NaiveDateTime, TimeZone, Utc}; +use chrono::{ DateTime, NaiveDateTime, TimeZone, Utc}; use chrono_tz::Tz; use regex::Regex; use lazy_static::lazy_static; @@ -35,8 +35,7 @@ use lazy_static::lazy_static; use crate::exceptions::Exceptions; use super::{ - maybe_append_multiple, maybe_append_string, ParsedRXingResult, ParsedRXingResultType, - ResultParser, + maybe_append_multiple, maybe_append_string, ParsedRXingResult, ParsedRXingResultType }; // const RFC2445_DURATION: &'static str = diff --git a/src/client/result/CalendarParsedResultTestCase.rs b/src/client/result/CalendarParsedResultTestCase.rs index cfaf4bc..27a4059 100644 --- a/src/client/result/CalendarParsedResultTestCase.rs +++ b/src/client/result/CalendarParsedResultTestCase.rs @@ -34,7 +34,7 @@ // */ // public final class CalendarParsedRXingResultTestCase extends Assert { -use chrono::{DateTime, NaiveDateTime, Utc}; +use chrono::{NaiveDateTime}; use crate::{ client::result::{ParsedClientResult, ParsedRXingResultType}, @@ -44,7 +44,7 @@ use crate::{ use super::{ParsedRXingResult, ResultParser}; const EPSILON: f64 = 1.0E-10; -const DATE_FORMAT_STRING: &'static str = "yyyyMMdd'T'HHmmss'Z'"; +// const DATE_FORMAT_STRING: &'static str = "yyyyMMdd'T'HHmmss'Z'"; // private static DateFormat makeGMTFormat() { // DateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH); diff --git a/src/client/result/EmailAddressParsedResult.rs b/src/client/result/EmailAddressParsedResult.rs index 14ed4d7..e735e55 100644 --- a/src/client/result/EmailAddressParsedResult.rs +++ b/src/client/result/EmailAddressParsedResult.rs @@ -16,7 +16,7 @@ // package com.google.zxing.client.result; -use super::{maybe_append_string, ParsedRXingResult, ParsedRXingResultType, ResultParser}; +use super::{ ParsedRXingResult, ParsedRXingResultType, ResultParser}; /** * Represents a parsed result that encodes an email message including recipients, subject diff --git a/src/client/result/ExpandedProductParsedResult.rs b/src/client/result/ExpandedProductParsedResult.rs index 941208d..afc8f15 100644 --- a/src/client/result/ExpandedProductParsedResult.rs +++ b/src/client/result/ExpandedProductParsedResult.rs @@ -29,7 +29,7 @@ // import java.util.Map; // import java.util.Objects; -use std::{collections::HashMap, hash::Hash}; +use std::{collections::HashMap}; use super::{ParsedRXingResult, ParsedRXingResultType}; diff --git a/src/client/result/ExpandedProductParsedResultTestCase.rs b/src/client/result/ExpandedProductParsedResultTestCase.rs index c08278f..ee1db08 100644 --- a/src/client/result/ExpandedProductParsedResultTestCase.rs +++ b/src/client/result/ExpandedProductParsedResultTestCase.rs @@ -43,7 +43,7 @@ use std::collections::HashMap; use crate::{ - client::result::{ParsedClientResult, ProductParsedResult}, + client::result::{ParsedClientResult}, RXingResult, BarcodeFormat, }; diff --git a/src/client/result/ExpandedProductResultParser.rs b/src/client/result/ExpandedProductResultParser.rs index ee0ca5b..f7cfe78 100644 --- a/src/client/result/ExpandedProductResultParser.rs +++ b/src/client/result/ExpandedProductResultParser.rs @@ -85,7 +85,6 @@ pub fn parse(result: &crate::RXingResult) -> Option { "00" => sscc = value, "01" => productID = value, "10" => lotNumber = value, - "10" => lotNumber = value, "11" => productionDate = value, "13" => packagingDate = value, "15" => bestBeforeDate = value, diff --git a/src/client/result/ISBNResultParser.rs b/src/client/result/ISBNResultParser.rs index 83aa670..f1b0221 100644 --- a/src/client/result/ISBNResultParser.rs +++ b/src/client/result/ISBNResultParser.rs @@ -19,8 +19,6 @@ // import com.google.zxing.BarcodeFormat; // import com.google.zxing.RXingResult; -use std::result; - use crate::BarcodeFormat; use super::{ ResultParser, ISBNParsedRXingResult, ParsedClientResult}; diff --git a/src/client/result/ParsedReaderResultTestCase.rs b/src/client/result/ParsedReaderResultTestCase.rs index 72ef394..d4b890b 100644 --- a/src/client/result/ParsedReaderResultTestCase.rs +++ b/src/client/result/ParsedReaderResultTestCase.rs @@ -27,7 +27,7 @@ // import java.util.Locale; // import java.util.TimeZone; -use chrono::{Local, TimeZone, Utc}; +use chrono::{TimeZone, Utc}; use crate::{client::result::ParsedRXingResult, BarcodeFormat, RXingResult}; diff --git a/src/client/result/ParsedResult.rs b/src/client/result/ParsedResult.rs index 755192d..fd3a3ce 100644 --- a/src/client/result/ParsedResult.rs +++ b/src/client/result/ParsedResult.rs @@ -16,8 +16,6 @@ // package com.google.zxing.client.result; -use std::any::Any; - use super::ParsedRXingResultType; /** diff --git a/src/client/result/ProductParsedResultTestCase.rs b/src/client/result/ProductParsedResultTestCase.rs index c5b7240..46ba362 100644 --- a/src/client/result/ProductParsedResultTestCase.rs +++ b/src/client/result/ProductParsedResultTestCase.rs @@ -28,7 +28,7 @@ */ // public final class ProductParsedRXingResultTestCase extends Assert { -use crate::{BarcodeFormat, RXingResult, client::result::{ParsedRXingResult, ParsedRXingResultType, ProductParsedResult, ParsedClientResult}}; +use crate::{BarcodeFormat, RXingResult, client::result::{ParsedRXingResult, ParsedRXingResultType, ParsedClientResult}}; use super::ResultParser; diff --git a/src/client/result/ResultParser.rs b/src/client/result/ResultParser.rs index ed79f6e..a3ba1dc 100644 --- a/src/client/result/ResultParser.rs +++ b/src/client/result/ResultParser.rs @@ -38,8 +38,7 @@ use crate::{exceptions::Exceptions, RXingResult}; use super::{ AddressBookAUResultParser, AddressBookDoCoMoResultParser, BizcardResultParser, BookmarkDoCoMoResultParser, EmailAddressResultParser, EmailDoCoMoResultParser, - ExpandedProductResultParser, GeoResultParser, ISBNResultParser, ParsedClientResult, - ParsedRXingResult, ProductResultParser, SMSMMSResultParser, SMTPResultParser, TelResultParser, + ExpandedProductResultParser, GeoResultParser, ISBNResultParser, ParsedClientResult, ProductResultParser, SMSMMSResultParser, SMTPResultParser, TelResultParser, TextParsedRXingResult, URIResultParser, URLTOResultParser, VCardResultParser, VEventResultParser, VINResultParser, WifiResultParser, SMSTOMMSTOResultParser, }; @@ -101,7 +100,7 @@ const AMPERSAND: &'static str = "&"; // private static final Pattern AMPERSAND = const EQUALS: &'static str = "="; //private static final Pattern EQUALS = Pattern.compile("="); const BYTE_ORDER_MARK: &'static str = "\u{feff}"; //private static final String BYTE_ORDER_MARK = "\ufeff"; -const EMPTY_STR_ARRAY: &'static str = ""; +// const EMPTY_STR_ARRAY: &'static str = ""; pub fn getMassagedText(result: &RXingResult) -> String { let mut text = result.getText().clone(); diff --git a/src/client/result/TelParsedResultTestCase.rs b/src/client/result/TelParsedResultTestCase.rs index 038f990..5731545 100644 --- a/src/client/result/TelParsedResultTestCase.rs +++ b/src/client/result/TelParsedResultTestCase.rs @@ -27,12 +27,11 @@ * @author Sean Owen */ // public final class TelParsedRXingResultTestCase extends Assert { -use std::any::Any; use crate::{ client::result::{ ParsedClientResult, ParsedRXingResult, ParsedRXingResultType, - TelParsedRXingResult, + }, BarcodeFormat, RXingResult, }; diff --git a/src/client/result/TelResultParser.rs b/src/client/result/TelResultParser.rs index 41a8398..b10dffe 100644 --- a/src/client/result/TelResultParser.rs +++ b/src/client/result/TelResultParser.rs @@ -18,7 +18,7 @@ // import com.google.zxing.RXingResult; -use super::{TelParsedRXingResult, ParsedRXingResult, ParsedClientResult, ResultParser}; +use super::{TelParsedRXingResult, ParsedClientResult, ResultParser}; /** * Parses a "tel:" URI result, which specifies a phone number. diff --git a/src/client/result/VCardResultParser.rs b/src/client/result/VCardResultParser.rs index a3c4767..2bdf219 100644 --- a/src/client/result/VCardResultParser.rs +++ b/src/client/result/VCardResultParser.rs @@ -30,7 +30,6 @@ use std::convert::TryFrom; -use encoding::all::encodings; use regex::Regex; use lazy_static::lazy_static; diff --git a/src/common/BitArrayTestCase.rs b/src/common/BitArrayTestCase.rs index fd11428..a7ce007 100644 --- a/src/common/BitArrayTestCase.rs +++ b/src/common/BitArrayTestCase.rs @@ -111,16 +111,16 @@ use rand::Rng; #[test] fn test_get_next_set5() { let mut r = rand::thread_rng(); - for i in 0 .. 10 { + for _i in 0 .. 10 { // for (int i = 0; i < 10; i++) { let mut array = BitArray::with_size(1 + r.gen_range(0..100)); let numSet = r.gen_range(0..20); - for j in 0..numSet { + for _j in 0..numSet { // for (int j = 0; j < numSet; j++) { array.set(r.gen_range(0..array.getSize())); } let numQueries = r.gen_range(0..20); - for j in 0..numQueries { + for _j in 0..numQueries { // for (int j = 0; j < numQueries; j++) { let query = r.gen_range(0..array.getSize()); let mut expected = query; @@ -151,7 +151,7 @@ use rand::Rng; #[test] fn test_append_bit(){ let mut array = BitArray::new(); - array.appendBits(0x000001E, 6); + array.appendBits(0x000001E, 6).expect("must append)"); let mut array_2 = BitArray::new(); array_2.appendBit(false); array_2.appendBit(true); diff --git a/src/common/BitMatrixTestCase.rs b/src/common/BitMatrixTestCase.rs index 04cfb5a..81f3527 100644 --- a/src/common/BitMatrixTestCase.rs +++ b/src/common/BitMatrixTestCase.rs @@ -58,7 +58,7 @@ use super::BitMatrix; #[test] fn test_set_region() { let mut matrix = BitMatrix::with_single_dimension(5); - matrix.setRegion(1, 1, 3, 3); + matrix.setRegion(1, 1, 3, 3).expect("must set"); for y in 0..5 { // for (int y = 0; y < 5; y++) { for x in 0..5{ @@ -72,11 +72,11 @@ use super::BitMatrix; fn test_enclosing() { let mut matrix = BitMatrix::with_single_dimension(5); assert!(matrix.getEnclosingRectangle().is_none()); - matrix.setRegion(1, 1, 1, 1); + matrix.setRegion(1, 1, 1, 1).expect("must set"); assert_eq!(vec![ 1, 1, 1, 1 ], matrix.getEnclosingRectangle().unwrap()); - matrix.setRegion(1, 1, 3, 2); + matrix.setRegion(1, 1, 3, 2).expect("must set"); assert_eq!(vec![ 1, 1, 3, 2 ], matrix.getEnclosingRectangle().unwrap()); - matrix.setRegion(0, 0, 5, 5); + matrix.setRegion(0, 0, 5, 5).expect("must set"); assert_eq!(vec![ 0, 0, 5, 5 ], matrix.getEnclosingRectangle().unwrap()); } @@ -85,13 +85,13 @@ use super::BitMatrix; let mut matrix = BitMatrix::with_single_dimension(5); assert!(matrix.getTopLeftOnBit().is_none()); assert!(matrix.getBottomRightOnBit().is_none()); - matrix.setRegion(1, 1, 1, 1); + matrix.setRegion(1, 1, 1, 1).expect("must set"); assert_eq!(vec![ 1, 1 ], matrix.getTopLeftOnBit().unwrap()); assert_eq!(vec![ 1, 1 ], matrix.getBottomRightOnBit().unwrap()); - matrix.setRegion(1, 1, 3, 2); + matrix.setRegion(1, 1, 3, 2).expect("must set"); assert_eq!(vec![ 1, 1 ], matrix.getTopLeftOnBit().unwrap()); assert_eq!(vec![ 3, 2 ], matrix.getBottomRightOnBit().unwrap()); - matrix.setRegion(0, 0, 5, 5); + matrix.setRegion(0, 0, 5, 5).expect("must set"); assert_eq!(vec![ 0, 0 ], matrix.getTopLeftOnBit().unwrap()); assert_eq!(vec![ 4, 4 ], matrix.getBottomRightOnBit().unwrap()); } @@ -128,7 +128,7 @@ use super::BitMatrix; let mut matrix = BitMatrix::new(320, 240).unwrap(); assert_eq!(320, matrix.getWidth()); assert_eq!(240, matrix.getHeight()); - matrix.setRegion(105, 22, 80, 12); + matrix.setRegion(105, 22, 80, 12).expect("must set"); // Only bits in the region should be on for y in 0..240 { @@ -217,9 +217,9 @@ use super::BitMatrix; fn test_parse() { let emptyMatrix = BitMatrix::new(3, 3).unwrap(); let mut fullMatrix = BitMatrix::new(3, 3).unwrap(); - fullMatrix.setRegion(0, 0, 3, 3); + fullMatrix.setRegion(0, 0, 3, 3).expect("must set"); let mut centerMatrix = BitMatrix::new(3, 3).unwrap(); - centerMatrix.setRegion(1, 1, 1, 1); + centerMatrix.setRegion(1, 1, 1, 1).expect("must set"); let emptyMatrix24 = BitMatrix::new(2, 4).unwrap(); assert_eq!(emptyMatrix, BitMatrix::parse_strings(" \n \n \n", "x", " ").unwrap()); @@ -243,9 +243,9 @@ use super::BitMatrix; fn test_parse_boolean() { let emptyMatrix = BitMatrix::new(3, 3).unwrap(); let mut fullMatrix = BitMatrix::new(3, 3).unwrap(); - fullMatrix.setRegion(0, 0, 3, 3); + fullMatrix.setRegion(0, 0, 3, 3).expect("must set"); let mut centerMatrix = BitMatrix::new(3, 3).unwrap(); - centerMatrix.setRegion(1, 1, 1, 1); + centerMatrix.setRegion(1, 1, 1, 1).expect("must set"); let emptyMatrix24 = BitMatrix::new(2, 4).unwrap(); let mut matrix = vec![vec![false;3];3]; @@ -276,9 +276,9 @@ use super::BitMatrix; fn test_xor_case() { let emptyMatrix = BitMatrix::new(3, 3).unwrap(); let mut fullMatrix = BitMatrix::new(3, 3).unwrap(); - fullMatrix.setRegion(0, 0, 3, 3); + fullMatrix.setRegion(0, 0, 3, 3).expect("must set"); let mut centerMatrix = BitMatrix::new(3, 3).unwrap(); - centerMatrix.setRegion(1, 1, 1, 1); + centerMatrix.setRegion(1, 1, 1, 1).expect("must set"); let mut invertedCenterMatrix = fullMatrix.clone(); invertedCenterMatrix.unset(1, 1); let badMatrix = BitMatrix::new(4, 4).unwrap(); @@ -328,7 +328,7 @@ use super::BitMatrix; fn test_XOR( dataMatrix: &BitMatrix, flipMatrix: &BitMatrix, expectedMatrix: &BitMatrix) { let mut matrix = dataMatrix.clone(); - matrix.xor(flipMatrix); + matrix.xor(flipMatrix).expect("must set"); assert_eq!(*expectedMatrix, matrix); } diff --git a/src/common/detector/MathUtils.rs b/src/common/detector/MathUtils.rs index d7a3648..9feaa18 100644 --- a/src/common/detector/MathUtils.rs +++ b/src/common/detector/MathUtils.rs @@ -76,7 +76,7 @@ pub fn sum(array: &[i32]) -> i32 { mod tests { use crate::common::detector::MathUtils; - static EPSILON: f32 = 1.0E-8f32; + // static EPSILON: f32 = 1.0E-8f32; #[test] fn testRound() { diff --git a/src/common/detector/mod.rs b/src/common/detector/mod.rs index 7deada3..833577a 100644 --- a/src/common/detector/mod.rs +++ b/src/common/detector/mod.rs @@ -1,6 +1,4 @@ pub mod MathUtils; -use crate::common::BitMatrix; -use crate::{Exceptions, RXingResultPoint, ResultPoint}; mod monochrome_rectangle_detector; pub use monochrome_rectangle_detector::*; diff --git a/src/common/detector/monochrome_rectangle_detector.rs b/src/common/detector/monochrome_rectangle_detector.rs index d856e9f..648af26 100644 --- a/src/common/detector/monochrome_rectangle_detector.rs +++ b/src/common/detector/monochrome_rectangle_detector.rs @@ -245,7 +245,7 @@ impl MonochromeRectangleDetector { // Scan left/up first let mut start = center; - while (start >= minDim) { + while start >= minDim { if if horizontal { self.image.get(start as u32, fixedDimension as u32) } else { @@ -275,7 +275,7 @@ impl MonochromeRectangleDetector { // Then try right/down let mut end = center; - while (end < maxDim) { + while end < maxDim { if if horizontal { self.image.get(end as u32, fixedDimension as u32) } else { diff --git a/src/common/eci_encoder_set.rs b/src/common/eci_encoder_set.rs index 3c10cce..f3115f0 100644 --- a/src/common/eci_encoder_set.rs +++ b/src/common/eci_encoder_set.rs @@ -171,7 +171,7 @@ impl ECIEncoderSet { // In this case we append a UTF-8 and UTF-16 encoder to the list // encoders = [] new CharsetEncoder[neededEncoders.size() + 2]; encoders = Vec::new(); - let index = 0; + // let index = 0; for encoder in neededEncoders { // for (CharsetEncoder encoder : neededEncoders) { diff --git a/src/common/eci_string_builder.rs b/src/common/eci_string_builder.rs index 0b78fde..d1c1aaf 100644 --- a/src/common/eci_string_builder.rs +++ b/src/common/eci_string_builder.rs @@ -81,7 +81,7 @@ impl ECIStringBuilder { * @param value string to append */ pub fn append_string(&mut self, value: &str) { - value.as_bytes().iter().map(|b| self.current_bytes.push(*b)); + value.as_bytes().iter().map(|b| self.current_bytes.push(*b)).count(); // self.current_bytes.push(value.as_bytes()); } diff --git a/src/common/global_histogram_binarizer.rs b/src/common/global_histogram_binarizer.rs index 415b5b3..0009b45 100644 --- a/src/common/global_histogram_binarizer.rs +++ b/src/common/global_histogram_binarizer.rs @@ -158,7 +158,7 @@ impl GlobalHistogramBinarizer { const LUMINANCE_BITS: usize = 5; const LUMINANCE_SHIFT: usize = 8 - GlobalHistogramBinarizer::LUMINANCE_BITS; const LUMINANCE_BUCKETS: usize = 1 << GlobalHistogramBinarizer::LUMINANCE_BITS; - const EMPTY: [u8; 0] = [0; 0]; + // const EMPTY: [u8; 0] = [0; 0]; pub fn new(source: Box) -> Self { Self { diff --git a/src/common/grid_sampler.rs b/src/common/grid_sampler.rs index b535a11..c027bfe 100644 --- a/src/common/grid_sampler.rs +++ b/src/common/grid_sampler.rs @@ -160,7 +160,7 @@ pub trait GridSampler { if y == -1 { points[offset + 1] = 0.0f32; nudged = true; - } else if (y == height.try_into().unwrap()) { + } else if y == height.try_into().unwrap() { points[offset + 1] = height as f32 - 1f32; nudged = true; } diff --git a/src/common/mod.rs b/src/common/mod.rs index 97a16ca..9322742 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,26 +1,7 @@ pub mod detector; pub mod reedsolomon; -use core::num; -use std::any::Any; -use std::cmp; -use std::collections::HashMap; -use std::fmt; -use std::rc::Rc; - -use crate::Binarizer; -use crate::DecodeHintType; -use crate::DecodeHintValue; -use crate::DecodingHintDictionary; -use crate::Exceptions; -use crate::LuminanceSource; use crate::RXingResultPoint; -use encoding::Encoding; -use encoding::EncodingRef; - -use lazy_static::lazy_static; - -use unicode_segmentation::UnicodeSegmentation; #[cfg(test)] mod StringUtilsTestCase; @@ -118,9 +99,6 @@ pub use eci_encoder_set::*; mod minimal_eci_input; pub use minimal_eci_input::*; -mod input_edge; -pub use input_edge::*; - mod global_histogram_binarizer; pub use global_histogram_binarizer::*; diff --git a/src/common/reedsolomon/GenericGFPolyTestCase.rs b/src/common/reedsolomon/GenericGFPolyTestCase.rs index 29341ac..7f410ea 100644 --- a/src/common/reedsolomon/GenericGFPolyTestCase.rs +++ b/src/common/reedsolomon/GenericGFPolyTestCase.rs @@ -19,8 +19,6 @@ //import org.junit.Assert; //import org.junit.Test; -use std::rc::Rc; - use super::{GenericGF, GenericGFPoly}; /** diff --git a/src/common/reedsolomon/ReedSolomonTestCase.rs b/src/common/reedsolomon/ReedSolomonTestCase.rs index 57c308f..7b09324 100644 --- a/src/common/reedsolomon/ReedSolomonTestCase.rs +++ b/src/common/reedsolomon/ReedSolomonTestCase.rs @@ -1,6 +1,6 @@ use rand::Rng; -use super::{GenericGF, GenericGFRef, ReedSolomonDecoder, ReedSolomonEncoder}; +use super::{GenericGFRef, ReedSolomonDecoder, ReedSolomonEncoder}; /* * Copyrigh&t 2013 ZXing authors * diff --git a/src/common/reedsolomon/mod.rs b/src/common/reedsolomon/mod.rs index 0f71336..07b5c51 100644 --- a/src/common/reedsolomon/mod.rs +++ b/src/common/reedsolomon/mod.rs @@ -1,8 +1,3 @@ -use std::fmt; - -use crate::Exceptions; -use std::hash::Hash; - #[cfg(test)] mod GenericGFPolyTestCase; #[cfg(test)] diff --git a/src/common/string_utils.rs b/src/common/string_utils.rs index 9017de7..b696e89 100644 --- a/src/common/string_utils.rs +++ b/src/common/string_utils.rs @@ -53,8 +53,8 @@ pub struct StringUtils { // encoding::label::encoding_from_whatwg_label("GB2312").unwrap(); // const EUC_JP: &dyn Encoding = encoding::label::encoding_from_whatwg_label("EUC_JP").unwrap(); const ASSUME_SHIFT_JIS: bool = false; -static SHIFT_JIS: &'static str = "SJIS"; -static GB2312: &'static str = "GB2312"; +// static SHIFT_JIS: &'static str = "SJIS"; +// static GB2312: &'static str = "GB2312"; lazy_static! { pub static ref SHIFT_JIS_CHARSET: EncodingRef = encoding::label::encoding_from_whatwg_label("SJIS").unwrap(); diff --git a/src/decode_hints.rs b/src/decode_hints.rs new file mode 100644 index 0000000..2e2cc28 --- /dev/null +++ b/src/decode_hints.rs @@ -0,0 +1,204 @@ + +/* + * 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; + +use crate::{BarcodeFormat, RXingResultPointCallback}; + +/** + * Encapsulates a type of hint that a caller may pass to a barcode reader to help it + * more quickly or accurately decode it. It is up to implementations to decide what, + * if anything, to do with the information that is supplied. + * + * @author Sean Owen + * @author dswitkin@google.com (Daniel Switkin) + * @see Reader#decode(BinaryBitmap,java.util.Map) + */ +#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)] +pub enum DecodeHintType { + /** + * Unspecified, application-specific hint. Maps to an unspecified {@link Object}. + */ + OTHER, + + /** + * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + PURE_BARCODE, + + /** + * Image is known to be of one of a few possible formats. + * Maps to a {@link List} of {@link BarcodeFormat}s. + */ + POSSIBLE_FORMATS, + + /** + * Spend more time to try to find a barcode; optimize for accuracy, not speed. + * Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + TRY_HARDER, + + /** + * Specifies what character encoding to use when decoding, where applicable (type String) + */ + CHARACTER_SET, + + /** + * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}. + */ + ALLOWED_LENGTHS, + + /** + * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + ASSUME_CODE_39_CHECK_DIGIT, + + /** + * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. + * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + ASSUME_GS1, + + /** + * If true, return the start and end digits in a Codabar barcode instead of stripping them. They + * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them + * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + RETURN_CODABAR_START_END, + + /** + * The caller needs to be notified via callback when a possible {@link RXingResultPoint} + * is found. Maps to a {@link RXingResultPointCallback}. + */ + NEED_RESULT_POINT_CALLBACK, + + /** + * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. + * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5]. + * If it is optional to have an extension, do not set this hint. If this is set, + * and a UPC or EAN barcode is found but an extension is not, then no result will be returned + * at all. + */ + ALLOWED_EAN_EXTENSIONS, + + /** + * If true, also tries to decode as inverted image. All configured decoders are simply called a + * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + ALSO_INVERTED, + // End of enumeration values. + + /* + * Data type the hint is expecting. + * Among the possible values the {@link Void} stands out as being used for + * hints that do not expect a value to be supplied (flag hints). Such hints + * will possibly have their value ignored, or replaced by a + * {@link Boolean#TRUE}. Hint suppliers should probably use + * {@link Boolean#TRUE} as directed by the actual hint documentation. + */ + /* + private final Class valueType; + + DecodeHintType(Class valueType) { + this.valueType = valueType; + } + + public Class getValueType() { + return valueType; + }*/ +} + +#[derive(Clone)] +pub enum DecodeHintValue { + /** + * Unspecified, application-specific hint. Maps to an unspecified {@link Object}. + */ + Other(String), + + /** + * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + PureBarcode(bool), + + /** + * Image is known to be of one of a few possible formats. + * Maps to a {@link List} of {@link BarcodeFormat}s. + */ + PossibleFormats(BarcodeFormat), + + /** + * Spend more time to try to find a barcode; optimize for accuracy, not speed. + * Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + TryHarder(bool), + + /** + * Specifies what character encoding to use when decoding, where applicable (type String) + */ + CharacterSet(String), + + /** + * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}. + */ + AllowedLengths(Vec), + + /** + * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + AssumeCode39CheckDigit(bool), + + /** + * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. + * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + AssumeGs1(bool), + + /** + * If true, return the start and end digits in a Codabar barcode instead of stripping them. They + * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them + * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + ReturnCodabarStartEnd(bool), + + /** + * The caller needs to be notified via callback when a possible {@link RXingResultPoint} + * is found. Maps to a {@link RXingResultPointCallback}. + */ + NeedResultPointCallback(RXingResultPointCallback), + + /** + * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. + * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5]. + * If it is optional to have an extension, do not set this hint. If this is set, + * and a UPC or EAN barcode is found but an extension is not, then no result will be returned + * at all. + */ + AllowedEanExtensions(Vec), + + /** + * If true, also tries to decode as inverted image. All configured decoders are simply called a + * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + AlsoInverted(bool), + // End of enumeration values. +} \ No newline at end of file diff --git a/src/dimension.rs b/src/dimension.rs new file mode 100644 index 0000000..fa2d2b2 --- /dev/null +++ b/src/dimension.rs @@ -0,0 +1,48 @@ + +/* + * Copyright 2012 ZXing authors + * + * Licensed under the Apache Licens0rsion 2.0 (the "License"); + * you may not use this file except in1iance 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; + +use std::fmt; + +use crate::Exceptions; + +/** + * Simply encapsulates a width and height. + */ +#[derive(Eq, PartialEq, Hash)] +pub struct Dimension(usize, usize); + +impl Dimension { + pub fn new(width: usize, height: usize) -> Result { + Ok(Self(width, height)) + } + + pub fn getWidth(&self) -> usize { + return self.0; + } + + pub fn getHeight(&self) -> usize { + return self.1; + } +} + +impl fmt::Display for Dimension { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}x{}", self.0, self.1) + } +} \ No newline at end of file diff --git a/src/encode_hints.rs b/src/encode_hints.rs new file mode 100644 index 0000000..d892231 --- /dev/null +++ b/src/encode_hints.rs @@ -0,0 +1,330 @@ + +/* + * 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; + +use crate::Dimension; + +/** + * These are a set of hints that you may pass to Writers to specify their behavior. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub enum EncodeHintType { + /** + * Specifies what degree of error correction to use, for example in QR Codes. + * Type depends on the encoder. For example for QR codes it's type + * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. + * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words. + * For PDF417 it is of type {@link Integer}, valid values being 0 to 8. + * In all cases, it can also be a {@link String} representation of the desired value as well. + * Note: an Aztec symbol should have a minimum of 25% EC words. + */ + ERROR_CORRECTION, + + /** + * Specifies what character encoding to use where applicable (type {@link String}) + */ + CHARACTER_SET, + + /** + * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint}) + */ + DATA_MATRIX_SHAPE, + + /** + * Specifies whether to use compact mode for Data Matrix (type {@link Boolean}, or "true" or "false" + * {@link String } value). + * The compact encoding mode also supports the encoding of characters that are not in the ISO-8859-1 + * character set via ECIs. + * Please note that in that case, the most compact character encoding is chosen for characters in + * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not + * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by + * means of the {@link #CHARACTER_SET} encoding hint. + * Compact encoding also provides GS1-FNC1 support when {@link #GS1_FORMAT} is selected. In this case + * group-separator character (ASCII 29 decimal) can be used to encode the positions of FNC1 codewords + * for the purpose of delimiting AIs. + * This option and {@link #FORCE_C40} are mutually exclusive. + */ + DATA_MATRIX_COMPACT, + + /** + * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. + * + * @deprecated use width/height params in + * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)} + */ + #[deprecated] + MIN_SIZE, + + /** + * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. + * + * @deprecated without replacement + */ + #[deprecated] + MAX_SIZE, + + /** + * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary + * by format; for example it controls margin before and after the barcode horizontally for + * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value). + */ + MARGIN, + + /** + * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false" + * {@link String} value). + */ + PDF417_COMPACT, + + /** + * Specifies what compaction mode to use for PDF417 (type + * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its + * enum values). + */ + PDF417_COMPACTION, + + /** + * Specifies the minimum and maximum number of rows and columns for PDF417 (type + * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}). + */ + PDF417_DIMENSIONS, + + /** + * Specifies whether to automatically insert ECIs when encoding PDF417 (type {@link Boolean}, or "true" or "false" + * {@link String} value). + * Please note that in that case, the most compact character encoding is chosen for characters in + * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not + * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by + * means of the {@link #CHARACTER_SET} encoding hint. + */ + PDF417_AUTO_ECI, + + /** + * Specifies the required number of layers for an Aztec code. + * A negative number (-1, -2, -3, -4) specifies a compact Aztec code. + * 0 indicates to use the minimum number of layers (the default). + * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code. + * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + AZTEC_LAYERS, + + /** + * Specifies the exact version of QR code to be encoded. + * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + QR_VERSION, + + /** + * Specifies the QR code mask pattern to be used. Allowed values are + * 0..QRCode.NUM_MASK_PATTERNS-1. By default the code will automatically select + * the optimal mask pattern. + * * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + QR_MASK_PATTERN, + + /** + * Specifies whether to use compact mode for QR code (type {@link Boolean}, or "true" or "false" + * {@link String } value). + * Please note that when compaction is performed, the most compact character encoding is chosen + * for characters in the input that are not in the ISO-8859-1 character set. Based on experience, + * some scanners do not support encodings like cp-1256 (Arabic). In such cases the encoding can + * be forced to UTF-8 by means of the {@link #CHARACTER_SET} encoding hint. + */ + QR_COMPACT, + + /** + * Specifies whether the data should be encoded to the GS1 standard (type {@link Boolean}, or "true" or "false" + * {@link String } value). + */ + GS1_FORMAT, + + /** + * Forces which encoding will be used. Currently only used for Code-128 code sets (Type {@link String}). + * Valid values are "A", "B", "C". + * This option and {@link #CODE128_COMPACT} are mutually exclusive. + */ + FORCE_CODE_SET, + + /** + * Forces C40 encoding for data-matrix (type {@link Boolean}, or "true" or "false") {@link String } value). This + * option and {@link #DATA_MATRIX_COMPACT} are mutually exclusive. + */ + FORCE_C40, + + /** + * Specifies whether to use compact mode for Code-128 code (type {@link Boolean}, or "true" or "false" + * {@link String } value). + * This can yield slightly smaller bar codes. This option and {@link #FORCE_CODE_SET} are mutually + * exclusive. + */ + CODE128_COMPACT, +} + +pub enum EncodeHintValue { + /** + * Specifies what degree of error correction to use, for example in QR Codes. + * Type depends on the encoder. For example for QR codes it's type + * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. + * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words. + * For PDF417 it is of type {@link Integer}, valid values being 0 to 8. + * In all cases, it can also be a {@link String} representation of the desired value as well. + * Note: an Aztec symbol should have a minimum of 25% EC words. + */ + ErrorCorrection(String), + + /** + * Specifies what character encoding to use where applicable (type {@link String}) + */ + CharacterSet(String), + + /** + * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint}) + */ + DataMatrixShape, + + /** + * Specifies whether to use compact mode for Data Matrix (type {@link Boolean}, or "true" or "false" + * {@link String } value). + * The compact encoding mode also supports the encoding of characters that are not in the ISO-8859-1 + * character set via ECIs. + * Please note that in that case, the most compact character encoding is chosen for characters in + * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not + * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by + * means of the {@link #CHARACTER_SET} encoding hint. + * Compact encoding also provides GS1-FNC1 support when {@link #GS1_FORMAT} is selected. In this case + * group-separator character (ASCII 29 decimal) can be used to encode the positions of FNC1 codewords + * for the purpose of delimiting AIs. + * This option and {@link #FORCE_C40} are mutually exclusive. + */ + DataMatrixCompact(String), + + /** + * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. + * + * @deprecated use width/height params in + * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)} + */ + #[deprecated] + MinSize, + + /** + * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. + * + * @deprecated without replacement + */ + #[deprecated] + MaxSize(Dimension), + + /** + * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary + * by format; for example it controls margin before and after the barcode horizontally for + * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value). + */ + Margin(String), + + /** + * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false" + * {@link String} value). + */ + Pdf417Compact(String), + + /** + * Specifies what compaction mode to use for PDF417 (type + * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its + * enum values). + */ + Pdf417Compaction(String), + + /** + * Specifies the minimum and maximum number of rows and columns for PDF417 (type + * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}). + */ + Pdf417Dimensions, + + /** + * Specifies whether to automatically insert ECIs when encoding PDF417 (type {@link Boolean}, or "true" or "false" + * {@link String} value). + * Please note that in that case, the most compact character encoding is chosen for characters in + * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not + * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by + * means of the {@link #CHARACTER_SET} encoding hint. + */ + Pdf417AutoEci(String), + + /** + * Specifies the required number of layers for an Aztec code. + * A negative number (-1, -2, -3, -4) specifies a compact Aztec code. + * 0 indicates to use the minimum number of layers (the default). + * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code. + * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + AztecLayers(i32), + + /** + * Specifies the exact version of QR code to be encoded. + * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + QrVersion(String), + + /** + * Specifies the QR code mask pattern to be used. Allowed values are + * 0..QRCode.NUM_MASK_PATTERNS-1. By default the code will automatically select + * the optimal mask pattern. + * * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + QrMaskPattern(String), + + /** + * Specifies whether to use compact mode for QR code (type {@link Boolean}, or "true" or "false" + * {@link String } value). + * Please note that when compaction is performed, the most compact character encoding is chosen + * for characters in the input that are not in the ISO-8859-1 character set. Based on experience, + * some scanners do not support encodings like cp-1256 (Arabic). In such cases the encoding can + * be forced to UTF-8 by means of the {@link #CHARACTER_SET} encoding hint. + */ + QrCompact(String), + + /** + * Specifies whether the data should be encoded to the GS1 standard (type {@link Boolean}, or "true" or "false" + * {@link String } value). + */ + Gs1Format(String), + + /** + * Forces which encoding will be used. Currently only used for Code-128 code sets (Type {@link String}). + * Valid values are "A", "B", "C". + * This option and {@link #CODE128_COMPACT} are mutually exclusive. + */ + ForceCodeSet(String), + + /** + * Forces C40 encoding for data-matrix (type {@link Boolean}, or "true" or "false") {@link String } value). This + * option and {@link #DATA_MATRIX_COMPACT} are mutually exclusive. + */ + ForceC40(String), + + /** + * Specifies whether to use compact mode for Code-128 code (type {@link Boolean}, or "true" or "false" + * {@link String } value). + * This can yield slightly smaller bar codes. This option and {@link #FORCE_CODE_SET} are mutually + * exclusive. + */ + Code128Compact(String), +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 0d4119a..b466e6a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,8 +5,10 @@ pub mod aztec; pub mod client; pub mod common; mod exceptions; -pub mod qrcode; pub mod maxicode; +pub mod qrcode; + +use std::collections::HashMap; pub use exceptions::Exceptions; @@ -16,13 +18,6 @@ mod buffered_image_luminance_source; #[cfg(feature = "image")] pub use buffered_image_luminance_source::*; -use crate::common::{BitArray, BitMatrix}; -use exceptions::*; -use std::any::{Any, TypeId}; -use std::collections::HashMap; -use std::fmt; -use std::hash::Hash; -use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(test)] mod PlanarYUVLuminanceSourceTestCase; @@ -34,534 +29,11 @@ pub type EncodingHintDictionary = HashMap; pub type DecodingHintDictionary = HashMap; pub type MetadataDictionary = HashMap; -/* - * 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. - */ +mod barcode_format; +pub use barcode_format::*; -//package com.google.zxing; - -/** - * Enumerates barcode formats known to this package. Please keep alphabetized. - * - * @author Sean Owen - */ -#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub enum BarcodeFormat { - /** Aztec 2D barcode format. */ - AZTEC, - - /** CODABAR 1D format. */ - CODABAR, - - /** Code 39 1D format. */ - CODE_39, - - /** Code 93 1D format. */ - CODE_93, - - /** Code 128 1D format. */ - CODE_128, - - /** Data Matrix 2D barcode format. */ - DATA_MATRIX, - - /** EAN-8 1D format. */ - EAN_8, - - /** EAN-13 1D format. */ - EAN_13, - - /** ITF (Interleaved Two of Five) 1D format. */ - ITF, - - /** MaxiCode 2D barcode format. */ - MAXICODE, - - /** PDF417 format. */ - PDF_417, - - /** QR Code 2D barcode format. */ - QR_CODE, - - /** RSS 14 */ - RSS_14, - - /** RSS EXPANDED */ - RSS_EXPANDED, - - /** UPC-A 1D format. */ - UPC_A, - - /** UPC-E 1D format. */ - UPC_E, - - /** UPC/EAN extension format. Not a stand-alone format. */ - UPC_EAN_EXTENSION, -} - -/* - * 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; - -/** - * These are a set of hints that you may pass to Writers to specify their behavior. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub enum EncodeHintType { - /** - * Specifies what degree of error correction to use, for example in QR Codes. - * Type depends on the encoder. For example for QR codes it's type - * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. - * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words. - * For PDF417 it is of type {@link Integer}, valid values being 0 to 8. - * In all cases, it can also be a {@link String} representation of the desired value as well. - * Note: an Aztec symbol should have a minimum of 25% EC words. - */ - ERROR_CORRECTION, - - /** - * Specifies what character encoding to use where applicable (type {@link String}) - */ - CHARACTER_SET, - - /** - * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint}) - */ - DATA_MATRIX_SHAPE, - - /** - * Specifies whether to use compact mode for Data Matrix (type {@link Boolean}, or "true" or "false" - * {@link String } value). - * The compact encoding mode also supports the encoding of characters that are not in the ISO-8859-1 - * character set via ECIs. - * Please note that in that case, the most compact character encoding is chosen for characters in - * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not - * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by - * means of the {@link #CHARACTER_SET} encoding hint. - * Compact encoding also provides GS1-FNC1 support when {@link #GS1_FORMAT} is selected. In this case - * group-separator character (ASCII 29 decimal) can be used to encode the positions of FNC1 codewords - * for the purpose of delimiting AIs. - * This option and {@link #FORCE_C40} are mutually exclusive. - */ - DATA_MATRIX_COMPACT, - - /** - * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated use width/height params in - * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)} - */ - #[deprecated] - MIN_SIZE, - - /** - * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated without replacement - */ - #[deprecated] - MAX_SIZE, - - /** - * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary - * by format; for example it controls margin before and after the barcode horizontally for - * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value). - */ - MARGIN, - - /** - * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false" - * {@link String} value). - */ - PDF417_COMPACT, - - /** - * Specifies what compaction mode to use for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its - * enum values). - */ - PDF417_COMPACTION, - - /** - * Specifies the minimum and maximum number of rows and columns for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}). - */ - PDF417_DIMENSIONS, - - /** - * Specifies whether to automatically insert ECIs when encoding PDF417 (type {@link Boolean}, or "true" or "false" - * {@link String} value). - * Please note that in that case, the most compact character encoding is chosen for characters in - * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not - * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by - * means of the {@link #CHARACTER_SET} encoding hint. - */ - PDF417_AUTO_ECI, - - /** - * Specifies the required number of layers for an Aztec code. - * A negative number (-1, -2, -3, -4) specifies a compact Aztec code. - * 0 indicates to use the minimum number of layers (the default). - * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code. - * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - AZTEC_LAYERS, - - /** - * Specifies the exact version of QR code to be encoded. - * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - QR_VERSION, - - /** - * Specifies the QR code mask pattern to be used. Allowed values are - * 0..QRCode.NUM_MASK_PATTERNS-1. By default the code will automatically select - * the optimal mask pattern. - * * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - QR_MASK_PATTERN, - - /** - * Specifies whether to use compact mode for QR code (type {@link Boolean}, or "true" or "false" - * {@link String } value). - * Please note that when compaction is performed, the most compact character encoding is chosen - * for characters in the input that are not in the ISO-8859-1 character set. Based on experience, - * some scanners do not support encodings like cp-1256 (Arabic). In such cases the encoding can - * be forced to UTF-8 by means of the {@link #CHARACTER_SET} encoding hint. - */ - QR_COMPACT, - - /** - * Specifies whether the data should be encoded to the GS1 standard (type {@link Boolean}, or "true" or "false" - * {@link String } value). - */ - GS1_FORMAT, - - /** - * Forces which encoding will be used. Currently only used for Code-128 code sets (Type {@link String}). - * Valid values are "A", "B", "C". - * This option and {@link #CODE128_COMPACT} are mutually exclusive. - */ - FORCE_CODE_SET, - - /** - * Forces C40 encoding for data-matrix (type {@link Boolean}, or "true" or "false") {@link String } value). This - * option and {@link #DATA_MATRIX_COMPACT} are mutually exclusive. - */ - FORCE_C40, - - /** - * Specifies whether to use compact mode for Code-128 code (type {@link Boolean}, or "true" or "false" - * {@link String } value). - * This can yield slightly smaller bar codes. This option and {@link #FORCE_CODE_SET} are mutually - * exclusive. - */ - CODE128_COMPACT, -} - -pub enum EncodeHintValue { - /** - * Specifies what degree of error correction to use, for example in QR Codes. - * Type depends on the encoder. For example for QR codes it's type - * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. - * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words. - * For PDF417 it is of type {@link Integer}, valid values being 0 to 8. - * In all cases, it can also be a {@link String} representation of the desired value as well. - * Note: an Aztec symbol should have a minimum of 25% EC words. - */ - ErrorCorrection(String), - - /** - * Specifies what character encoding to use where applicable (type {@link String}) - */ - CharacterSet(String), - - /** - * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint}) - */ - DataMatrixShape, - - /** - * Specifies whether to use compact mode for Data Matrix (type {@link Boolean}, or "true" or "false" - * {@link String } value). - * The compact encoding mode also supports the encoding of characters that are not in the ISO-8859-1 - * character set via ECIs. - * Please note that in that case, the most compact character encoding is chosen for characters in - * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not - * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by - * means of the {@link #CHARACTER_SET} encoding hint. - * Compact encoding also provides GS1-FNC1 support when {@link #GS1_FORMAT} is selected. In this case - * group-separator character (ASCII 29 decimal) can be used to encode the positions of FNC1 codewords - * for the purpose of delimiting AIs. - * This option and {@link #FORCE_C40} are mutually exclusive. - */ - DataMatrixCompact(String), - - /** - * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated use width/height params in - * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)} - */ - #[deprecated] - MinSize, - - /** - * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated without replacement - */ - #[deprecated] - MaxSize(Dimension), - - /** - * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary - * by format; for example it controls margin before and after the barcode horizontally for - * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value). - */ - Margin(String), - - /** - * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false" - * {@link String} value). - */ - Pdf417Compact(String), - - /** - * Specifies what compaction mode to use for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its - * enum values). - */ - Pdf417Compaction(String), - - /** - * Specifies the minimum and maximum number of rows and columns for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}). - */ - Pdf417Dimensions, - - /** - * Specifies whether to automatically insert ECIs when encoding PDF417 (type {@link Boolean}, or "true" or "false" - * {@link String} value). - * Please note that in that case, the most compact character encoding is chosen for characters in - * the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not - * support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by - * means of the {@link #CHARACTER_SET} encoding hint. - */ - Pdf417AutoEci(String), - - /** - * Specifies the required number of layers for an Aztec code. - * A negative number (-1, -2, -3, -4) specifies a compact Aztec code. - * 0 indicates to use the minimum number of layers (the default). - * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code. - * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - AztecLayers(i32), - - /** - * Specifies the exact version of QR code to be encoded. - * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - QrVersion(String), - - /** - * Specifies the QR code mask pattern to be used. Allowed values are - * 0..QRCode.NUM_MASK_PATTERNS-1. By default the code will automatically select - * the optimal mask pattern. - * * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - QrMaskPattern(String), - - /** - * Specifies whether to use compact mode for QR code (type {@link Boolean}, or "true" or "false" - * {@link String } value). - * Please note that when compaction is performed, the most compact character encoding is chosen - * for characters in the input that are not in the ISO-8859-1 character set. Based on experience, - * some scanners do not support encodings like cp-1256 (Arabic). In such cases the encoding can - * be forced to UTF-8 by means of the {@link #CHARACTER_SET} encoding hint. - */ - QrCompact(String), - - /** - * Specifies whether the data should be encoded to the GS1 standard (type {@link Boolean}, or "true" or "false" - * {@link String } value). - */ - Gs1Format(String), - - /** - * Forces which encoding will be used. Currently only used for Code-128 code sets (Type {@link String}). - * Valid values are "A", "B", "C". - * This option and {@link #CODE128_COMPACT} are mutually exclusive. - */ - ForceCodeSet(String), - - /** - * Forces C40 encoding for data-matrix (type {@link Boolean}, or "true" or "false") {@link String } value). This - * option and {@link #DATA_MATRIX_COMPACT} are mutually exclusive. - */ - ForceC40(String), - - /** - * Specifies whether to use compact mode for Code-128 code (type {@link Boolean}, or "true" or "false" - * {@link String } value). - * This can yield slightly smaller bar codes. This option and {@link #FORCE_CODE_SET} are mutually - * exclusive. - */ - Code128Compact(String), -} - -/* - * 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; - -/** - * Encapsulates a type of hint that a caller may pass to a barcode reader to help it - * more quickly or accurately decode it. It is up to implementations to decide what, - * if anything, to do with the information that is supplied. - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - * @see Reader#decode(BinaryBitmap,java.util.Map) - */ -#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)] -pub enum DecodeHintType { - /** - * Unspecified, application-specific hint. Maps to an unspecified {@link Object}. - */ - OTHER, - - /** - * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - PURE_BARCODE, - - /** - * Image is known to be of one of a few possible formats. - * Maps to a {@link List} of {@link BarcodeFormat}s. - */ - POSSIBLE_FORMATS, - - /** - * Spend more time to try to find a barcode; optimize for accuracy, not speed. - * Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - TRY_HARDER, - - /** - * Specifies what character encoding to use when decoding, where applicable (type String) - */ - CHARACTER_SET, - - /** - * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}. - */ - ALLOWED_LENGTHS, - - /** - * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - ASSUME_CODE_39_CHECK_DIGIT, - - /** - * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. - * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - ASSUME_GS1, - - /** - * If true, return the start and end digits in a Codabar barcode instead of stripping them. They - * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them - * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - RETURN_CODABAR_START_END, - - /** - * The caller needs to be notified via callback when a possible {@link RXingResultPoint} - * is found. Maps to a {@link RXingResultPointCallback}. - */ - NEED_RESULT_POINT_CALLBACK, - - /** - * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. - * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5]. - * If it is optional to have an extension, do not set this hint. If this is set, - * and a UPC or EAN barcode is found but an extension is not, then no result will be returned - * at all. - */ - ALLOWED_EAN_EXTENSIONS, - - /** - * If true, also tries to decode as inverted image. All configured decoders are simply called a - * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - ALSO_INVERTED, - // End of enumeration values. - - /* - * Data type the hint is expecting. - * Among the possible values the {@link Void} stands out as being used for - * hints that do not expect a value to be supplied (flag hints). Such hints - * will possibly have their value ignored, or replaced by a - * {@link Boolean#TRUE}. Hint suppliers should probably use - * {@link Boolean#TRUE} as directed by the actual hint documentation. - */ - /* - private final Class valueType; - - DecodeHintType(Class valueType) { - this.valueType = valueType; - } - - public Class getValueType() { - return valueType; - }*/ -} +mod encode_hints; +pub use encode_hints::*; /** * Callback which is invoked when a possible result point (significant @@ -570,1774 +42,44 @@ pub enum DecodeHintType { * @see DecodeHintType#NEED_RESULT_POINT_CALLBACK */ pub type RXingResultPointCallback = fn(&dyn ResultPoint); -#[derive(Clone)] -pub enum DecodeHintValue { - /** - * Unspecified, application-specific hint. Maps to an unspecified {@link Object}. - */ - Other(String), - /** - * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - PureBarcode(bool), +mod decode_hints; +pub use decode_hints::*; - /** - * Image is known to be of one of a few possible formats. - * Maps to a {@link List} of {@link BarcodeFormat}s. - */ - PossibleFormats(BarcodeFormat), +mod writer; +pub use writer::*; - /** - * Spend more time to try to find a barcode; optimize for accuracy, not speed. - * Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - TryHarder(bool), +mod reader; +pub use reader::*; - /** - * Specifies what character encoding to use when decoding, where applicable (type String) - */ - CharacterSet(String), +mod rxing_result_metadata; +pub use rxing_result_metadata::*; - /** - * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}. - */ - AllowedLengths(Vec), +mod rxing_result; +pub use rxing_result::*; - /** - * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - AssumeCode39CheckDigit(bool), +mod result_point; +pub use result_point::*; - /** - * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. - * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - AssumeGs1(bool), +pub mod result_point_utils; - /** - * If true, return the start and end digits in a Codabar barcode instead of stripping them. They - * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them - * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - ReturnCodabarStartEnd(bool), +mod rxing_result_point; +pub use rxing_result_point::*; - /** - * The caller needs to be notified via callback when a possible {@link RXingResultPoint} - * is found. Maps to a {@link RXingResultPointCallback}. - */ - NeedResultPointCallback(RXingResultPointCallback), +mod dimension; +pub use dimension::*; - /** - * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. - * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5]. - * If it is optional to have an extension, do not set this hint. If this is set, - * and a UPC or EAN barcode is found but an extension is not, then no result will be returned - * at all. - */ - AllowedEanExtensions(Vec), +mod binarizer; +pub use binarizer::*; - /** - * If true, also tries to decode as inverted image. All configured decoders are simply called a - * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - AlsoInverted(bool), - // End of enumeration values. -} +mod binary_bitmap; +pub use binary_bitmap::*; -/* - * 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. - */ +mod luminance_source; +pub use luminance_source::*; -//package com.google.zxing; +mod planar_yuv_luminance_source; +pub use planar_yuv_luminance_source::*; -/** - * The base class for all objects which encode/generate a barcode image. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -pub trait Writer { - /** - * Encode a barcode using the default settings. - * - * @param contents The contents to encode in the barcode - * @param format The barcode format to generate - * @param width The preferred width in pixels - * @param height The preferred height in pixels - * @return {@link BitMatrix} representing encoded barcode image - * @throws WriterException if contents cannot be encoded legally in a format - */ - fn encode( - &self, - contents: &str, - format: &BarcodeFormat, - width: i32, - height: i32, - ) -> Result; - - /** - * @param contents The contents to encode in the barcode - * @param format The barcode format to generate - * @param width The preferred width in pixels - * @param height The preferred height in pixels - * @param hints Additional parameters to supply to the encoder - * @return {@link BitMatrix} representing encoded barcode image - * @throws WriterException if contents cannot be encoded legally in a format - */ - fn encode_with_hints( - &self, - contents: &str, - format: &BarcodeFormat, - width: i32, - height: i32, - hints: &EncodingHintDictionary, - ) -> Result; -} - -/* - * 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; - -/** - * Implementations of this interface can decode an image of a barcode in some format into - * the String it encodes. For example, {@link com.google.zxing.qrcode.QRCodeReader} can - * decode a QR code. The decoder may optionally receive hints from the caller which may help - * it decode more quickly or accurately. - * - * See {@link MultiFormatReader}, which attempts to determine what barcode - * format is present within the image as well, and then decodes it accordingly. - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - */ -pub trait Reader { - /** - * Locates and decodes a barcode in some format within an image. - * - * @param image image of barcode to decode - * @return String which the barcode encodes - * @throws NotFoundException if no potential barcode is found - * @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; - - /** - * Locates and decodes a barcode in some format within an image. This method also accepts - * hints, each possibly associated to some data, which may help the implementation decode. - * - * @param image image of barcode to decode - * @param hints passed as a {@link Map} from {@link DecodeHintType} - * to arbitrary data. The - * meaning of the data depends upon the hint type. The implementation may or may not do - * anything with these hints. - * @return String which the barcode encodes - * @throws NotFoundException if no potential barcode is found - * @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_with_hints( - &self, - image: &BinaryBitmap, - hints: &DecodingHintDictionary, - ) -> Result; - - /** - * Resets any internal state the implementation has after a decode, to prepare it - * for reuse. - */ - fn reset(&self); -} - -/* - * 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; - -/** - * Represents some type of metadata about the result of the decoding that the decoder - * wishes to communicate back to the caller. - * - * @author Sean Owen - */ -#[derive(Eq, PartialEq, Hash, Debug)] -pub enum RXingResultMetadataType { - /** - * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. - */ - OTHER, - - /** - * Denotes the likely approximate orientation of the barcode in the image. This value - * is given as degrees rotated clockwise from the normal, upright orientation. - * For example a 1D barcode which was found by reading top-to-bottom would be - * said to have orientation "90". This key maps to an {@link Integer} whose - * value is in the range [0,360). - */ - ORIENTATION, - - /** - *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' - * which is sometimes used to encode binary data. While {@link RXingResult} makes available - * the complete raw bytes in the barcode for these formats, it does not offer the bytes - * from the byte segments alone.

- * - *

This maps to a {@link java.util.List} of byte arrays corresponding to the - * raw bytes in the byte segments in the barcode, in order.

- */ - BYTE_SEGMENTS, - - /** - * Error correction level used, if applicable. The value type depends on the - * format, but is typically a String. - */ - ERROR_CORRECTION_LEVEL, - - /** - * For some periodicals, indicates the issue number as an {@link Integer}. - */ - ISSUE_NUMBER, - - /** - * For some products, indicates the suggested retail price in the barcode as a - * formatted {@link String}. - */ - SUGGESTED_PRICE, - - /** - * For some products, the possible country of manufacture as a {@link String} denoting the - * ISO country code. Some map to multiple possible countries, like "US/CA". - */ - POSSIBLE_COUNTRY, - - /** - * For some products, the extension text - */ - UPC_EAN_EXTENSION, - - /** - * PDF417-specific metadata - */ - PDF417_EXTRA_METADATA, - - /** - * If the code format supports structured append and the current scanned code is part of one then the - * sequence number is given with it. - */ - STRUCTURED_APPEND_SEQUENCE, - - /** - * If the code format supports structured append and the current scanned code is part of one then the - * parity is given with it. - */ - STRUCTURED_APPEND_PARITY, - - /** - * Barcode Symbology Identifier. - * Note: According to the GS1 specification the identifier may have to replace a leading FNC1/GS character - * when prepending to the barcode content. - */ - SYMBOLOGY_IDENTIFIER, -} - -impl From for RXingResultMetadataType { - fn from(in_str: String) -> Self { - match in_str.as_str() { - "OTHER" => RXingResultMetadataType::OTHER, - "ORIENTATION" => RXingResultMetadataType::ORIENTATION, - "BYTE_SEGMENTS" => RXingResultMetadataType::BYTE_SEGMENTS, - "ERROR_CORRECTION_LEVEL" => RXingResultMetadataType::ERROR_CORRECTION_LEVEL, - "ISSUE_NUMBER" => RXingResultMetadataType::ISSUE_NUMBER, - "SUGGESTED_PRICE" => RXingResultMetadataType::SUGGESTED_PRICE, - "POSSIBLE_COUNTRY" => RXingResultMetadataType::POSSIBLE_COUNTRY, - "UPC_EAN_EXTENSION" => RXingResultMetadataType::UPC_EAN_EXTENSION, - "PDF417_EXTRA_METADATA" => RXingResultMetadataType::PDF417_EXTRA_METADATA, - "STRUCTURED_APPEND_SEQUENCE" => RXingResultMetadataType::STRUCTURED_APPEND_SEQUENCE, - "STRUCTURED_APPEND_PARITY" => RXingResultMetadataType::STRUCTURED_APPEND_PARITY, - "SYMBOLOGY_IDENTIFIER" => RXingResultMetadataType::SYMBOLOGY_IDENTIFIER, - _ => RXingResultMetadataType::OTHER, - } - } -} - -#[derive(Debug, PartialEq, Eq)] -pub enum RXingResultMetadataValue { - /** - * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. - */ - OTHER(String), - - /** - * Denotes the likely approximate orientation of the barcode in the image. This value - * is given as degrees rotated clockwise from the normal, upright orientation. - * For example a 1D barcode which was found by reading top-to-bottom would be - * said to have orientation "90". This key maps to an {@link Integer} whose - * value is in the range [0,360). - */ - Orientation(i32), - - /** - *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' - * which is sometimes used to encode binary data. While {@link RXingResult} makes available - * the complete raw bytes in the barcode for these formats, it does not offer the bytes - * from the byte segments alone.

- * - *

This maps to a {@link java.util.List} of byte arrays corresponding to the - * raw bytes in the byte segments in the barcode, in order.

- */ - ByteSegments(Vec>), - - /** - * Error correction level used, if applicable. The value type depends on the - * format, but is typically a String. - */ - ErrorCorrectionLevel(String), - - /** - * For some periodicals, indicates the issue number as an {@link Integer}. - */ - IssueNumber(i32), - - /** - * For some products, indicates the suggested retail price in the barcode as a - * formatted {@link String}. - */ - SuggestedPrice(String), - - /** - * For some products, the possible country of manufacture as a {@link String} denoting the - * ISO country code. Some map to multiple possible countries, like "US/CA". - */ - PossibleCountry(String), - - /** - * For some products, the extension text - */ - UpcEanExtension(String), - - /** - * PDF417-specific metadata - */ - Pdf417ExtraMetadata(String), - - /** - * If the code format supports structured append and the current scanned code is part of one then the - * sequence number is given with it. - */ - StructuredAppendSequence(i32), - - /** - * If the code format supports structured append and the current scanned code is part of one then the - * parity is given with it. - */ - StructuredAppendParity(i32), - - /** - * Barcode Symbology Identifier. - * Note: According to the GS1 specification the identifier may have to replace a leading FNC1/GS character - * when prepending to the barcode content. - */ - SymbologyIdentifier(String), -} - -/* - * 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 java.util.EnumMap; -//import java.util.Map; - -/** - *

Encapsulates the result of decoding a barcode within an image.

- * - * @author Sean Owen - */ -pub struct RXingResult { - text: String, - rawBytes: Vec, - numBits: usize, - resultPoints: Vec, - format: BarcodeFormat, - resultMetadata: HashMap, - timestamp: u128, -} -impl RXingResult { - pub fn new( - text: &str, - rawBytes: Vec, - resultPoints: Vec, - format: BarcodeFormat, - ) -> Self { - Self::new_timestamp( - text, - rawBytes, - resultPoints, - format, - SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_millis(), - ) - } - - pub fn new_timestamp( - text: &str, - rawBytes: Vec, - resultPoints: Vec, - format: BarcodeFormat, - timestamp: u128, - ) -> Self { - let l = rawBytes.len(); - Self::new_complex(text, rawBytes, 8 * l, resultPoints, format, timestamp) - } - - pub fn new_complex( - text: &str, - rawBytes: Vec, - numBits: usize, - resultPoints: Vec, - format: BarcodeFormat, - timestamp: u128, - ) -> Self { - Self { - text: text.to_owned(), - rawBytes: rawBytes, - numBits, - resultPoints, - format, - resultMetadata: HashMap::new(), - timestamp, - } - } - - /** - * @return raw text encoded by the barcode - */ - pub fn getText(&self) -> &String { - return &self.text; - } - - /** - * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null} - */ - pub fn getRawBytes(&self) -> &Vec { - return &self.rawBytes; - } - - /** - * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length - * @since 3.3.0 - */ - pub fn getNumBits(&self) -> usize { - return self.numBits; - } - - /** - * @return points related to the barcode in the image. These are typically points - * identifying finder patterns or the corners of the barcode. The exact meaning is - * specific to the type of barcode that was decoded. - */ - pub fn getRXingResultPoints(&self) -> &Vec { - return &self.resultPoints; - } - - /** - * @return {@link BarcodeFormat} representing the format of the barcode that was decoded - */ - pub fn getBarcodeFormat(&self) -> &BarcodeFormat { - return &self.format; - } - - /** - * @return {@link Map} mapping {@link RXingResultMetadataType} keys to values. May be - * {@code null}. This contains optional metadata about what was detected about the barcode, - * like orientation. - */ - pub fn getRXingResultMetadata( - &self, - ) -> &HashMap { - return &self.resultMetadata; - } - - pub fn putMetadata( - &mut self, - md_type: RXingResultMetadataType, - value: RXingResultMetadataValue, - ) { - self.resultMetadata.insert(md_type, value); - } - - pub fn putAllMetadata( - &mut self, - metadata: HashMap, - ) { - if self.resultMetadata.is_empty() { - self.resultMetadata = metadata; - } else { - for (key, value) in metadata.into_iter() { - self.resultMetadata.insert(key, value); - } - } - } - - pub fn addRXingResultPoints(&mut self, newPoints: &mut Vec) { - //RXingResultPoint[] oldPoints = resultPoints; - if !newPoints.is_empty() { - // let allPoints:Vec= Vec::with_capacity(oldPoints.len() + newPoints.len()); - //System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length); - //System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length); - //resultPoints = allPoints; - self.resultPoints.append(newPoints); - } - } - - pub fn getTimestamp(&self) -> u128 { - return self.timestamp; - } -} - -impl fmt::Display for RXingResult { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.text) - } -} - -/* - * 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; - -pub trait ResultPoint { - fn getX(&self) -> f32; - fn getY(&self) -> f32; - fn into_rxing_result_point(self) -> RXingResultPoint; -} - -pub mod result_point_utils { - use crate::{common::detector::MathUtils, ResultPoint}; - - /** - * Orders an array of three RXingResultPoints in an order [A,B,C] such that AB is less than AC - * and BC is less than AC, and the angle between BC and BA is less than 180 degrees. - * - * @param patterns array of three {@code RXingResultPoint} to order - */ - pub fn orderBestPatterns(patterns: &mut [T; 3]) { - // Find distances between pattern centers - let zeroOneDistance = MathUtils::distance_float( - patterns[0].getX(), - patterns[0].getY(), - patterns[1].getX(), - patterns[1].getY(), - ); - let oneTwoDistance = MathUtils::distance_float( - patterns[1].getX(), - patterns[1].getY(), - patterns[2].getX(), - patterns[2].getY(), - ); - let zeroTwoDistance = MathUtils::distance_float( - patterns[0].getX(), - patterns[0].getY(), - patterns[2].getX(), - patterns[2].getY(), - ); - - let mut pointA; //: &RXingResultPoint; - let pointB; //: &RXingResultPoint; - let mut pointC; //: &RXingResultPoint; - // Assume one closest to other two is B; A and C will just be guesses at first - if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance { - pointB = patterns[0]; - pointA = patterns[1]; - pointC = patterns[2]; - } else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance { - pointB = patterns[1]; - pointA = patterns[0]; - pointC = patterns[2]; - } else { - pointB = patterns[2]; - pointA = patterns[0]; - pointC = patterns[1]; - } - - // Use cross product to figure out whether A and C are correct or flipped. - // This asks whether BC x BA has a positive z component, which is the arrangement - // we want for A, B, C. If it's negative, then we've got it flipped around and - // should swap A and C. - if crossProductZ(pointA, pointB, pointC) < 0.0f32 { - let temp = pointA; - pointA = pointC; - pointC = temp; - } - - let pa = pointA; - let pb = pointB; - let pc = pointC; - - patterns[0] = pa; - patterns[1] = pb; - patterns[2] = pc; - } - - /** - * @param pattern1 first pattern - * @param pattern2 second pattern - * @return distance between two points - */ - pub fn distance(pattern1: &T, pattern2: &T) -> f32 { - return MathUtils::distance_float( - pattern1.getX(), - pattern1.getY(), - pattern2.getX(), - pattern2.getY(), - ); - } - - /** - * Returns the z component of the cross product between vectors BC and BA. - */ - pub fn crossProductZ(pointA: T, pointB: T, pointC: T) -> f32 { - let bX = pointB.getX(); - let bY = pointB.getY(); - return ((pointC.getX() - bX) * (pointA.getY() - bY)) - - ((pointC.getY() - bY) * (pointA.getX() - bX)); - } -} - -/** - *

Encapsulates a point of interest in an image containing a barcode. Typically, this - * would be the location of a finder pattern or the corner of the barcode, for example.

- * - * @author Sean Owen - */ -#[derive(Debug, Clone, Copy)] -pub struct RXingResultPoint { - x: f32, - y: f32, -} -impl Hash for RXingResultPoint { - fn hash(&self, state: &mut H) { - self.x.to_string().hash(state); - self.y.to_string().hash(state); - } -} -impl PartialEq for RXingResultPoint { - fn eq(&self, other: &Self) -> bool { - self.x.to_string() == other.x.to_string() && self.y.to_string() == other.y.to_string() - } -} -impl Eq for RXingResultPoint {} -impl RXingResultPoint { - pub const fn new(x: f32, y: f32) -> Self { - Self { x, y } - } -} - -impl ResultPoint for RXingResultPoint { - fn getX(&self) -> f32 { - return self.x; - } - - fn getY(&self) -> f32 { - return self.y; - } - - fn into_rxing_result_point(self) -> RXingResultPoint { - self - } -} - -impl fmt::Display for RXingResultPoint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "({},{})", self.x, self.y) - } -} - -/* - * Copyright 2012 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; - -/** - * Simply encapsulates a width and height. - */ -#[derive(Eq, PartialEq, Hash)] -pub struct Dimension { - width: usize, - height: usize, -} - -impl Dimension { - pub fn new(width: usize, height: usize) -> Result { - Ok(Self { width, height }) - } - - pub fn getWidth(&self) -> usize { - return self.width; - } - - pub fn getHeight(&self) -> usize { - return self.height; - } -} - -impl fmt::Display for Dimension { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}x{}", self.width, self.height) - } -} - -/* - * Copyright 2009 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; - -/** - * This class hierarchy provides a set of methods to convert luminance data to 1 bit data. - * It allows the algorithm to vary polymorphically, for example allowing a very expensive - * thresholding technique for servers and a fast one for mobile. It also permits the implementation - * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -pub trait Binarizer { - //private final LuminanceSource source; - //fn new(source:dyn LuminanceSource) -> Self; - - fn getLuminanceSource(&self) -> &Box; - - /** - * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - * cached data. Callers should assume this method is expensive and call it as seldom as possible. - * This method is intended for decoding 1D barcodes and may choose to apply sharpening. - * For callers which only examine one row of pixels at a time, the same BitArray should be reused - * and passed in with each call for performance. However it is legal to keep more than one row - * at a time if needed. - * - * @param y The row to fetch, which must be in [0, bitmap height) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * If used, the Binarizer will call BitArray.clear(). Always use the returned object. - * @return The array of bits for this row (true means black). - * @throws NotFoundException if row can't be binarized - */ - fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result; - - /** - * Converts a 2D array of luminance data to 1 bit data. 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 - */ - fn getBlackMatrix(&self) -> Result; - - /** - * Creates a new object with the same type as this Binarizer implementation, but with pristine - * state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache - * of 1 bit data. See Effective Java for why we can't use Java's clone() method. - * - * @param source The LuminanceSource this Binarizer will operate on. - * @return A new concrete Binarizer implementation object. - */ - fn createBinarizer(&self, source: Box) -> Box; - - fn getWidth(&self) -> usize; - - fn getHeight(&self) -> usize; -} - -/* - * Copyright 2009 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; - -/** - * This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects - * accept a BinaryBitmap and attempt to decode it. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -pub struct BinaryBitmap { - binarizer: Box, - matrix: BitMatrix, -} - -impl BinaryBitmap { - pub fn new(binarizer: Box) -> Self { - Self { - matrix: binarizer.getBlackMatrix().unwrap(), - binarizer: binarizer, - } - } - - /** - * @return The width of the bitmap. - */ - pub fn getWidth(&self) -> usize { - return self.binarizer.getWidth(); - } - - /** - * @return The height of the bitmap. - */ - pub fn getHeight(&self) -> usize { - return self.binarizer.getHeight(); - } - - /** - * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - * cached data. Callers should assume this method is expensive and call it as seldom as possible. - * This method is intended for decoding 1D barcodes and may choose to apply sharpening. - * - * @param y The row to fetch, which must be in [0, bitmap height) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * If used, the Binarizer will call BitArray.clear(). Always use the returned object. - * @return The array of bits for this row (true means black). - * @throws NotFoundException if row can't be binarized - */ - pub fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result { - return self.binarizer.getBlackRow(y, row); - } - - /** - * 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) -> Result<&BitMatrix, Exceptions> { - // 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); - } - - /** - * @return Whether this bitmap can be cropped. - */ - pub fn isCropSupported(&self) -> bool { - let b = &self.binarizer; - let r = &b.getLuminanceSource(); - let isCropOk = r.isCropSupported(); - return isCropOk; - } - - /** - * Returns a new object with cropped image data. Implementations may keep a reference to the - * original data rather than a copy. Only callable if isCropSupported() is true. - * - * @param left The left coordinate, which must be in [0,getWidth()) - * @param top The top coordinate, which must be in [0,getHeight()) - * @param width The width of the rectangle to crop. - * @param height The height of the rectangle to crop. - * @return A cropped version of this object. - */ - pub fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> BinaryBitmap { - let newSource = self - .binarizer - .getLuminanceSource() - .crop(left, top, width, height); - return BinaryBitmap::new( - self.binarizer - .createBinarizer(newSource.expect("new lum source expected")), - ); - } - - /** - * @return Whether this bitmap supports counter-clockwise rotation. - */ - pub fn isRotateSupported(&self) -> bool { - return self.binarizer.getLuminanceSource().isRotateSupported(); - } - - /** - * Returns a new object with rotated image data by 90 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - pub fn rotateCounterClockwise(&self) -> BinaryBitmap { - let newSource = self.binarizer.getLuminanceSource().rotateCounterClockwise(); - return BinaryBitmap::new( - self.binarizer - .createBinarizer(newSource.expect("new lum source expected")), - ); - } - - /** - * Returns a new object with rotated image data by 45 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - pub fn rotateCounterClockwise45(&self) -> BinaryBitmap { - let newSource = self - .binarizer - .getLuminanceSource() - .rotateCounterClockwise45(); - return BinaryBitmap::new( - self.binarizer - .createBinarizer(newSource.expect("new lum source expected")), - ); - } -} - -impl fmt::Display for BinaryBitmap { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.getBlackMatrix().unwrap()) - } -} - -/* - * Copyright 2009 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; - -/** - * The purpose of this class hierarchy is to abstract different bitmap implementations across - * platforms into a standard interface for requesting greyscale luminance values. The interface - * only provides immutable methods; therefore crop and rotation create copies. This is to ensure - * that one Reader does not modify the original luminance source and leave it in an unknown state - * for other Readers in the chain. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -pub trait LuminanceSource { - //private final int width; - //private final int height; - - //fn new( width:usize, height:usize) -> Self; - - /** - * Fetches one row of luminance data from the underlying platform's bitmap. Values range from - * 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have - * to bitwise and with 0xff for each value. It is preferable for implementations of this method - * to only fetch this row rather than the whole image, since no 2D Readers may be installed and - * getMatrix() may never be called. - * - * @param y The row to fetch, which must be in [0,getHeight()) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * Always use the returned object, and ignore the .length of the array. - * @return An array containing the luminance data. - */ - fn getRow(&self, y: usize, row: &Vec) -> Vec; - - /** - * Fetches luminance data for the underlying bitmap. Values should be fetched using: - * {@code int luminance = array[y * width + x] & 0xff} - * - * @return A row-major 2D array of luminance values. Do not use result.length as it may be - * larger than width * height bytes on some platforms. Do not modify the contents - * of the result. - */ - fn getMatrix(&self) -> Vec; - - /** - * @return The width of the bitmap. - */ - fn getWidth(&self) -> usize; - - /** - * @return The height of the bitmap. - */ - fn getHeight(&self) -> usize; - - /** - * @return Whether this subclass supports cropping. - */ - fn isCropSupported(&self) -> bool { - return false; - } - - /** - * Returns a new object with cropped image data. Implementations may keep a reference to the - * original data rather than a copy. Only callable if isCropSupported() is true. - * - * @param left The left coordinate, which must be in [0,getWidth()) - * @param top The top coordinate, which must be in [0,getHeight()) - * @param width The width of the rectangle to crop. - * @param height The height of the rectangle to crop. - * @return A cropped version of this object. - */ - fn crop( - &self, - left: usize, - top: usize, - width: usize, - height: usize, - ) -> Result, Exceptions> { - return Err(Exceptions::UnsupportedOperationException( - "This luminance source does not support cropping.".to_owned(), - )); - } - - /** - * @return Whether this subclass supports counter-clockwise rotation. - */ - fn isRotateSupported(&self) -> bool { - return false; - } - - /** - * @return a wrapper of this {@code LuminanceSource} which inverts the luminances it returns -- black becomes - * white and vice versa, and each value becomes (255-value). - */ - fn invert(&mut self); /* { - return InvertedLuminanceSource::new_with_delegate(self); - }*/ - - /** - * Returns a new object with rotated image data by 90 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - fn rotateCounterClockwise(&self) -> Result, Exceptions> { - return Err(Exceptions::UnsupportedOperationException( - "This luminance source does not support rotation by 90 degrees.".to_owned(), - )); - } - - /** - * Returns a new object with rotated image data by 45 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - fn rotateCounterClockwise45(&self) -> Result, Exceptions> { - return Err(Exceptions::UnsupportedOperationException( - "This luminance source does not support rotation by 45 degrees.".to_owned(), - )); - } - - fn invert_block_of_bytes(&self, vec_to_invert: Vec) -> Vec { - let mut iv = vec_to_invert.clone(); - for itm in iv.iter_mut() { - let z = *itm; - *itm = 255 - (z & 0xFF); - } - iv - } - - /* - @Override - public final String toString() { - byte[] row = new byte[width]; - StringBuilder result = new StringBuilder(height * (width + 1)); - for (int y = 0; y < height; y++) { - row = getRow(y, row); - for (int x = 0; x < width; x++) { - int luminance = row[x] & 0xFF; - char c; - if (luminance < 0x40) { - c = '#'; - } else if (luminance < 0x80) { - c = '+'; - } else if (luminance < 0xC0) { - c = '.'; - } else { - c = ' '; - } - result.append(c); - } - result.append('\n'); - } - return result.toString(); - }*/ -} - -// /* -// * Copyright 2013 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; - -// /** -// * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes -// * white and vice versa, and each value becomes (255-value). -// * -// * @author Sean Owen -// */ -// pub struct InvertedLuminanceSource { -// width: usize, -// height: usize, -// delegate: Box, -// } - -// impl InvertedLuminanceSource { -// pub fn new_with_delegate(delegate: Box) -> Self { -// Self { -// width: delegate.getWidth(), -// height: delegate.getHeight(), -// delegate, -// } -// } -// } - -// impl LuminanceSource for InvertedLuminanceSource { -// fn getRow(&self, y: usize, row: &Vec) -> Vec { -// let mut new_row = self.delegate.getRow(y, row); -// let width = self.getWidth(); -// for i in 0..width { -// //for (int i = 0; i < width; i++) { -// new_row[i] = 255 - (new_row[i] & 0xFF); -// } -// return new_row; -// } - -// fn getMatrix(&self) -> Vec { -// let matrix = self.delegate.getMatrix(); -// let length = self.getWidth() * self.getHeight(); -// let mut invertedMatrix = Vec::with_capacity(length); -// for i in 0..length { -// //for (int i = 0; i < length; i++) { -// invertedMatrix[i] = 255 - (matrix[i] & 0xFF); -// } -// return invertedMatrix; -// } - -// fn getWidth(&self) -> usize { -// self.width -// } - -// fn getHeight(&self) -> usize { -// self.height -// } - -// fn isCropSupported(&self) -> bool { -// return self.delegate.isCropSupported(); -// } - -// fn crop( -// &self, -// left: usize, -// top: usize, -// width: usize, -// height: usize, -// ) -> Result, UnsupportedOperationException> { -// let crop = self.delegate.crop(left, top, width, height)?; -// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(crop))); -// } - -// fn isRotateSupported(&self) -> bool { -// return self.delegate.isRotateSupported(); -// } - -// /** -// * @return original delegate {@link LuminanceSource} since invert undoes itself -// */ -// fn invert(&self) -> Box { -// return self.delegate; -// } - -// fn rotateCounterClockwise( -// &self, -// ) -> Result, UnsupportedOperationException> { -// let rot = self.delegate.rotateCounterClockwise()?; -// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(rot))); -// } - -// fn rotateCounterClockwise45( -// &self, -// ) -> Result, UnsupportedOperationException> { -// let rot_45 = self.delegate.rotateCounterClockwise45()?; -// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(rot_45))); -// } -// } - -/* - * Copyright 2009 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; - -const THUMBNAIL_SCALE_FACTOR: usize = 2; - -/** - * This object extends LuminanceSource around an array of YUV data returned from the camera driver, - * with the option to crop to a rectangle within the full data. This can be used to exclude - * superfluous pixels around the perimeter and speed up decoding. - * - * It works for any pixel format where the Y channel is planar and appears first, including - * YCbCr_420_SP and YCbCr_422_SP. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -#[derive(Debug, Clone)] -pub struct PlanarYUVLuminanceSource { - yuv_data: Vec, - data_width: usize, - data_height: usize, - left: usize, - top: usize, - width: usize, - height: usize, - invert: bool, -} - -impl PlanarYUVLuminanceSource { - pub fn new_with_all( - yuv_data: Vec, - data_width: usize, - data_height: usize, - left: usize, - top: usize, - width: usize, - height: usize, - reverse_horizontal: bool, - inverted: bool, - ) -> Result { - if left + width > data_width || top + height > data_height { - return Err(Exceptions::IllegalArgumentException( - "Crop rectangle does not fit within image data.".to_owned(), - )); - } - - let mut new_s: Self = Self { - yuv_data, - data_width, - data_height, - left, - top, - width, - height, - invert: inverted, - }; - - if reverse_horizontal { - new_s.reverseHorizontal(width, height); - } - - Ok(new_s) - } - - pub fn renderThumbnail(&self) -> Vec { - let width = self.getWidth() / THUMBNAIL_SCALE_FACTOR; - let height = self.getHeight() / THUMBNAIL_SCALE_FACTOR; - let mut pixels = vec![0; width * height]; - let yuv = &self.yuv_data; - let mut input_offset = self.top * self.data_width + self.left; - - for y in 0..height { - //for (int y = 0; y < height; y++) { - let output_offset = y * width; - for x in 0..width { - //for (int x = 0; x < width; x++) { - let grey = yuv[input_offset + x * THUMBNAIL_SCALE_FACTOR] & 0xff; - pixels[output_offset + x] = (0xFF000000 | (grey as u32 * 0x00010101)) as u8; - } - input_offset += self.data_width * THUMBNAIL_SCALE_FACTOR; - } - return pixels; - } - - /** - * @return width of image from {@link #renderThumbnail()} - */ - pub fn getThumbnailWidth(&self) -> usize { - return self.getWidth() / THUMBNAIL_SCALE_FACTOR; - } - - /** - * @return height of image from {@link #renderThumbnail()} - */ - pub fn getThumbnailHeight(&self) -> usize { - return self.getHeight() / THUMBNAIL_SCALE_FACTOR; - } - - fn reverseHorizontal(&mut self, width: usize, height: usize) { - //let mut yuvData = self.yuvData; - let mut rowStart = self.top * self.data_width + self.left; - for _y in 0..height { - let middle = rowStart + width / 2; - let mut x2 = rowStart + width - 1; - for x1 in rowStart..middle { - //for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { - let temp = self.yuv_data[x1]; - self.yuv_data[x1] = self.yuv_data[x2]; - self.yuv_data[x2] = temp; - x2 -= 1; - } - rowStart += self.data_width; - } - //self.yuvData = yuvData; - /*for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) { - let middle = rowStart + width / 2; - for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { - let temp = yuvData[x1]; - yuvData[x1] = yuvData[x2]; - yuvData[x2] = temp; - } - }*/ - } -} - -impl LuminanceSource for PlanarYUVLuminanceSource { - fn getRow(&self, y: usize, row: &Vec) -> Vec { - if y >= self.getHeight() { - //throw new IllegalArgumentException("Requested row is outside the image: " + y); - panic!("Requested row is outside the image: {}", y); - } - let width = self.getWidth(); - - let offset = (y + self.top) * self.data_width + self.left; - - let mut row = if row.len() >= width { - row.to_vec() - } else { - vec![0; width] - }; - - row[..width].clone_from_slice(&self.yuv_data[offset..width + offset]); - //System.arraycopy(yuvData, offset, row, 0, width); - if self.invert { - row = self.invert_block_of_bytes(row); - } - return row; - } - - fn getMatrix(&self) -> Vec { - let width = self.getWidth(); - let height = self.getHeight(); - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if width == self.data_width && height == self.data_height { - let mut v = self.yuv_data.clone(); - if self.invert { - v = self.invert_block_of_bytes(v); - } - return v; - } - - let area = width * height; - let mut matrix = vec![0; area]; - let mut inputOffset = self.top * self.data_width + self.left; - - // If the width matches the full width of the underlying data, perform a single copy. - if width == self.data_width { - matrix[0..area].clone_from_slice(&self.yuv_data[inputOffset..area]); - //System.arraycopy(yuvData, inputOffset, matrix, 0, area); - if self.invert { - matrix = self.invert_block_of_bytes(matrix); - } - return matrix; - } - - // Otherwise copy one cropped row at a time. - for y in 0..height { - //for (int y = 0; y < height; y++) { - let outputOffset = y * width; - matrix[outputOffset..outputOffset + width] - .clone_from_slice(&self.yuv_data[inputOffset..inputOffset + width]); - //System.arraycopy(yuvData, inputOffset, matrix, outputOffset, width); - inputOffset += self.data_width; - } - - if self.invert { - matrix = self.invert_block_of_bytes(matrix); - } - - return matrix; - } - - fn getWidth(&self) -> usize { - self.width - } - - fn getHeight(&self) -> usize { - self.height - } - - fn isCropSupported(&self) -> bool { - return true; - } - - fn crop( - &self, - left: usize, - top: usize, - width: usize, - height: usize, - ) -> Result, Exceptions> { - match PlanarYUVLuminanceSource::new_with_all( - self.yuv_data.clone(), - self.data_width, - self.data_height, - self.left + left, - self.top + top, - width, - height, - false, - self.invert, - ) { - Ok(new) => Ok(Box::new(new)), - Err(_err) => Err(Exceptions::UnsupportedOperationException("".to_owned())), - } - } - - fn isRotateSupported(&self) -> bool { - return false; - } - - fn invert(&mut self) { - self.invert = !self.invert; - } -} - -/* - * Copyright 2009 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; - -/** - * This class is used to help decode images from files which arrive as RGB data from - * an ARGB pixel array. It does not support rotation. - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Betaminos - */ -#[derive(Debug, Clone)] -pub struct RGBLuminanceSource { - luminances: Vec, - dataWidth: usize, - dataHeight: usize, - left: usize, - top: usize, - width: usize, - height: usize, - invert: bool, -} - -impl LuminanceSource for RGBLuminanceSource { - fn getRow(&self, y: usize, row: &Vec) -> Vec { - if y >= self.getHeight() { - panic!("Requested row is outside the image: {}", y); - } - let width = self.getWidth(); - - let offset = (y + self.top) * self.dataWidth + self.left; - - let mut row = if row.len() >= width { - row.to_vec() - } else { - vec![0; width] - }; - - row[..width].clone_from_slice(&self.luminances[offset..offset + width]); - //System.arraycopy(self.luminances, offset, row, 0, width); - if self.invert { - row = self.invert_block_of_bytes(row); - } - return row; - } - - fn getMatrix(&self) -> Vec { - let width = self.getWidth(); - let height = self.getHeight(); - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if width == self.dataWidth && height == self.dataHeight { - let mut z = self.luminances.clone(); - if self.invert { - z = self.invert_block_of_bytes(z); - } - return z; - } - - let area = width * height; - let mut matrix = vec![0; area]; - let mut inputOffset = self.top * self.dataWidth + self.left; - - // If the width matches the full width of the underlying data, perform a single copy. - if width == self.dataWidth { - matrix[..area].clone_from_slice(&self.luminances[inputOffset..area + inputOffset]); - //System.arraycopy(self.luminances, inputOffset, matrix, 0, area); - if self.invert { - matrix = self.invert_block_of_bytes(matrix); - } - return matrix; - } - - // Otherwise copy one cropped row at a time. - for y in 0..height { - //for (int y = 0; y < height; y++) { - let outputOffset = y * width; - matrix[outputOffset..width + outputOffset] - .clone_from_slice(&self.luminances[inputOffset..width + inputOffset]); - //System.arraycopy(luminances, inputOffset, matrix, outputOffset, width); - inputOffset += self.dataWidth; - } - - if self.invert { - matrix = self.invert_block_of_bytes(matrix); - } - return matrix; - } - - fn getWidth(&self) -> usize { - self.width - } - - fn getHeight(&self) -> usize { - self.height - } - - fn isCropSupported(&self) -> bool { - return true; - } - - fn crop( - &self, - left: usize, - top: usize, - width: usize, - height: usize, - ) -> Result, Exceptions> { - match RGBLuminanceSource::new_complex( - &self.luminances, - self.dataWidth, - self.dataHeight, - self.left + left, - self.top + top, - width, - height, - ) { - Ok(crop) => Ok(Box::new(crop)), - Err(_error) => Err(Exceptions::UnsupportedOperationException("".to_owned())), - } - } - - fn invert(&mut self) { - self.invert = !self.invert; - } -} - -impl RGBLuminanceSource { - pub fn new_with_width_height_pixels(width: usize, height: usize, pixels: &Vec) -> Self { - //super(width, height); - - let dataWidth = width; - let dataHeight = height; - let left = 0; - let top = 0; - - // In order to measure pure decoding speed, we convert the entire image to a greyscale array - // up front, which is the same as the Y channel of the YUVLuminanceSource in the real app. - // - // Total number of pixels suffices, can ignore shape - let size = width * height; - let mut luminances: Vec = vec![0; size]; - for offset in 0..size { - //for (int offset = 0; offset < size; offset++) { - let pixel = pixels[offset]; - let r = (pixel >> 16) & 0xff; // red - let g2 = (pixel >> 7) & 0x1fe; // 2 * green - let b = pixel & 0xff; // blue - // Calculate green-favouring average cheaply - luminances[offset] = ((r + g2 + b) / 4).try_into().unwrap(); - } - Self { - luminances, - dataWidth, - dataHeight, - left: left, - top: top, - width, - height, - invert: false, - } - } - - fn new_complex( - pixels: &Vec, - data_width: usize, - data_height: usize, - left: usize, - top: usize, - width: usize, - height: usize, - ) -> Result { - if left + width > data_width || top + height > data_height { - return Err(Exceptions::IllegalArgumentException( - "Crop rectangle does not fit within image data.".to_owned(), - )); - } - Ok(Self { - luminances: pixels.clone(), - dataWidth: data_width, - dataHeight: data_height, - left, - top, - width, - height, - invert: false, - }) - } -} +mod rgb_luminance_source; +pub use rgb_luminance_source::*; diff --git a/src/luminance_source.rs b/src/luminance_source.rs new file mode 100644 index 0000000..65b6d7c --- /dev/null +++ b/src/luminance_source.rs @@ -0,0 +1,173 @@ + +/* + * Copyright 2009 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; + +use crate::Exceptions; + +/** + * The purpose of this class hierarchy is to abstract different bitmap implementations across + * platforms into a standard interface for requesting greyscale luminance values. The interface + * only provides immutable methods; therefore crop and rotation create copies. This is to ensure + * that one Reader does not modify the original luminance source and leave it in an unknown state + * for other Readers in the chain. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +pub trait LuminanceSource { + //private final int width; + //private final int height; + + //fn new( width:usize, height:usize) -> Self; + + /** + * Fetches one row of luminance data from the underlying platform's bitmap. Values range from + * 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have + * to bitwise and with 0xff for each value. It is preferable for implementations of this method + * to only fetch this row rather than the whole image, since no 2D Readers may be installed and + * getMatrix() may never be called. + * + * @param y The row to fetch, which must be in [0,getHeight()) + * @param row An optional preallocated array. If null or too small, it will be ignored. + * Always use the returned object, and ignore the .length of the array. + * @return An array containing the luminance data. + */ + fn getRow(&self, y: usize, row: &Vec) -> Vec; + + /** + * Fetches luminance data for the underlying bitmap. Values should be fetched using: + * {@code int luminance = array[y * width + x] & 0xff} + * + * @return A row-major 2D array of luminance values. Do not use result.length as it may be + * larger than width * height bytes on some platforms. Do not modify the contents + * of the result. + */ + fn getMatrix(&self) -> Vec; + + /** + * @return The width of the bitmap. + */ + fn getWidth(&self) -> usize; + + /** + * @return The height of the bitmap. + */ + fn getHeight(&self) -> usize; + + /** + * @return Whether this subclass supports cropping. + */ + fn isCropSupported(&self) -> bool { + return false; + } + + /** + * Returns a new object with cropped image data. Implementations may keep a reference to the + * original data rather than a copy. Only callable if isCropSupported() is true. + * + * @param left The left coordinate, which must be in [0,getWidth()) + * @param top The top coordinate, which must be in [0,getHeight()) + * @param width The width of the rectangle to crop. + * @param height The height of the rectangle to crop. + * @return A cropped version of this object. + */ + fn crop( + &self, + left: usize, + top: usize, + width: usize, + height: usize, + ) -> Result, Exceptions> { + return Err(Exceptions::UnsupportedOperationException( + "This luminance source does not support cropping.".to_owned(), + )); + } + + /** + * @return Whether this subclass supports counter-clockwise rotation. + */ + fn isRotateSupported(&self) -> bool { + return false; + } + + /** + * @return a wrapper of this {@code LuminanceSource} which inverts the luminances it returns -- black becomes + * white and vice versa, and each value becomes (255-value). + */ + fn invert(&mut self); /* { + return InvertedLuminanceSource::new_with_delegate(self); + }*/ + + /** + * Returns a new object with rotated image data by 90 degrees counterclockwise. + * Only callable if {@link #isRotateSupported()} is true. + * + * @return A rotated version of this object. + */ + fn rotateCounterClockwise(&self) -> Result, Exceptions> { + return Err(Exceptions::UnsupportedOperationException( + "This luminance source does not support rotation by 90 degrees.".to_owned(), + )); + } + + /** + * Returns a new object with rotated image data by 45 degrees counterclockwise. + * Only callable if {@link #isRotateSupported()} is true. + * + * @return A rotated version of this object. + */ + fn rotateCounterClockwise45(&self) -> Result, Exceptions> { + return Err(Exceptions::UnsupportedOperationException( + "This luminance source does not support rotation by 45 degrees.".to_owned(), + )); + } + + fn invert_block_of_bytes(&self, vec_to_invert: Vec) -> Vec { + let mut iv = vec_to_invert.clone(); + for itm in iv.iter_mut() { + let z = *itm; + *itm = 255 - (z & 0xFF); + } + iv + } + + /* + @Override + public final String toString() { + byte[] row = new byte[width]; + StringBuilder result = new StringBuilder(height * (width + 1)); + for (int y = 0; y < height; y++) { + row = getRow(y, row); + for (int x = 0; x < width; x++) { + int luminance = row[x] & 0xFF; + char c; + if (luminance < 0x40) { + c = '#'; + } else if (luminance < 0x80) { + c = '+'; + } else if (luminance < 0xC0) { + c = '.'; + } else { + c = ' '; + } + result.append(c); + } + result.append('\n'); + } + return result.toString(); + }*/ +} \ No newline at end of file diff --git a/src/maxicode/decoder/decoder.rs b/src/maxicode/decoder/decoder.rs index bd9d62d..f92b063 100644 --- a/src/maxicode/decoder/decoder.rs +++ b/src/maxicode/decoder/decoder.rs @@ -40,7 +40,7 @@ const EVEN: u32 = 1; const ODD: u32 = 2; lazy_static! { - static ref rsDecoder: ReedSolomonDecoder = ReedSolomonDecoder::new(get_predefined_genericgf( + static ref RS_DECODER: ReedSolomonDecoder = ReedSolomonDecoder::new(get_predefined_genericgf( PredefinedGenericGF::MaxicodeField64 )); } @@ -103,7 +103,7 @@ fn correctErrors( } } // try { - rsDecoder.decode(&mut codewordsInts, (ecCodewords / divisor) as i32)?; + RS_DECODER.decode(&mut codewordsInts, (ecCodewords / divisor) as i32)?; // } catch (ReedSolomonException ignored) { // throw ChecksumException.getChecksumInstance(); // } diff --git a/src/planar_yuv_luminance_source.rs b/src/planar_yuv_luminance_source.rs new file mode 100644 index 0000000..e26f475 --- /dev/null +++ b/src/planar_yuv_luminance_source.rs @@ -0,0 +1,364 @@ + +// /* +// * Copyright 2013 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; + +// /** +// * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes +// * white and vice versa, and each value becomes (255-value). +// * +// * @author Sean Owen +// */ +// pub struct InvertedLuminanceSource { +// width: usize, +// height: usize, +// delegate: Box, +// } + +// impl InvertedLuminanceSource { +// pub fn new_with_delegate(delegate: Box) -> Self { +// Self { +// width: delegate.getWidth(), +// height: delegate.getHeight(), +// delegate, +// } +// } +// } + +// impl LuminanceSource for InvertedLuminanceSource { +// fn getRow(&self, y: usize, row: &Vec) -> Vec { +// let mut new_row = self.delegate.getRow(y, row); +// let width = self.getWidth(); +// for i in 0..width { +// //for (int i = 0; i < width; i++) { +// new_row[i] = 255 - (new_row[i] & 0xFF); +// } +// return new_row; +// } + +// fn getMatrix(&self) -> Vec { +// let matrix = self.delegate.getMatrix(); +// let length = self.getWidth() * self.getHeight(); +// let mut invertedMatrix = Vec::with_capacity(length); +// for i in 0..length { +// //for (int i = 0; i < length; i++) { +// invertedMatrix[i] = 255 - (matrix[i] & 0xFF); +// } +// return invertedMatrix; +// } + +// fn getWidth(&self) -> usize { +// self.width +// } + +// fn getHeight(&self) -> usize { +// self.height +// } + +// fn isCropSupported(&self) -> bool { +// return self.delegate.isCropSupported(); +// } + +// fn crop( +// &self, +// left: usize, +// top: usize, +// width: usize, +// height: usize, +// ) -> Result, UnsupportedOperationException> { +// let crop = self.delegate.crop(left, top, width, height)?; +// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(crop))); +// } + +// fn isRotateSupported(&self) -> bool { +// return self.delegate.isRotateSupported(); +// } + +// /** +// * @return original delegate {@link LuminanceSource} since invert undoes itself +// */ +// fn invert(&self) -> Box { +// return self.delegate; +// } + +// fn rotateCounterClockwise( +// &self, +// ) -> Result, UnsupportedOperationException> { +// let rot = self.delegate.rotateCounterClockwise()?; +// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(rot))); +// } + +// fn rotateCounterClockwise45( +// &self, +// ) -> Result, UnsupportedOperationException> { +// let rot_45 = self.delegate.rotateCounterClockwise45()?; +// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(rot_45))); +// } +// } + +/* + * Copyright 2009 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; + +use crate::{Exceptions, LuminanceSource}; + +const THUMBNAIL_SCALE_FACTOR: usize = 2; + +/** + * This object extends LuminanceSource around an array of YUV data returned from the camera driver, + * with the option to crop to a rectangle within the full data. This can be used to exclude + * superfluous pixels around the perimeter and speed up decoding. + * + * It works for any pixel format where the Y channel is planar and appears first, including + * YCbCr_420_SP and YCbCr_422_SP. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +#[derive(Debug, Clone)] +pub struct PlanarYUVLuminanceSource { + yuv_data: Vec, + data_width: usize, + data_height: usize, + left: usize, + top: usize, + width: usize, + height: usize, + invert: bool, +} + +impl PlanarYUVLuminanceSource { + pub fn new_with_all( + yuv_data: Vec, + data_width: usize, + data_height: usize, + left: usize, + top: usize, + width: usize, + height: usize, + reverse_horizontal: bool, + inverted: bool, + ) -> Result { + if left + width > data_width || top + height > data_height { + return Err(Exceptions::IllegalArgumentException( + "Crop rectangle does not fit within image data.".to_owned(), + )); + } + + let mut new_s: Self = Self { + yuv_data, + data_width, + data_height, + left, + top, + width, + height, + invert: inverted, + }; + + if reverse_horizontal { + new_s.reverseHorizontal(width, height); + } + + Ok(new_s) + } + + pub fn renderThumbnail(&self) -> Vec { + let width = self.getWidth() / THUMBNAIL_SCALE_FACTOR; + let height = self.getHeight() / THUMBNAIL_SCALE_FACTOR; + let mut pixels = vec![0; width * height]; + let yuv = &self.yuv_data; + let mut input_offset = self.top * self.data_width + self.left; + + for y in 0..height { + //for (int y = 0; y < height; y++) { + let output_offset = y * width; + for x in 0..width { + //for (int x = 0; x < width; x++) { + let grey = yuv[input_offset + x * THUMBNAIL_SCALE_FACTOR] & 0xff; + pixels[output_offset + x] = (0xFF000000 | (grey as u32 * 0x00010101)) as u8; + } + input_offset += self.data_width * THUMBNAIL_SCALE_FACTOR; + } + return pixels; + } + + /** + * @return width of image from {@link #renderThumbnail()} + */ + pub fn getThumbnailWidth(&self) -> usize { + return self.getWidth() / THUMBNAIL_SCALE_FACTOR; + } + + /** + * @return height of image from {@link #renderThumbnail()} + */ + pub fn getThumbnailHeight(&self) -> usize { + return self.getHeight() / THUMBNAIL_SCALE_FACTOR; + } + + fn reverseHorizontal(&mut self, width: usize, height: usize) { + //let mut yuvData = self.yuvData; + let mut rowStart = self.top * self.data_width + self.left; + for _y in 0..height { + let middle = rowStart + width / 2; + let mut x2 = rowStart + width - 1; + for x1 in rowStart..middle { + //for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { + let temp = self.yuv_data[x1]; + self.yuv_data[x1] = self.yuv_data[x2]; + self.yuv_data[x2] = temp; + x2 -= 1; + } + rowStart += self.data_width; + } + //self.yuvData = yuvData; + /*for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) { + let middle = rowStart + width / 2; + for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { + let temp = yuvData[x1]; + yuvData[x1] = yuvData[x2]; + yuvData[x2] = temp; + } + }*/ + } +} + +impl LuminanceSource for PlanarYUVLuminanceSource { + fn getRow(&self, y: usize, row: &Vec) -> Vec { + if y >= self.getHeight() { + //throw new IllegalArgumentException("Requested row is outside the image: " + y); + panic!("Requested row is outside the image: {}", y); + } + let width = self.getWidth(); + + let offset = (y + self.top) * self.data_width + self.left; + + let mut row = if row.len() >= width { + row.to_vec() + } else { + vec![0; width] + }; + + row[..width].clone_from_slice(&self.yuv_data[offset..width + offset]); + //System.arraycopy(yuvData, offset, row, 0, width); + if self.invert { + row = self.invert_block_of_bytes(row); + } + return row; + } + + fn getMatrix(&self) -> Vec { + let width = self.getWidth(); + let height = self.getHeight(); + + // If the caller asks for the entire underlying image, save the copy and give them the + // original data. The docs specifically warn that result.length must be ignored. + if width == self.data_width && height == self.data_height { + let mut v = self.yuv_data.clone(); + if self.invert { + v = self.invert_block_of_bytes(v); + } + return v; + } + + let area = width * height; + let mut matrix = vec![0; area]; + let mut inputOffset = self.top * self.data_width + self.left; + + // If the width matches the full width of the underlying data, perform a single copy. + if width == self.data_width { + matrix[0..area].clone_from_slice(&self.yuv_data[inputOffset..area]); + //System.arraycopy(yuvData, inputOffset, matrix, 0, area); + if self.invert { + matrix = self.invert_block_of_bytes(matrix); + } + return matrix; + } + + // Otherwise copy one cropped row at a time. + for y in 0..height { + //for (int y = 0; y < height; y++) { + let outputOffset = y * width; + matrix[outputOffset..outputOffset + width] + .clone_from_slice(&self.yuv_data[inputOffset..inputOffset + width]); + //System.arraycopy(yuvData, inputOffset, matrix, outputOffset, width); + inputOffset += self.data_width; + } + + if self.invert { + matrix = self.invert_block_of_bytes(matrix); + } + + return matrix; + } + + fn getWidth(&self) -> usize { + self.width + } + + fn getHeight(&self) -> usize { + self.height + } + + fn isCropSupported(&self) -> bool { + return true; + } + + fn crop( + &self, + left: usize, + top: usize, + width: usize, + height: usize, + ) -> Result, Exceptions> { + match PlanarYUVLuminanceSource::new_with_all( + self.yuv_data.clone(), + self.data_width, + self.data_height, + self.left + left, + self.top + top, + width, + height, + false, + self.invert, + ) { + Ok(new) => Ok(Box::new(new)), + Err(_err) => Err(Exceptions::UnsupportedOperationException("".to_owned())), + } + } + + fn isRotateSupported(&self) -> bool { + return false; + } + + fn invert(&mut self) { + self.invert = !self.invert; + } +} \ No newline at end of file diff --git a/src/qrcode/QRCodeWriterTestCase.rs b/src/qrcode/QRCodeWriterTestCase.rs index 77cf52e..e4b24b0 100644 --- a/src/qrcode/QRCodeWriterTestCase.rs +++ b/src/qrcode/QRCodeWriterTestCase.rs @@ -16,11 +16,10 @@ use std::{ collections::HashMap, - hash::Hash, - path::{Path, PathBuf}, + path::{ PathBuf}, }; -use image::{DynamicImage, EncodableLayout}; +use image::{DynamicImage}; use crate::{ common::BitMatrix, qrcode::QRCodeWriter, BarcodeFormat, EncodeHintType, EncodeHintValue, Writer, diff --git a/src/qrcode/detector/detector.rs b/src/qrcode/detector/detector.rs index 99f5882..cc7d183 100644 --- a/src/qrcode/detector/detector.rs +++ b/src/qrcode/detector/detector.rs @@ -18,12 +18,12 @@ use std::collections::HashMap; use crate::{ common::{ - detector::MathUtils, BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler, + detector::MathUtils, BitMatrix, DefaultGridSampler, GridSampler, PerspectiveTransform, }, qrcode::decoder::Version, result_point_utils, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, - RXingResultPoint, RXingResultPointCallback, ResultPoint, + RXingResultPointCallback, ResultPoint, }; use super::{ diff --git a/src/qrcode/detector/finder_pattern_finder.rs b/src/qrcode/detector/finder_pattern_finder.rs index 27509c3..0902566 100755 --- a/src/qrcode/detector/finder_pattern_finder.rs +++ b/src/qrcode/detector/finder_pattern_finder.rs @@ -14,11 +14,9 @@ * limitations under the License. */ -use std::{fs::File, io::Write}; - use crate::{ common::BitMatrix, result_point_utils, DecodeHintType, DecodingHintDictionary, Exceptions, - RXingResultPoint, RXingResultPointCallback, ResultPoint, + RXingResultPointCallback, ResultPoint, }; use super::{FinderPattern, FinderPatternInfo}; diff --git a/src/qrcode/detector/qrcode_detector_result.rs b/src/qrcode/detector/qrcode_detector_result.rs index 63b0864..902a533 100644 --- a/src/qrcode/detector/qrcode_detector_result.rs +++ b/src/qrcode/detector/qrcode_detector_result.rs @@ -1,6 +1,6 @@ use crate::{ common::{BitMatrix, DetectorRXingResult}, - RXingResultPoint, ResultPoint, + RXingResultPoint, }; pub struct QRCodeDetectorResult { diff --git a/src/qrcode/encoder/BitVectorTestCase.rs b/src/qrcode/encoder/BitVectorTestCase.rs index 27efc8b..0797fe8 100644 --- a/src/qrcode/encoder/BitVectorTestCase.rs +++ b/src/qrcode/encoder/BitVectorTestCase.rs @@ -23,10 +23,10 @@ use crate::common::BitArray; fn getUnsignedInt(v: &BitArray) -> u64 { let mut result = 0u64; - const offset: usize = 0; + const OFFSET: usize = 0; for i in 0..32 { // for (int i = 0, offset = 0; i < 32; i++) { - if v.get(offset + i) { + if v.get(OFFSET + i) { result |= 1 << (31 - i); } } @@ -82,15 +82,15 @@ fn testAppendBit() { #[test] fn testAppendBits() { let mut v = BitArray::new(); - v.appendBits(0x1, 1); + v.appendBits(0x1, 1).expect("append"); assert_eq!(1, v.getSize()); assert_eq!(0x80000000, getUnsignedInt(&v)); let mut v = BitArray::new(); - v.appendBits(0xff, 8); + v.appendBits(0xff, 8).expect("append"); assert_eq!(8, v.getSize()); assert_eq!(0xff000000, getUnsignedInt(&v)); let mut v = BitArray::new(); - v.appendBits(0xff7, 12); + v.appendBits(0xff7, 12).expect("append"); assert_eq!(12, v.getSize()); assert_eq!(0xff700000, getUnsignedInt(&v)); } @@ -102,11 +102,11 @@ fn testNumBytes() { v.appendBit(false); // 1 bit was added in the vector, so 1 byte should be consumed. assert_eq!(1, v.getSizeInBytes()); - v.appendBits(0, 7); + v.appendBits(0, 7).expect("append"); assert_eq!(1, v.getSizeInBytes()); - v.appendBits(0, 8); + v.appendBits(0, 8).expect("append"); assert_eq!(2, v.getSizeInBytes()); - v.appendBits(0, 1); + v.appendBits(0, 1).expect("append"); // We now have 17 bits, so 3 bytes should be consumed. assert_eq!(3, v.getSizeInBytes()); } @@ -114,9 +114,9 @@ fn testNumBytes() { #[test] fn testAppendBitVector() { let mut v1 = BitArray::new(); - v1.appendBits(0xbe, 8); + v1.appendBits(0xbe, 8).expect("append"); let mut v2 = BitArray::new(); - v2.appendBits(0xef, 8); + v2.appendBits(0xef, 8).expect("append"); v1.appendBitArray(v2); // beef = 1011 1110 1110 1111 assert_eq!(" X.XXXXX. XXX.XXXX", v1.to_string()); @@ -125,9 +125,9 @@ fn testAppendBitVector() { #[test] fn testXOR() { let mut v1 = BitArray::new(); - v1.appendBits(0x5555aaaa, 32); + v1.appendBits(0x5555aaaa, 32).expect("append"); let mut v2 = BitArray::new(); - v2.appendBits(0xaaaa5555, 32); + v2.appendBits(0xaaaa5555, 32).expect("append"); v1.xor(&v2); assert_eq!(0xffffffff, getUnsignedInt(&v1)); } @@ -135,7 +135,7 @@ fn testXOR() { #[test] fn testXOR2() { let mut v1 = BitArray::new(); - v1.appendBits(0x2a, 7); // 010 1010 + v1.appendBits(0x2a, 7).expect("append"); // 010 1010 let mut v2 = BitArray::new(); v2.appendBits(0x55, 7); // 101 0101 v1.xor(&v2); @@ -145,7 +145,7 @@ fn testXOR2() { #[test] fn testAt() { let mut v = BitArray::new(); - v.appendBits(0xdead, 16); // 1101 1110 1010 1101 + v.appendBits(0xdead, 16).expect("append"); // 1101 1110 1010 1101 assert!(v.get(0)); assert!(v.get(1)); assert!(!v.get(2)); @@ -170,6 +170,6 @@ fn testAt() { #[test] fn testToString() { let mut v = BitArray::new(); - v.appendBits(0xdead, 16); // 1101 1110 1010 1101 + v.appendBits(0xdead, 16).expect("append"); // 1101 1110 1010 1101 assert_eq!(" XX.XXXX. X.X.XX.X", v.to_string()); } diff --git a/src/qrcode/encoder/EncoderTestCase.rs b/src/qrcode/encoder/EncoderTestCase.rs index 3973477..d297ee7 100644 --- a/src/qrcode/encoder/EncoderTestCase.rs +++ b/src/qrcode/encoder/EncoderTestCase.rs @@ -686,23 +686,23 @@ fn testInterleaveWithECBytes() { fn testAppendNumericBytes() { // 1 = 01 = 0001 in 4 bits. let mut bits = BitArray::new(); - encoder::appendNumericBytes("1", &mut bits); + encoder::appendNumericBytes("1", &mut bits).expect("append"); assert_eq!(" ...X", bits.to_string()); // 12 = 0xc = 0001100 in 7 bits. let mut bits = BitArray::new(); - encoder::appendNumericBytes("12", &mut bits); + encoder::appendNumericBytes("12", &mut bits).expect("append"); assert_eq!(" ...XX..", bits.to_string()); // 123 = 0x7b = 0001111011 in 10 bits. let mut bits = BitArray::new(); - encoder::appendNumericBytes("123", &mut bits); + encoder::appendNumericBytes("123", &mut bits).expect("append"); assert_eq!(" ...XXXX. XX", bits.to_string()); // 1234 = "123" + "4" = 0001111011 + 0100 let mut bits = BitArray::new(); - encoder::appendNumericBytes("1234", &mut bits); + encoder::appendNumericBytes("1234", &mut bits).expect("append"); assert_eq!(" ...XXXX. XX.X..", bits.to_string()); // Empty. let mut bits = BitArray::new(); - encoder::appendNumericBytes("", &mut bits); + encoder::appendNumericBytes("", &mut bits).expect("append"); assert_eq!("", bits.to_string()); } @@ -710,19 +710,19 @@ fn testAppendNumericBytes() { fn testAppendAlphanumericBytes() { // A = 10 = 0xa = 001010 in 6 bits let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("A", &mut bits); + encoder::appendAlphanumericBytes("A", &mut bits).expect("append"); assert_eq!(" ..X.X.", bits.to_string()); // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("AB", &mut bits); + encoder::appendAlphanumericBytes("AB", &mut bits).expect("append"); assert_eq!(" ..XXX..X X.X", bits.to_string()); // ABC = "AB" + "C" = 00111001101 + 001100 let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("ABC", &mut bits); + encoder::appendAlphanumericBytes("ABC", &mut bits).expect("append"); assert_eq!(" ..XXX..X X.X..XX. .", bits.to_string()); // Empty. let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("", &mut bits); + encoder::appendAlphanumericBytes("", &mut bits).expect("append"); assert_eq!("", bits.to_string()); // Invalid data. // try { @@ -738,11 +738,11 @@ fn testAppendAlphanumericBytes() { fn testAppend8BitBytes() { // 0x61, 0x62, 0x63 let mut bits = BitArray::new(); - encoder::append8BitBytes("abc", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + encoder::append8BitBytes("abc", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).expect("append"); assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string()); // Empty. let mut bits = BitArray::new(); - encoder::append8BitBytes("", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + encoder::append8BitBytes("", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).expect("append"); assert_eq!("", bits.to_string()); } @@ -750,9 +750,9 @@ fn testAppend8BitBytes() { #[test] fn testAppendKanjiBytes() { let mut bits = BitArray::new(); - encoder::appendKanjiBytes(&shiftJISString(&[0x93, 0x5f]), &mut bits); + encoder::appendKanjiBytes(&shiftJISString(&[0x93, 0x5f]), &mut bits).expect("append"); assert_eq!(" .XX.XX.. XXXXX", bits.to_string()); - encoder::appendKanjiBytes(&shiftJISString(&[0xe4, 0xaa]), &mut bits); + encoder::appendKanjiBytes(&shiftJISString(&[0xe4, 0xaa]), &mut bits).expect("append"); assert_eq!(" .XX.XX.. XXXXXXX. X.X.X.X. X.", bits.to_string()); } @@ -826,7 +826,7 @@ fn testBugInBitVectorNumBytes() { // 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468 // bytes). let mut builder = String::with_capacity(3518); - for x in 0..3518 { + for _x in 0..3518 { // for (int x = 0; x < 3518; x++) { builder.push('0'); } diff --git a/src/qrcode/encoder/MatrixUtilTestCase.rs b/src/qrcode/encoder/MatrixUtilTestCase.rs index 1a5aebf..57b7bf9 100644 --- a/src/qrcode/encoder/MatrixUtilTestCase.rs +++ b/src/qrcode/encoder/MatrixUtilTestCase.rs @@ -209,7 +209,7 @@ fn testEmbedDataBits() { ) .expect("op ok"); let bits = BitArray::new(); - matrix_util::embedDataBits(&bits, -1, &mut matrix); + matrix_util::embedDataBits(&bits, -1, &mut matrix).expect("append"); let expected = r" 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1 @@ -254,7 +254,7 @@ fn testBuildMatrix() { Version::getVersionForNumber(1).expect("version"), // Version 1 3, // Mask pattern 3 &mut matrix, - ); + ).expect("append"); let expected = r" 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1 @@ -344,6 +344,6 @@ fn testMakeVersionInfoBits() { fn testMakeTypeInfoInfoBits() { // From Appendix C in JISX0510:2004 (p 65) let mut bits = BitArray::new(); - matrix_util::makeTypeInfoBits(&ErrorCorrectionLevel::M, 5, &mut bits); + matrix_util::makeTypeInfoBits(&ErrorCorrectionLevel::M, 5, &mut bits).expect("append"); assert_eq!(" X......X X..XXX.", bits.to_string()); } diff --git a/src/qrcode/encoder/encoder.rs b/src/qrcode/encoder/encoder.rs index 6ea5427..b688130 100644 --- a/src/qrcode/encoder/encoder.rs +++ b/src/qrcode/encoder/encoder.rs @@ -43,7 +43,7 @@ use unicode_segmentation::UnicodeSegmentation; use crate::{ common::{ reedsolomon::{get_predefined_genericgf, PredefinedGenericGF, ReedSolomonEncoder}, - BitArray, CharacterSetECI, StringUtils, + BitArray, CharacterSetECI, }, qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef}, EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions, diff --git a/src/qrcode/encoder/minimal_encoder.rs b/src/qrcode/encoder/minimal_encoder.rs index f461d35..6cca0f8 100644 --- a/src/qrcode/encoder/minimal_encoder.rs +++ b/src/qrcode/encoder/minimal_encoder.rs @@ -24,7 +24,7 @@ use crate::{ Exceptions, }; -use unicode_segmentation::{Graphemes, UnicodeSegmentation}; +use unicode_segmentation::{ UnicodeSegmentation}; use super::encoder; diff --git a/src/qrcode/qr_code_reader.rs b/src/qrcode/qr_code_reader.rs index a647637..8c3ece3 100644 --- a/src/qrcode/qr_code_reader.rs +++ b/src/qrcode/qr_code_reader.rs @@ -19,7 +19,7 @@ use std::collections::HashMap; use crate::{ common::{BitMatrix, DecoderRXingResult, DetectorRXingResult}, BarcodeFormat, DecodeHintType, Exceptions, RXingResult, RXingResultMetadataType, - RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint, + RXingResultMetadataValue, RXingResultPoint, Reader, }; use super::{ diff --git a/src/reader.rs b/src/reader.rs new file mode 100644 index 0000000..544f600 --- /dev/null +++ b/src/reader.rs @@ -0,0 +1,71 @@ + +/* + * 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; + +use crate::{BinaryBitmap, RXingResult, Exceptions, DecodingHintDictionary}; + +/** + * Implementations of this interface can decode an image of a barcode in some format into + * the String it encodes. For example, {@link com.google.zxing.qrcode.QRCodeReader} can + * decode a QR code. The decoder may optionally receive hints from the caller which may help + * it decode more quickly or accurately. + * + * See {@link MultiFormatReader}, which attempts to determine what barcode + * format is present within the image as well, and then decodes it accordingly. + * + * @author Sean Owen + * @author dswitkin@google.com (Daniel Switkin) + */ +pub trait Reader { + /** + * Locates and decodes a barcode in some format within an image. + * + * @param image image of barcode to decode + * @return String which the barcode encodes + * @throws NotFoundException if no potential barcode is found + * @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; + + /** + * Locates and decodes a barcode in some format within an image. This method also accepts + * hints, each possibly associated to some data, which may help the implementation decode. + * + * @param image image of barcode to decode + * @param hints passed as a {@link Map} from {@link DecodeHintType} + * to arbitrary data. The + * meaning of the data depends upon the hint type. The implementation may or may not do + * anything with these hints. + * @return String which the barcode encodes + * @throws NotFoundException if no potential barcode is found + * @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_with_hints( + &self, + image: &BinaryBitmap, + hints: &DecodingHintDictionary, + ) -> Result; + + /** + * Resets any internal state the implementation has after a decode, to prepare it + * for reuse. + */ + fn reset(&self); +} \ No newline at end of file diff --git a/src/result_point.rs b/src/result_point.rs new file mode 100644 index 0000000..4261eff --- /dev/null +++ b/src/result_point.rs @@ -0,0 +1,26 @@ + +/* + * 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; + +use crate::RXingResultPoint; + +pub trait ResultPoint { + fn getX(&self) -> f32; + fn getY(&self) -> f32; + fn into_rxing_result_point(self) -> RXingResultPoint; +} \ No newline at end of file diff --git a/src/result_point_utils.rs b/src/result_point_utils.rs new file mode 100644 index 0000000..c0bf936 --- /dev/null +++ b/src/result_point_utils.rs @@ -0,0 +1,89 @@ +use crate::{common::detector::MathUtils, ResultPoint}; + + /** + * Orders an array of three RXingResultPoints in an order [A,B,C] such that AB is less than AC + * and BC is less than AC, and the angle between BC and BA is less than 180 degrees. + * + * @param patterns array of three {@code RXingResultPoint} to order + */ + pub fn orderBestPatterns(patterns: &mut [T; 3]) { + // Find distances between pattern centers + let zeroOneDistance = MathUtils::distance_float( + patterns[0].getX(), + patterns[0].getY(), + patterns[1].getX(), + patterns[1].getY(), + ); + let oneTwoDistance = MathUtils::distance_float( + patterns[1].getX(), + patterns[1].getY(), + patterns[2].getX(), + patterns[2].getY(), + ); + let zeroTwoDistance = MathUtils::distance_float( + patterns[0].getX(), + patterns[0].getY(), + patterns[2].getX(), + patterns[2].getY(), + ); + + let mut pointA; //: &RXingResultPoint; + let pointB; //: &RXingResultPoint; + let mut pointC; //: &RXingResultPoint; + // Assume one closest to other two is B; A and C will just be guesses at first + if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance { + pointB = patterns[0]; + pointA = patterns[1]; + pointC = patterns[2]; + } else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance { + pointB = patterns[1]; + pointA = patterns[0]; + pointC = patterns[2]; + } else { + pointB = patterns[2]; + pointA = patterns[0]; + pointC = patterns[1]; + } + + // Use cross product to figure out whether A and C are correct or flipped. + // This asks whether BC x BA has a positive z component, which is the arrangement + // we want for A, B, C. If it's negative, then we've got it flipped around and + // should swap A and C. + if crossProductZ(pointA, pointB, pointC) < 0.0f32 { + let temp = pointA; + pointA = pointC; + pointC = temp; + } + + let pa = pointA; + let pb = pointB; + let pc = pointC; + + patterns[0] = pa; + patterns[1] = pb; + patterns[2] = pc; + } + + /** + * @param pattern1 first pattern + * @param pattern2 second pattern + * @return distance between two points + */ + pub fn distance(pattern1: &T, pattern2: &T) -> f32 { + return MathUtils::distance_float( + pattern1.getX(), + pattern1.getY(), + pattern2.getX(), + pattern2.getY(), + ); + } + + /** + * Returns the z component of the cross product between vectors BC and BA. + */ + pub fn crossProductZ(pointA: T, pointB: T, pointC: T) -> f32 { + let bX = pointB.getX(); + let bY = pointB.getY(); + return ((pointC.getX() - bX) * (pointA.getY() - bY)) + - ((pointC.getY() - bY) * (pointA.getX() - bX)); + } \ No newline at end of file diff --git a/src/rgb_luminance_source.rs b/src/rgb_luminance_source.rs new file mode 100644 index 0000000..5efe4e2 --- /dev/null +++ b/src/rgb_luminance_source.rs @@ -0,0 +1,207 @@ + +/* + * Copyright 2009 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; + +use crate::{Exceptions, LuminanceSource}; + +/** + * This class is used to help decode images from files which arrive as RGB data from + * an ARGB pixel array. It does not support rotation. + * + * @author dswitkin@google.com (Daniel Switkin) + * @author Betaminos + */ +#[derive(Debug, Clone)] +pub struct RGBLuminanceSource { + luminances: Vec, + dataWidth: usize, + dataHeight: usize, + left: usize, + top: usize, + width: usize, + height: usize, + invert: bool, +} + +impl LuminanceSource for RGBLuminanceSource { + fn getRow(&self, y: usize, row: &Vec) -> Vec { + if y >= self.getHeight() { + panic!("Requested row is outside the image: {}", y); + } + let width = self.getWidth(); + + let offset = (y + self.top) * self.dataWidth + self.left; + + let mut row = if row.len() >= width { + row.to_vec() + } else { + vec![0; width] + }; + + row[..width].clone_from_slice(&self.luminances[offset..offset + width]); + //System.arraycopy(self.luminances, offset, row, 0, width); + if self.invert { + row = self.invert_block_of_bytes(row); + } + return row; + } + + fn getMatrix(&self) -> Vec { + let width = self.getWidth(); + let height = self.getHeight(); + + // If the caller asks for the entire underlying image, save the copy and give them the + // original data. The docs specifically warn that result.length must be ignored. + if width == self.dataWidth && height == self.dataHeight { + let mut z = self.luminances.clone(); + if self.invert { + z = self.invert_block_of_bytes(z); + } + return z; + } + + let area = width * height; + let mut matrix = vec![0; area]; + let mut inputOffset = self.top * self.dataWidth + self.left; + + // If the width matches the full width of the underlying data, perform a single copy. + if width == self.dataWidth { + matrix[..area].clone_from_slice(&self.luminances[inputOffset..area + inputOffset]); + //System.arraycopy(self.luminances, inputOffset, matrix, 0, area); + if self.invert { + matrix = self.invert_block_of_bytes(matrix); + } + return matrix; + } + + // Otherwise copy one cropped row at a time. + for y in 0..height { + //for (int y = 0; y < height; y++) { + let outputOffset = y * width; + matrix[outputOffset..width + outputOffset] + .clone_from_slice(&self.luminances[inputOffset..width + inputOffset]); + //System.arraycopy(luminances, inputOffset, matrix, outputOffset, width); + inputOffset += self.dataWidth; + } + + if self.invert { + matrix = self.invert_block_of_bytes(matrix); + } + return matrix; + } + + fn getWidth(&self) -> usize { + self.width + } + + fn getHeight(&self) -> usize { + self.height + } + + fn isCropSupported(&self) -> bool { + return true; + } + + fn crop( + &self, + left: usize, + top: usize, + width: usize, + height: usize, + ) -> Result, Exceptions> { + match RGBLuminanceSource::new_complex( + &self.luminances, + self.dataWidth, + self.dataHeight, + self.left + left, + self.top + top, + width, + height, + ) { + Ok(crop) => Ok(Box::new(crop)), + Err(_error) => Err(Exceptions::UnsupportedOperationException("".to_owned())), + } + } + + fn invert(&mut self) { + self.invert = !self.invert; + } +} + +impl RGBLuminanceSource { + pub fn new_with_width_height_pixels(width: usize, height: usize, pixels: &Vec) -> Self { + //super(width, height); + + let dataWidth = width; + let dataHeight = height; + let left = 0; + let top = 0; + + // In order to measure pure decoding speed, we convert the entire image to a greyscale array + // up front, which is the same as the Y channel of the YUVLuminanceSource in the real app. + // + // Total number of pixels suffices, can ignore shape + let size = width * height; + let mut luminances: Vec = vec![0; size]; + for offset in 0..size { + //for (int offset = 0; offset < size; offset++) { + let pixel = pixels[offset]; + let r = (pixel >> 16) & 0xff; // red + let g2 = (pixel >> 7) & 0x1fe; // 2 * green + let b = pixel & 0xff; // blue + // Calculate green-favouring average cheaply + luminances[offset] = ((r + g2 + b) / 4).try_into().unwrap(); + } + Self { + luminances, + dataWidth, + dataHeight, + left: left, + top: top, + width, + height, + invert: false, + } + } + + fn new_complex( + pixels: &Vec, + data_width: usize, + data_height: usize, + left: usize, + top: usize, + width: usize, + height: usize, + ) -> Result { + if left + width > data_width || top + height > data_height { + return Err(Exceptions::IllegalArgumentException( + "Crop rectangle does not fit within image data.".to_owned(), + )); + } + Ok(Self { + luminances: pixels.clone(), + dataWidth: data_width, + dataHeight: data_height, + left, + top, + width, + height, + invert: false, + }) + } +} \ No newline at end of file diff --git a/src/rxing_result.rs b/src/rxing_result.rs new file mode 100644 index 0000000..b3701dd --- /dev/null +++ b/src/rxing_result.rs @@ -0,0 +1,180 @@ + +/* + * 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 java.util.EnumMap; +//import java.util.Map; + +use std::{fmt, collections::HashMap, time::{SystemTime, UNIX_EPOCH}}; + +use crate::{RXingResultMetadataValue, RXingResultMetadataType, BarcodeFormat, RXingResultPoint}; + +/** + *

Encapsulates the result of decoding a barcode within an image.

+ * + * @author Sean Owen + */ +pub struct RXingResult { + text: String, + rawBytes: Vec, + numBits: usize, + resultPoints: Vec, + format: BarcodeFormat, + resultMetadata: HashMap, + timestamp: u128, +} +impl RXingResult { + pub fn new( + text: &str, + rawBytes: Vec, + resultPoints: Vec, + format: BarcodeFormat, + ) -> Self { + Self::new_timestamp( + text, + rawBytes, + resultPoints, + format, + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_millis(), + ) + } + + pub fn new_timestamp( + text: &str, + rawBytes: Vec, + resultPoints: Vec, + format: BarcodeFormat, + timestamp: u128, + ) -> Self { + let l = rawBytes.len(); + Self::new_complex(text, rawBytes, 8 * l, resultPoints, format, timestamp) + } + + pub fn new_complex( + text: &str, + rawBytes: Vec, + numBits: usize, + resultPoints: Vec, + format: BarcodeFormat, + timestamp: u128, + ) -> Self { + Self { + text: text.to_owned(), + rawBytes: rawBytes, + numBits, + resultPoints, + format, + resultMetadata: HashMap::new(), + timestamp, + } + } + + /** + * @return raw text encoded by the barcode + */ + pub fn getText(&self) -> &String { + return &self.text; + } + + /** + * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null} + */ + pub fn getRawBytes(&self) -> &Vec { + return &self.rawBytes; + } + + /** + * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length + * @since 3.3.0 + */ + pub fn getNumBits(&self) -> usize { + return self.numBits; + } + + /** + * @return points related to the barcode in the image. These are typically points + * identifying finder patterns or the corners of the barcode. The exact meaning is + * specific to the type of barcode that was decoded. + */ + pub fn getRXingResultPoints(&self) -> &Vec { + return &self.resultPoints; + } + + /** + * @return {@link BarcodeFormat} representing the format of the barcode that was decoded + */ + pub fn getBarcodeFormat(&self) -> &BarcodeFormat { + return &self.format; + } + + /** + * @return {@link Map} mapping {@link RXingResultMetadataType} keys to values. May be + * {@code null}. This contains optional metadata about what was detected about the barcode, + * like orientation. + */ + pub fn getRXingResultMetadata( + &self, + ) -> &HashMap { + return &self.resultMetadata; + } + + pub fn putMetadata( + &mut self, + md_type: RXingResultMetadataType, + value: RXingResultMetadataValue, + ) { + self.resultMetadata.insert(md_type, value); + } + + pub fn putAllMetadata( + &mut self, + metadata: HashMap, + ) { + if self.resultMetadata.is_empty() { + self.resultMetadata = metadata; + } else { + for (key, value) in metadata.into_iter() { + self.resultMetadata.insert(key, value); + } + } + } + + pub fn addRXingResultPoints(&mut self, newPoints: &mut Vec) { + //RXingResultPoint[] oldPoints = resultPoints; + if !newPoints.is_empty() { + // let allPoints:Vec= Vec::with_capacity(oldPoints.len() + newPoints.len()); + //System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length); + //System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length); + //resultPoints = allPoints; + self.resultPoints.append(newPoints); + } + } + + pub fn getTimestamp(&self) -> u128 { + return self.timestamp; + } +} + +impl fmt::Display for RXingResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.text) + } +} \ No newline at end of file diff --git a/src/rxing_result_metadata.rs b/src/rxing_result_metadata.rs new file mode 100644 index 0000000..d27d474 --- /dev/null +++ b/src/rxing_result_metadata.rs @@ -0,0 +1,204 @@ + +/* + * 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; + +/** + * Represents some type of metadata about the result of the decoding that the decoder + * wishes to communicate back to the caller. + * + * @author Sean Owen + */ +#[derive(Eq, PartialEq, Hash, Debug)] +pub enum RXingResultMetadataType { + /** + * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. + */ + OTHER, + + /** + * Denotes the likely approximate orientation of the barcode in the image. This value + * is given as degrees rotated clockwise from the normal, upright orientation. + * For example a 1D barcode which was found by reading top-to-bottom would be + * said to have orientation "90". This key maps to an {@link Integer} whose + * value is in the range [0,360). + */ + ORIENTATION, + + /** + *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' + * which is sometimes used to encode binary data. While {@link RXingResult} makes available + * the complete raw bytes in the barcode for these formats, it does not offer the bytes + * from the byte segments alone.

+ * + *

This maps to a {@link java.util.List} of byte arrays corresponding to the + * raw bytes in the byte segments in the barcode, in order.

+ */ + BYTE_SEGMENTS, + + /** + * Error correction level used, if applicable. The value type depends on the + * format, but is typically a String. + */ + ERROR_CORRECTION_LEVEL, + + /** + * For some periodicals, indicates the issue number as an {@link Integer}. + */ + ISSUE_NUMBER, + + /** + * For some products, indicates the suggested retail price in the barcode as a + * formatted {@link String}. + */ + SUGGESTED_PRICE, + + /** + * For some products, the possible country of manufacture as a {@link String} denoting the + * ISO country code. Some map to multiple possible countries, like "US/CA". + */ + POSSIBLE_COUNTRY, + + /** + * For some products, the extension text + */ + UPC_EAN_EXTENSION, + + /** + * PDF417-specific metadata + */ + PDF417_EXTRA_METADATA, + + /** + * If the code format supports structured append and the current scanned code is part of one then the + * sequence number is given with it. + */ + STRUCTURED_APPEND_SEQUENCE, + + /** + * If the code format supports structured append and the current scanned code is part of one then the + * parity is given with it. + */ + STRUCTURED_APPEND_PARITY, + + /** + * Barcode Symbology Identifier. + * Note: According to the GS1 specification the identifier may have to replace a leading FNC1/GS character + * when prepending to the barcode content. + */ + SYMBOLOGY_IDENTIFIER, +} + +impl From for RXingResultMetadataType { + fn from(in_str: String) -> Self { + match in_str.as_str() { + "OTHER" => RXingResultMetadataType::OTHER, + "ORIENTATION" => RXingResultMetadataType::ORIENTATION, + "BYTE_SEGMENTS" => RXingResultMetadataType::BYTE_SEGMENTS, + "ERROR_CORRECTION_LEVEL" => RXingResultMetadataType::ERROR_CORRECTION_LEVEL, + "ISSUE_NUMBER" => RXingResultMetadataType::ISSUE_NUMBER, + "SUGGESTED_PRICE" => RXingResultMetadataType::SUGGESTED_PRICE, + "POSSIBLE_COUNTRY" => RXingResultMetadataType::POSSIBLE_COUNTRY, + "UPC_EAN_EXTENSION" => RXingResultMetadataType::UPC_EAN_EXTENSION, + "PDF417_EXTRA_METADATA" => RXingResultMetadataType::PDF417_EXTRA_METADATA, + "STRUCTURED_APPEND_SEQUENCE" => RXingResultMetadataType::STRUCTURED_APPEND_SEQUENCE, + "STRUCTURED_APPEND_PARITY" => RXingResultMetadataType::STRUCTURED_APPEND_PARITY, + "SYMBOLOGY_IDENTIFIER" => RXingResultMetadataType::SYMBOLOGY_IDENTIFIER, + _ => RXingResultMetadataType::OTHER, + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum RXingResultMetadataValue { + /** + * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. + */ + OTHER(String), + + /** + * Denotes the likely approximate orientation of the barcode in the image. This value + * is given as degrees rotated clockwise from the normal, upright orientation. + * For example a 1D barcode which was found by reading top-to-bottom would be + * said to have orientation "90". This key maps to an {@link Integer} whose + * value is in the range [0,360). + */ + Orientation(i32), + + /** + *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' + * which is sometimes used to encode binary data. While {@link RXingResult} makes available + * the complete raw bytes in the barcode for these formats, it does not offer the bytes + * from the byte segments alone.

+ * + *

This maps to a {@link java.util.List} of byte arrays corresponding to the + * raw bytes in the byte segments in the barcode, in order.

+ */ + ByteSegments(Vec>), + + /** + * Error correction level used, if applicable. The value type depends on the + * format, but is typically a String. + */ + ErrorCorrectionLevel(String), + + /** + * For some periodicals, indicates the issue number as an {@link Integer}. + */ + IssueNumber(i32), + + /** + * For some products, indicates the suggested retail price in the barcode as a + * formatted {@link String}. + */ + SuggestedPrice(String), + + /** + * For some products, the possible country of manufacture as a {@link String} denoting the + * ISO country code. Some map to multiple possible countries, like "US/CA". + */ + PossibleCountry(String), + + /** + * For some products, the extension text + */ + UpcEanExtension(String), + + /** + * PDF417-specific metadata + */ + Pdf417ExtraMetadata(String), + + /** + * If the code format supports structured append and the current scanned code is part of one then the + * sequence number is given with it. + */ + StructuredAppendSequence(i32), + + /** + * If the code format supports structured append and the current scanned code is part of one then the + * parity is given with it. + */ + StructuredAppendParity(i32), + + /** + * Barcode Symbology Identifier. + * Note: According to the GS1 specification the identifier may have to replace a leading FNC1/GS character + * when prepending to the barcode content. + */ + SymbologyIdentifier(String), +} \ No newline at end of file diff --git a/src/rxing_result_point.rs b/src/rxing_result_point.rs new file mode 100644 index 0000000..2483d24 --- /dev/null +++ b/src/rxing_result_point.rs @@ -0,0 +1,54 @@ +use std::fmt; + +use crate::ResultPoint; +use std::hash::Hash; + + +/** + *

Encapsulates a point of interest in an image containing a barcode. Typically, this + * would be the location of a finder pattern or the corner of the barcode, for example.

+ * + * @author Sean Owen + */ +#[derive(Debug, Clone, Copy)] +pub struct RXingResultPoint { + pub(crate) x: f32, + pub(crate)y: f32, +} +impl Hash for RXingResultPoint { + fn hash(&self, state: &mut H) { + self.x.to_string().hash(state); + self.y.to_string().hash(state); + } +} +impl PartialEq for RXingResultPoint { + fn eq(&self, other: &Self) -> bool { + self.x.to_string() == other.x.to_string() && self.y.to_string() == other.y.to_string() + } +} +impl Eq for RXingResultPoint {} +impl RXingResultPoint { + pub const fn new(x: f32, y: f32) -> Self { + Self { x, y } + } +} + +impl ResultPoint for RXingResultPoint { + fn getX(&self) -> f32 { + return self.x; + } + + fn getY(&self) -> f32 { + return self.y; + } + + fn into_rxing_result_point(self) -> RXingResultPoint { + self + } +} + +impl fmt::Display for RXingResultPoint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "({},{})", self.x, self.y) + } +} \ No newline at end of file diff --git a/src/writer.rs b/src/writer.rs new file mode 100644 index 0000000..e2cc058 --- /dev/null +++ b/src/writer.rs @@ -0,0 +1,63 @@ + +/* + * 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; + +use crate::{BarcodeFormat, common::BitMatrix, Exceptions, EncodingHintDictionary}; + +/** + * The base class for all objects which encode/generate a barcode image. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +pub trait Writer { + /** + * Encode a barcode using the default settings. + * + * @param contents The contents to encode in the barcode + * @param format The barcode format to generate + * @param width The preferred width in pixels + * @param height The preferred height in pixels + * @return {@link BitMatrix} representing encoded barcode image + * @throws WriterException if contents cannot be encoded legally in a format + */ + fn encode( + &self, + contents: &str, + format: &BarcodeFormat, + width: i32, + height: i32, + ) -> Result; + + /** + * @param contents The contents to encode in the barcode + * @param format The barcode format to generate + * @param width The preferred width in pixels + * @param height The preferred height in pixels + * @param hints Additional parameters to supply to the encoder + * @return {@link BitMatrix} representing encoded barcode image + * @throws WriterException if contents cannot be encoded legally in a format + */ + fn encode_with_hints( + &self, + contents: &str, + format: &BarcodeFormat, + width: i32, + height: i32, + hints: &EncodingHintDictionary, + ) -> Result; +} \ No newline at end of file diff --git a/tests/aztec_blackbox_tests.rs b/tests/aztec_blackbox_tests.rs index 4efdb3b..8120407 100644 --- a/tests/aztec_blackbox_tests.rs +++ b/tests/aztec_blackbox_tests.rs @@ -30,12 +30,12 @@ fn aztec_black_box1_test_case() { ); // super("src/test/resources/blackbox/aztec-1", AztecReader::new(), BarcodeFormat::AZTEC); - tester.addTest(14, 14, 0.0); - tester.addTest(14, 14, 90.0); - tester.addTest(14, 14, 180.0); - tester.addTest(14, 14, 270.0); + tester.add_test(14, 14, 0.0); + tester.add_test(14, 14, 90.0); + tester.add_test(14, 14, 180.0); + tester.add_test(14, 14, 270.0); - tester.testBlackBox(); + tester.test_black_box(); } /** @@ -51,10 +51,10 @@ fn aztec_black_box2_test_case() { BarcodeFormat::AZTEC, ); // super(, new AztecReader(), BarcodeFormat.AZTEC); - tester.addTest(5, 5, 0.0); - tester.addTest(4, 4, 90.0); - tester.addTest(6, 6, 180.0); - tester.addTest(3, 3, 270.0); + tester.add_test(5, 5, 0.0); + tester.add_test(4, 4, 90.0); + tester.add_test(6, 6, 180.0); + tester.add_test(3, 3, 270.0); - tester.testBlackBox(); + tester.test_black_box(); } diff --git a/tests/common/abstract_black_box_test_case.rs b/tests/common/abstract_black_box_test_case.rs index 03f9790..15e6af2 100644 --- a/tests/common/abstract_black_box_test_case.rs +++ b/tests/common/abstract_black_box_test_case.rs @@ -43,9 +43,9 @@ pub struct AbstractBlackBoxTestCase { impl AbstractBlackBoxTestCase { - pub fn buildTestBase(testBasePathSuffix: &str) -> Box { + pub fn build_test_base(test_base_path_suffix: &str) -> Box { // A little workaround to prevent aggravation in my IDE - let test_base = Path::new(testBasePathSuffix); + let test_base = Path::new(test_base_path_suffix); // if !testBase.exists() { // // try starting with 'core' since the test base is often given as the project root // testBase = Paths.get("core").resolve(testBasePathSuffix); @@ -59,7 +59,7 @@ impl AbstractBlackBoxTestCase { expected_format: BarcodeFormat, ) -> Self { Self { - test_base: Self::buildTestBase(test_base_path_suffix), + test_base: Self::build_test_base(test_base_path_suffix), barcode_reader, expected_format, test_rxing_results: Vec::new(), @@ -67,15 +67,15 @@ impl AbstractBlackBoxTestCase { } } - pub fn getTestBase(&self) -> &Box { + pub fn get_test_base(&self) -> &Box { &self.test_base } - pub fn addTest(&mut self, must_pass_count: u32, try_harder_count: u32, rotation: f32) { - self.addTestComplex(must_pass_count, try_harder_count, 0, 0, rotation); + pub fn add_test(&mut self, must_pass_count: u32, try_harder_count: u32, rotation: f32) { + self.add_test_complex(must_pass_count, try_harder_count, 0, 0, rotation); } - pub fn addHint(&mut self, hint: DecodeHintType, value: DecodeHintValue) { + pub fn add_hint(&mut self, hint: DecodeHintType, value: DecodeHintValue) { self.hints.insert(hint, value); } @@ -89,7 +89,7 @@ impl AbstractBlackBoxTestCase { * reading the wrong contents using the try harder flag * @param rotation The rotation in degrees clockwise to use for this test. */ - pub fn addTestComplex( + pub fn add_test_complex( &mut self, must_pass_count: u32, try_harder_count: u32, @@ -106,14 +106,14 @@ impl AbstractBlackBoxTestCase { )); } - pub fn getImageFiles(&self) -> Vec { + pub fn get_image_files(&self) -> Vec { assert!( self.test_base.exists(), "Please download and install test images, and run from the 'core' directory" ); // let paths = Vec::new(); let path_search = read_dir(&self.test_base); - const possible_extensions: &str = "jpg,jpeg,gif,png,JPG,JPEG,GIF,PNG"; + const POSSIBLE_EXTENSIONS: &str = "jpg,jpeg,gif,png,JPG,JPEG,GIF,PNG"; let mut paths = path_search .unwrap() @@ -121,7 +121,7 @@ impl AbstractBlackBoxTestCase { .filter(|r| r.is_ok()) // Get rid of Err variants for Result .map(|r| r.unwrap().path()) // This is safe, since we only have the Ok variants .filter(|r| r.is_file()) // Filter out non-folders - .filter(|r| possible_extensions.contains(r.extension().unwrap().to_str().unwrap())) + .filter(|r| POSSIBLE_EXTENSIONS.contains(r.extension().unwrap().to_str().unwrap())) // .map(|r| r.into_boxed_path()) .collect::>(); @@ -130,14 +130,14 @@ impl AbstractBlackBoxTestCase { paths } - pub fn getReader(&self) -> &T { + pub fn get_reader(&self) -> &T { &self.barcode_reader } - pub fn testBlackBox(&self) { + pub fn test_black_box(&self) { assert!(!self.test_rxing_results.is_empty()); - let image_files = self.getImageFiles(); + let image_files = self.get_image_files(); let test_count = self.test_rxing_results.len(); let mut passed_counts = vec![0usize; test_count]; @@ -145,16 +145,16 @@ impl AbstractBlackBoxTestCase { let mut try_harder_counts = vec![0usize; test_count]; let mut try_harder_misread_counts = vec![0usize; test_count]; - for testImage in &image_files { + for test_image in &image_files { // for (Path testImage : imageFiles) { - log::info(format!("Starting {}", testImage.to_string_lossy())); + log::info(format!("Starting {}", test_image.to_string_lossy())); - let image = image::open(testImage).unwrap(); //ImageIO.read(testImage.toFile()); + let image = image::open(test_image).unwrap(); //ImageIO.read(testImage.toFile()); //let testImageFileName = testImage.getFileName().toString(); - let file_base_name = testImage.file_stem().unwrap(); + let file_base_name = test_image.file_stem().unwrap(); //let expectedTextFile = self.testBase.resolve(fileBaseName + ".txt"); - let mut expected_text_file = testImage.clone(); + let mut expected_text_file = test_image.clone(); expected_text_file.set_extension("txt"); let expected_text = if expected_text_file.exists() { Self::read_file_as_string(expected_text_file) @@ -171,7 +171,7 @@ impl AbstractBlackBoxTestCase { let mut expected_metadata_file: PathBuf = self.test_base.clone().to_path_buf(); expected_metadata_file.push(format!("{}.metadata", file_base_name.to_str().unwrap())); expected_metadata_file.set_extension("txt"); - let expectedMetadata_unfinished = if expected_metadata_file.exists() { + let expected_metadata_unfinished = if expected_metadata_file.exists() { java_properties::read( std::fs::File::open(expected_metadata_file) .expect("file exists, we already know that"), @@ -184,7 +184,7 @@ impl AbstractBlackBoxTestCase { HashMap::new() }; let expected_metadata = HashMap::new(); - for (k, v) in expectedMetadata_unfinished { + for (k, v) in expected_metadata_unfinished { let new_k = RXingResultMetadataType::from(k); let _new_v = match new_k { RXingResultMetadataType::OTHER => RXingResultMetadataValue::OTHER(v), @@ -230,7 +230,7 @@ impl AbstractBlackBoxTestCase { for x in 0..test_count { // for (int x = 0; x < testCount; x++) { - let rotation = self.test_rxing_results.get(x).unwrap().getRotation(); + let rotation = self.test_rxing_results.get(x).unwrap().get_rotation(); let rotated_image = Self::rotate_image(&image, rotation); let source = BufferedImageLuminanceSource::new(rotated_image); let bitmap = BinaryBitmap::new(Box::new(HybridBinarizer::new(Box::new(source)))); @@ -296,13 +296,13 @@ impl AbstractBlackBoxTestCase { let test_rxing_result = self.test_rxing_results.get(x).unwrap(); log::info(format!( "Rotation {} degrees:", - test_rxing_result.getRotation() + test_rxing_result.get_rotation() )); log::info(format!( " {} of {} images passed ({} required)", passed_counts[x], image_files.len(), - test_rxing_result.getMustPassCount() + test_rxing_result.get_must_pass_count() )); let mut failed = image_files.len() - passed_counts[x]; log::info(format!( @@ -314,7 +314,7 @@ impl AbstractBlackBoxTestCase { " {} of {} images passed with try harder ({} required)", try_harder_counts[x], image_files.len(), - test_rxing_result.getTryHarderCount() + test_rxing_result.get_try_harder_count() )); failed = image_files.len() - try_harder_counts[x]; log::info(format!( @@ -324,18 +324,18 @@ impl AbstractBlackBoxTestCase { )); total_found += passed_counts[x] + try_harder_counts[x]; total_must_pass += - test_rxing_result.getMustPassCount() + test_rxing_result.getTryHarderCount(); + test_rxing_result.get_must_pass_count() + test_rxing_result.get_try_harder_count(); total_misread += misread_counts[x] + try_harder_misread_counts[x]; total_max_misread += - test_rxing_result.getMaxMisreads() + test_rxing_result.getMaxTryHarderMisreads(); + test_rxing_result.get_max_misreads() + test_rxing_result.get_max_try_harder_misreads(); } - let totalTests = image_files.len() * test_count * 2; + let total_tests = image_files.len() * test_count * 2; log::info(format!( "Decoded {} images out of {} ({}, {} required)", total_found, - totalTests, - total_found * 100 / totalTests, + total_tests, + total_found * 100 / total_tests, total_must_pass )); if total_found > total_must_pass as usize { @@ -365,32 +365,32 @@ impl AbstractBlackBoxTestCase { // Then run through again and assert if any failed for x in 0..test_count { // for (int x = 0; x < testCount; x++) { - let testRXingResult = self.test_rxing_results.get(x).unwrap(); + let test_rxing_result = self.test_rxing_results.get(x).unwrap(); let label = format!( "Rotation {} degrees: Too many images failed", - testRXingResult.getRotation() + test_rxing_result.get_rotation() ); assert!( - passed_counts[x] >= testRXingResult.getMustPassCount() as usize, + passed_counts[x] >= test_rxing_result.get_must_pass_count() as usize, "{}", label ); assert!( - try_harder_counts[x] >= testRXingResult.getTryHarderCount() as usize, + try_harder_counts[x] >= test_rxing_result.get_try_harder_count() as usize, "Try harder, {}", label, ); let label = format!( "Rotation {} degrees: Too many images misread", - testRXingResult.getRotation() + test_rxing_result.get_rotation() ); assert!( - misread_counts[x] <= testRXingResult.getMaxMisreads() as usize, + misread_counts[x] <= test_rxing_result.get_max_misreads() as usize, "{}", label ); assert!( - try_harder_misread_counts[x] <= testRXingResult.getMaxTryHarderMisreads() as usize, + try_harder_misread_counts[x] <= test_rxing_result.get_max_try_harder_misreads() as usize, "Try harder, {}", label ); @@ -419,13 +419,13 @@ impl AbstractBlackBoxTestCase { // Try in 'pure' mode mostly to exercise PURE_BARCODE code paths for exceptions; // not expected to pass, generally - let mut result = None; + // let mut result = None; let mut pure_hints = HashMap::new(); pure_hints.insert( DecodeHintType::PURE_BARCODE, DecodeHintValue::PureBarcode(true), ); - result = if let Ok(res) = self.barcode_reader.decode_with_hints(source, &pure_hints) { + let mut result = if let Ok(res) = self.barcode_reader.decode_with_hints(source, &pure_hints) { Some(res) } else { None diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 33fae6d..c57a95b 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,5 +1,5 @@ -mod TestResult; +mod test_result; mod abstract_black_box_test_case; -pub use TestResult::*; +pub use test_result::*; pub use abstract_black_box_test_case::*; \ No newline at end of file diff --git a/tests/common/TestResult.rs b/tests/common/test_result.rs similarity index 85% rename from tests/common/TestResult.rs rename to tests/common/test_result.rs index f99dfd4..8787dc5 100644 --- a/tests/common/TestResult.rs +++ b/tests/common/test_result.rs @@ -42,23 +42,23 @@ impl TestRXingResult { } } - pub fn getMustPassCount(&self) -> u32 { + pub fn get_must_pass_count(&self) -> u32 { self.must_pass_count } - pub fn getTryHarderCount(&self) -> u32 { + pub fn get_try_harder_count(&self) -> u32 { self.try_harder_count } - pub fn getMaxMisreads(&self) -> u32 { + pub fn get_max_misreads(&self) -> u32 { self.max_misreads } - pub fn getMaxTryHarderMisreads(&self) -> u32 { + pub fn get_max_try_harder_misreads(&self) -> u32 { self.max_try_harder_misreads } - pub fn getRotation(&self) -> f32 { + pub fn get_rotation(&self) -> f32 { self.rotation } } diff --git a/tests/maxicode_blackbox_tests.rs b/tests/maxicode_blackbox_tests.rs index 15b2e95..54cfad4 100644 --- a/tests/maxicode_blackbox_tests.rs +++ b/tests/maxicode_blackbox_tests.rs @@ -29,9 +29,9 @@ fn maxicode1_test_case() { BarcodeFormat::MAXICODE, ); // super("src/test/resources/blackbox/maxicode-1", new MultiFormatReader(), BarcodeFormat.MAXICODE); - tester.addTest(6, 6, 0.0); + tester.add_test(6, 6, 0.0); - tester.testBlackBox(); + tester.test_black_box(); } /** @@ -48,12 +48,12 @@ fn maxi_code_black_box1_test_case() { BarcodeFormat::MAXICODE, ); // super("src/test/resources/blackbox/maxicode-1", new MultiFormatReader(), BarcodeFormat.MAXICODE); - tester.addHint( + tester.add_hint( DecodeHintType::PURE_BARCODE, rxing::DecodeHintValue::PureBarcode(true), ); - tester.addTest(1, 1, 0.0); + tester.add_test(1, 1, 0.0); - tester.testBlackBox(); + tester.test_black_box(); } diff --git a/tests/qr_code_blackbox_tests.rs b/tests/qr_code_blackbox_tests.rs index 66fb294..0cd602c 100644 --- a/tests/qr_code_blackbox_tests.rs +++ b/tests/qr_code_blackbox_tests.rs @@ -30,12 +30,12 @@ fn qrcode_black_box1_test_case() { rxing::BarcodeFormat::QR_CODE, ); // super("src/test/resources/blackbox/qrcode-1", new MultiFormatReader(), BarcodeFormat.QR_CODE); - tester.addTest(17, 17, 0.0); - tester.addTest(14, 14, 90.0); - tester.addTest(17, 17, 180.0); - tester.addTest(14, 14, 270.0); + tester.add_test(17, 17, 0.0); + tester.add_test(14, 14, 90.0); + tester.add_test(17, 17, 180.0); + tester.add_test(14, 14, 270.0); - tester.testBlackBox(); + tester.test_black_box(); } /** @@ -49,12 +49,12 @@ fn qrcode_black_box2_test_case() { QRCodeReader {}, BarcodeFormat::QR_CODE, ); - tester.addTest(31, 31, 0.0); - tester.addTest(30, 30, 90.0); - tester.addTest(30, 30, 180.0); - tester.addTest(30, 30, 270.0); + tester.add_test(31, 31, 0.0); + tester.add_test(30, 30, 90.0); + tester.add_test(30, 30, 180.0); + tester.add_test(30, 30, 270.0); - tester.testBlackBox(); + tester.test_black_box(); } /** @@ -68,12 +68,12 @@ fn qrcode_black_box3_test_case() { QRCodeReader {}, BarcodeFormat::QR_CODE, ); - tester.addTest(38, 38, 0.0); - tester.addTest(39, 39, 90.0); - tester.addTest(36, 36, 180.0); - tester.addTest(39, 39, 270.0); + tester.add_test(38, 38, 0.0); + tester.add_test(39, 39, 90.0); + tester.add_test(36, 36, 180.0); + tester.add_test(39, 39, 270.0); - tester.testBlackBox(); + tester.test_black_box(); } /** @@ -89,12 +89,12 @@ fn qrcode_black_box4_test_case() { QRCodeReader {}, BarcodeFormat::QR_CODE, ); - tester.addTest(36, 36, 0.0); - tester.addTest(35, 35, 90.0); - tester.addTest(35, 35, 180.0); - tester.addTest(35, 35, 270.0); + tester.add_test(36, 36, 0.0); + tester.add_test(35, 35, 90.0); + tester.add_test(35, 35, 180.0); + tester.add_test(35, 35, 270.0); - tester.testBlackBox(); + tester.test_black_box(); } /** @@ -112,12 +112,12 @@ fn qrcode_black_box5_test_case() { QRCodeReader {}, BarcodeFormat::QR_CODE, ); - tester.addTest(19, 19, 0.0); - tester.addTest(19, 19, 90.0); - tester.addTest(19, 19, 180.0); - tester.addTest(19, 19, 270.0); + tester.add_test(19, 19, 0.0); + tester.add_test(19, 19, 90.0); + tester.add_test(19, 19, 180.0); + tester.add_test(19, 19, 270.0); - tester.testBlackBox(); + tester.test_black_box(); } /** @@ -132,10 +132,10 @@ fn qrcode_black_box6_test_case() { QRCodeReader {}, BarcodeFormat::QR_CODE, ); - tester.addTest(15, 15, 0.0); - tester.addTest(14, 14, 90.0); - tester.addTest(13, 13, 180.0); - tester.addTest(14, 14, 270.0); + tester.add_test(15, 15, 0.0); + tester.add_test(14, 14, 90.0); + tester.add_test(13, 13, 180.0); + tester.add_test(14, 14, 270.0); - tester.testBlackBox(); + tester.test_black_box(); }