diff --git a/Cargo.toml b/Cargo.toml index ddcce5a..1fca01d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rxing" -version = "0.5.5" +version = "0.5.6" description="A rust port of the zxing barcode library." license="Apache-2.0" repository="https://github.com/rxing-core/rxing" diff --git a/src/binary_bitmap.rs b/src/binary_bitmap.rs index f4882b6..d350bd7 100644 --- a/src/binary_bitmap.rs +++ b/src/binary_bitmap.rs @@ -113,7 +113,13 @@ impl BinaryBitmap { // 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. if self.matrix.is_none() { - self.matrix = Some(self.binarizer.get_black_matrix().unwrap().clone()) + self.matrix = Some(match self.binarizer.get_black_matrix() { + Ok(a) => a.clone(), + Err(_) => { + BitMatrix::new(self.get_width() as u32, self.get_height() as u32).unwrap() + } + }) + // self.binarizer.get_black_matrix().unwrap_or_else( |_| BitMatrix::new(self.get_width() as u32, self.get_height() as u32).unwrap()).clone()) } self.matrix.as_ref().unwrap() } diff --git a/src/common/global_histogram_binarizer.rs b/src/common/global_histogram_binarizer.rs index 9d2f2c6..842b1e7 100644 --- a/src/common/global_histogram_binarizer.rs +++ b/src/common/global_histogram_binarizer.rs @@ -227,14 +227,16 @@ impl GlobalHistogramBinarizer { } // Find a valley between them that is low and closer to the white peak. - let mut bestValley = secondPeak - 1; + let mut bestValley = secondPeak as isize - 1; let mut bestValleyScore = -1; - let mut x = secondPeak; - while x > firstPeak { + let mut x = secondPeak as isize; + while x > firstPeak as isize { // for (int x = secondPeak - 1; x > firstPeak; x--) { - let fromFirst = x - firstPeak; - let score = - fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]) as usize; + let fromFirst = x - firstPeak as isize; + let score = fromFirst + * fromFirst + * (secondPeak as isize - x) + * (maxBucketCount - buckets[x as usize]) as isize; if score as i32 > bestValleyScore { bestValley = x; bestValleyScore = score as i32; diff --git a/src/multi/generic_multiple_barcode_reader.rs b/src/multi/generic_multiple_barcode_reader.rs index f193f67..99bf6c5 100644 --- a/src/multi/generic_multiple_barcode_reader.rs +++ b/src/multi/generic_multiple_barcode_reader.rs @@ -57,14 +57,60 @@ impl MultipleBarcodeReader for GenericMultipleBarcodeReader { let mut results = Vec::new(); self.do_decode_multiple(image, hints, &mut results, 0, 0, 0); - if results.is_empty() { + let unique_results: Vec = results + .iter() + .enumerate() + .filter(|(i, r)| { + let already_found = if r.getPoints().len() >= 4 { + let q1 = Quadrilateral::new( + r.getPoints()[0], + r.getPoints()[1], + r.getPoints()[2], + r.getPoints()[3], + ); + results.iter().skip(*i + 1).any(|e| { + if e.getPoints().len() >= 4 { + let q2 = Quadrilateral::new( + e.getPoints()[0], + e.getPoints()[1], + e.getPoints()[2], + e.getPoints()[3], + ); + Quadrilateral::have_intersecting_bounding_boxes(&q1, &q2) + } else { + e.getPoints().iter().any(|p| q1.is_inside(*p)) + } + }) + } else { + results.iter().skip(*i + 1).any(|e| { + if e.getPoints().len() >= 4 { + let q2 = Quadrilateral::new( + e.getPoints()[0], + e.getPoints()[1], + e.getPoints()[2], + e.getPoints()[3], + ); + e.getPoints().iter().any(|p| q2.is_inside(*p)) + } else { + e.getText() == r.getText() + && e.getBarcodeFormat() == r.getBarcodeFormat() + } + }) + }; + !already_found + }) + .map(|(_, r)| r) + .cloned() + .collect(); + + if unique_results.is_empty() { return Err(Exceptions::NOT_FOUND); } - Ok(results) + Ok(unique_results) } } impl GenericMultipleBarcodeReader { - const MIN_DIMENSION_TO_RECUR: f32 = 10.0; + const MIN_DIMENSION_TO_RECUR: f32 = 100.0; const MAX_DEPTH: u32 = 4; pub fn new(delegate: T) -> Self { @@ -89,52 +135,11 @@ impl GenericMultipleBarcodeReader { return; }; - // let alreadyFound = results.iter().any(|r| r.getText() == result.getText() && r.getBarcodeFormat() == result.getBarcodeFormat()); - let resultPoints = result.getPoints().clone(); let possible_new_result = Self::translatePoints(result, xOffset, yOffset); - let already_found = if possible_new_result.getPoints().len() >= 4 { - let q1 = Quadrilateral::new( - possible_new_result.getPoints()[0], - possible_new_result.getPoints()[1], - possible_new_result.getPoints()[2], - possible_new_result.getPoints()[3], - ); - results.iter().any(|e| { - if e.getPoints().len() >= 4 { - let q2 = Quadrilateral::new( - e.getPoints()[0], - e.getPoints()[1], - e.getPoints()[2], - e.getPoints()[3], - ); - Quadrilateral::have_intersecting_bounding_boxes(&q1, &q2) - } else { - e.getPoints().iter().any(|p| q1.is_inside(*p)) - } - }) - } else { - results.iter().any(|e| { - if e.getPoints().len() >= 4 { - let q2 = Quadrilateral::new( - e.getPoints()[0], - e.getPoints()[1], - e.getPoints()[2], - e.getPoints()[3], - ); - e.getPoints().iter().any(|p| q2.is_inside(*p)) - } else { - e.getText() == possible_new_result.getText() - && e.getBarcodeFormat() == possible_new_result.getBarcodeFormat() - } - }) - }; - - if !already_found { - results.push(possible_new_result); - } + results.push(possible_new_result); if resultPoints.is_empty() { return; @@ -213,13 +218,6 @@ impl GenericMultipleBarcodeReader { .map(|oldPoint| point_f(oldPoint.x + xOffset as f32, oldPoint.y + yOffset as f32)) .collect(); - // let mut newPoints = Vec::with_capacity(oldPoints.len()); - // for oldPoint in oldPoints { - // newPoints.push(point( - // oldPoint.getX() + xOffset as f32, - // oldPoint.getY() + yOffset as f32, - // )); - // } let mut newRXingResult = RXingResult::new_complex( result.getText(), result.getRawBytes().clone(), diff --git a/src/rxing_result.rs b/src/rxing_result.rs index f888935..9e2337f 100644 --- a/src/rxing_result.rs +++ b/src/rxing_result.rs @@ -30,7 +30,7 @@ use serde::{Deserialize, Serialize}; * @author Sean Owen */ #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct RXingResult { text: String, rawBytes: Vec, diff --git a/test_resources/blackbox/multi-1/AllSupportedBarcodeTypes.png b/test_resources/blackbox/multi-1/AllSupportedBarcodeTypes.png new file mode 100644 index 0000000..a0a6817 Binary files /dev/null and b/test_resources/blackbox/multi-1/AllSupportedBarcodeTypes.png differ diff --git a/tests/github_issues.rs b/tests/github_issues.rs index 164a550..212fcc3 100644 --- a/tests/github_issues.rs +++ b/tests/github_issues.rs @@ -23,3 +23,27 @@ fn issue_28() { ); rxing::helpers::detect_multiple_in_file_with_hints("test_resources/blackbox/github_issue_cases/226611447-be6041dc-5b21-42fe-827b-068ccc59082c.png", &mut hints).unwrap_or_default(); } + +#[cfg(feature = "image")] +#[test] +fn dynamsoft_all_supported_formats_image_fault() { + use rxing::DecodingHintDictionary; + + let mut hints: DecodingHintDictionary = DecodingHintDictionary::new(); + hints.insert( + rxing::DecodeHintType::TRY_HARDER, + rxing::DecodeHintValue::TryHarder(true), + ); + let results = rxing::helpers::detect_multiple_in_file_with_hints( + "test_resources/blackbox/multi-1/AllSupportedBarcodeTypes.png", + &mut hints, + ) + .expect("must not fault during read"); + + assert!( + results.len() >= 11, + "regression detection, base count of 11 codes" + ); + + // ToDo: This test is incomplete. Some that should be detected aren't, and some that are detected shouldn't be. +}