Skip to content

Commit

Permalink
fix: correct error related to GenericMultipleBarcodeReader
Browse files Browse the repository at this point in the history
This error occured in some cases during decode for an image with  many barcodes spread througout.
  • Loading branch information
hschimke committed Feb 2, 2024
1 parent 3c6c042 commit d73d92b
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
8 changes: 7 additions & 1 deletion src/binary_bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,13 @@ impl<B: Binarizer> BinaryBitmap<B> {
// 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()
}
Expand Down
14 changes: 8 additions & 6 deletions src/common/global_histogram_binarizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,16 @@ impl<LS: LuminanceSource> GlobalHistogramBinarizer<LS> {
}

// 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;
Expand Down
102 changes: 50 additions & 52 deletions src/multi/generic_multiple_barcode_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,60 @@ impl<T: Reader> MultipleBarcodeReader for GenericMultipleBarcodeReader<T> {
let mut results = Vec::new();
self.do_decode_multiple(image, hints, &mut results, 0, 0, 0);

if results.is_empty() {
let unique_results: Vec<RXingResult> = 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<T: Reader> GenericMultipleBarcodeReader<T> {
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 {
Expand All @@ -89,52 +135,11 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
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;
Expand Down Expand Up @@ -213,13 +218,6 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
.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(),
Expand Down
2 changes: 1 addition & 1 deletion src/rxing_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8>,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions tests/github_issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}

0 comments on commit d73d92b

Please sign in to comment.