mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
Merge branch 'main' into dx_film_edge_read_support
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rxing"
|
||||
version = "0.5.5"
|
||||
version = "0.5.7"
|
||||
description="A rust port of the zxing barcode library."
|
||||
license="Apache-2.0"
|
||||
repository="https://github.com/rxing-core/rxing"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rxing-cli"
|
||||
version = "0.1.19"
|
||||
version = "0.1.20"
|
||||
edition = "2021"
|
||||
description = "A command line interface for rxing supporting encoding and decoding of multiple barcode formats"
|
||||
license="Apache-2.0"
|
||||
@@ -11,4 +11,4 @@ keywords = ["barcode", "2d_barcode", "1d_barcode", "barcode_reader", "barcode_wr
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.4.13", features = ["derive"] }
|
||||
rxing = {path = "../../", version = "~0.5.5", features = ["image", "svg_read", "svg_write"] }
|
||||
rxing = {path = "../../", version = "~0.5.7", features = ["image", "svg_read", "svg_write"] }
|
||||
|
||||
@@ -118,7 +118,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()
|
||||
}
|
||||
|
||||
@@ -55,30 +55,8 @@ impl BufferedImageLuminanceSource {
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Self {
|
||||
let img = image.to_rgba8();
|
||||
|
||||
let mut raster: ImageBuffer<_, Vec<_>> = ImageBuffer::new(image.width(), image.height());
|
||||
|
||||
for (x, y, new_pixel) in raster.enumerate_pixels_mut() {
|
||||
let pixel = img.get_pixel(x, y);
|
||||
let [red, green, blue, alpha] = pixel.0;
|
||||
if alpha == 0 {
|
||||
// white, so we know its luminance is 255
|
||||
*new_pixel = Luma([0xFF])
|
||||
} else {
|
||||
// .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),
|
||||
// (306*R) >> 10 is approximately equal to R*0.299, and so on.
|
||||
// 0x200 >> 10 is 0.5, it implements rounding.
|
||||
*new_pixel = Luma([((306 * (red as u64)
|
||||
+ 601 * (green as u64)
|
||||
+ 117 * (blue as u64)
|
||||
+ 0x200)
|
||||
>> 10) as u8])
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
image: Rc::new(DynamicImage::from(raster)),
|
||||
image: Rc::new(build_local_grey_image(image)),
|
||||
width,
|
||||
height,
|
||||
left,
|
||||
@@ -233,3 +211,87 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
self.image.get_pixel(x as u32, y as u32).to_luma().0[0]
|
||||
}
|
||||
}
|
||||
|
||||
fn build_local_grey_image(source: DynamicImage) -> DynamicImage {
|
||||
let raster = match source {
|
||||
DynamicImage::ImageLuma8(img) => img,
|
||||
DynamicImage::ImageLumaA8(img) => {
|
||||
let mut raster: ImageBuffer<_, Vec<_>> = ImageBuffer::new(img.width(), img.height());
|
||||
|
||||
for (x, y, new_pixel) in raster.enumerate_pixels_mut() {
|
||||
let pixel = img.get_pixel(x, y);
|
||||
let [luma, alpha] = pixel.0;
|
||||
if alpha == 0 {
|
||||
// white, so we know its luminance is 255
|
||||
*new_pixel = Luma([0xFF])
|
||||
} else {
|
||||
*new_pixel = Luma([luma.saturating_mul(alpha)])
|
||||
}
|
||||
}
|
||||
|
||||
raster
|
||||
}
|
||||
// DynamicImage::ImageRgb8(_) => todo!(),
|
||||
// DynamicImage::ImageRgba8(_) => todo!(),
|
||||
DynamicImage::ImageLuma16(img) => {
|
||||
let mut raster: ImageBuffer<_, Vec<_>> = ImageBuffer::new(img.width(), img.height());
|
||||
|
||||
for (x, y, new_pixel) in raster.enumerate_pixels_mut() {
|
||||
let pixel = img.get_pixel(x, y);
|
||||
let [luma] = pixel.0;
|
||||
|
||||
*new_pixel = Luma([(luma / u8::max_value() as u16) as u8])
|
||||
}
|
||||
|
||||
raster
|
||||
}
|
||||
DynamicImage::ImageLumaA16(img) => {
|
||||
let mut raster: ImageBuffer<_, Vec<_>> = ImageBuffer::new(img.width(), img.height());
|
||||
|
||||
for (x, y, new_pixel) in raster.enumerate_pixels_mut() {
|
||||
let pixel = img.get_pixel(x, y);
|
||||
let [luma, alpha] = pixel.0;
|
||||
if alpha == 0 {
|
||||
// white, so we know its luminance is 255
|
||||
*new_pixel = Luma([0xFF])
|
||||
} else {
|
||||
*new_pixel =
|
||||
Luma([((luma.saturating_mul(alpha)) / u8::max_value() as u16) as u8])
|
||||
}
|
||||
}
|
||||
|
||||
raster
|
||||
}
|
||||
// DynamicImage::ImageRgb16(_) => todo!(),
|
||||
// DynamicImage::ImageRgba16(_) => todo!(),
|
||||
// DynamicImage::ImageRgb32F(_) => todo!(),
|
||||
// DynamicImage::ImageRgba32F(_) => todo!(),
|
||||
_ => {
|
||||
let img = source.to_rgba8();
|
||||
|
||||
let mut raster: ImageBuffer<_, Vec<_>> =
|
||||
ImageBuffer::new(source.width(), source.height());
|
||||
|
||||
for (x, y, new_pixel) in raster.enumerate_pixels_mut() {
|
||||
let pixel = img.get_pixel(x, y);
|
||||
let [red, green, blue, alpha] = pixel.0;
|
||||
if alpha == 0 {
|
||||
// white, so we know its luminance is 255
|
||||
*new_pixel = Luma([0xFF])
|
||||
} else {
|
||||
// .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),
|
||||
// (306*R) >> 10 is approximately equal to R*0.299, and so on.
|
||||
// 0x200 >> 10 is 0.5, it implements rounding.
|
||||
*new_pixel = Luma([((306 * (red as u64)
|
||||
+ 601 * (green as u64)
|
||||
+ 117 * (blue as u64)
|
||||
+ 0x200)
|
||||
>> 10) as u8])
|
||||
}
|
||||
}
|
||||
raster
|
||||
}
|
||||
};
|
||||
|
||||
DynamicImage::from(raster)
|
||||
}
|
||||
|
||||
@@ -280,14 +280,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;
|
||||
|
||||
@@ -92,7 +92,7 @@ impl LuminanceSource for Luma8LuminanceSource {
|
||||
fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> Result<Self> {
|
||||
Ok(Self {
|
||||
dimensions: (width as u32, height as u32),
|
||||
origin: (left as u32, top as u32),
|
||||
origin: (self.origin.0 + left as u32, self.origin.1 + top as u32),
|
||||
data: self.data.clone(),
|
||||
inverted: self.inverted,
|
||||
original_dimension: self.original_dimension,
|
||||
@@ -257,13 +257,3 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// fn print_matrix(matrix: &[u8], width: usize, height: usize) {
|
||||
// for y in 0..height {
|
||||
// for x in 0..width {
|
||||
// print!("{}, ",matrix[y*width + x ]);
|
||||
// }
|
||||
// println!()
|
||||
// }
|
||||
// println!()
|
||||
// }
|
||||
|
||||
@@ -57,15 +57,61 @@ 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 = 2.0;
|
||||
const MAX_DEPTH: u32 = 8;
|
||||
const MIN_DIMENSION_TO_RECUR: f32 = 100.0;
|
||||
const MAX_DEPTH: u32 = 4;
|
||||
|
||||
pub fn new(delegate: T) -> Self {
|
||||
Self(delegate)
|
||||
@@ -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;
|
||||
@@ -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(),
|
||||
|
||||
@@ -30,7 +30,7 @@ use serde::{Deserialize, Serialize};
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RXingResult {
|
||||
text: String,
|
||||
rawBytes: Vec<u8>,
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
test_resources/blackbox/multi-1/AllSupportedBarcodeTypes.png
Normal file
BIN
test_resources/blackbox/multi-1/AllSupportedBarcodeTypes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 335 KiB |
@@ -211,7 +211,7 @@ fn cpp_qrcode_black_box2_test_case() {
|
||||
|
||||
tester.add_test(46, 48, 0.0);
|
||||
tester.add_test(46, 48, 90.0);
|
||||
tester.add_test(46, 48, 180.0);
|
||||
tester.add_test(46, 47, 180.0);
|
||||
tester.add_test(46, 48, 270.0);
|
||||
|
||||
tester.ignore_pure = true;
|
||||
@@ -322,7 +322,6 @@ fn cpp_qrcode_black_box7_test_case() {
|
||||
rxing::BarcodeFormat::QR_CODE,
|
||||
);
|
||||
|
||||
// super("src/test/resources/blackbox/pdf417-4", null, BarcodeFormat.PDF_417);
|
||||
tester.add_test_complex(1, 1, 0, 0, 0.0);
|
||||
|
||||
tester.test_black_box();
|
||||
|
||||
@@ -23,3 +23,330 @@ 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.
|
||||
}
|
||||
|
||||
#[cfg(feature = "image")]
|
||||
#[test]
|
||||
fn zxing_bench_issue_1() {
|
||||
use rxing::{BarcodeFormat, 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/github_issue_cases/170050507-1f10f0ef-82ca-4e14-a2d2-4b288ec54809.png",
|
||||
&mut hints,
|
||||
)
|
||||
.expect("must not fault during read");
|
||||
|
||||
assert_eq!(
|
||||
results.len(),
|
||||
9,
|
||||
"must detect 9 barcodes, found: {}",
|
||||
results.len()
|
||||
);
|
||||
|
||||
assert_eq!(results[0].getText(), "CODE39");
|
||||
assert_eq!(results[0].getBarcodeFormat(), &BarcodeFormat::CODE_39);
|
||||
|
||||
assert_eq!(results[1].getText(), "012345");
|
||||
assert_eq!(results[1].getBarcodeFormat(), &BarcodeFormat::CODABAR);
|
||||
|
||||
assert_eq!(results[2].getText(), "CODE128");
|
||||
assert_eq!(results[2].getBarcodeFormat(), &BarcodeFormat::CODE_128);
|
||||
|
||||
assert_eq!(results[3].getText(), "00123456");
|
||||
assert_eq!(results[3].getBarcodeFormat(), &BarcodeFormat::ITF);
|
||||
|
||||
assert_eq!(results[4].getText(), "CODE93");
|
||||
assert_eq!(results[4].getBarcodeFormat(), &BarcodeFormat::CODE_93);
|
||||
|
||||
assert_eq!(results[5].getText(), "012345678905");
|
||||
assert_eq!(results[5].getBarcodeFormat(), &BarcodeFormat::UPC_A);
|
||||
|
||||
assert_eq!(results[6].getText(), "01234565");
|
||||
assert_eq!(results[6].getBarcodeFormat(), &BarcodeFormat::EAN_8);
|
||||
|
||||
assert_eq!(results[7].getText(), "01234565");
|
||||
assert_eq!(results[7].getBarcodeFormat(), &BarcodeFormat::UPC_E);
|
||||
|
||||
assert_eq!(results[8].getText(), "1234567890128");
|
||||
assert_eq!(results[8].getBarcodeFormat(), &BarcodeFormat::EAN_13);
|
||||
|
||||
/*
|
||||
Found 9 results
|
||||
Result 0:
|
||||
(code 39) CODE39
|
||||
Result 1:
|
||||
(codabar) 012345
|
||||
Result 2:
|
||||
(code 128) CODE128
|
||||
Result 3:
|
||||
(itf) 00123456
|
||||
Result 4:
|
||||
(code 93) CODE93
|
||||
Result 5:
|
||||
(upc a) 012345678905
|
||||
Result 6:
|
||||
(ean 8) 01234565
|
||||
Result 7:
|
||||
(upc e) 01234565
|
||||
Result 8:
|
||||
(ean 13) 1234567890128
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
#[cfg(feature = "image")]
|
||||
#[test]
|
||||
fn issue_48() {
|
||||
use rxing::{BarcodeFormat, 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/github_issue_cases/300908088-2b3ffe34-1067-48c9-8663-f841b5d0acf6.png",
|
||||
&mut hints,
|
||||
)
|
||||
.expect("must not fault during read");
|
||||
|
||||
/*
|
||||
Found 3 results
|
||||
Result 0:
|
||||
(datamatrix) This is a Data Matrix by TEC-IT
|
||||
Result 1:
|
||||
(datamatrix) This is a Data Matrix by TEC-IT
|
||||
Result 2:
|
||||
(datamatrix) Hello world
|
||||
*/
|
||||
|
||||
assert_eq!(
|
||||
results.len(),
|
||||
3,
|
||||
"must detect 3 barcodes, found: {}",
|
||||
results.len()
|
||||
);
|
||||
|
||||
assert_eq!(results[0].getText(), "This is a Data Matrix by TEC-IT");
|
||||
assert_eq!(results[0].getBarcodeFormat(), &BarcodeFormat::DATA_MATRIX);
|
||||
|
||||
assert_eq!(results[1].getText(), "This is a Data Matrix by TEC-IT");
|
||||
assert_eq!(results[1].getBarcodeFormat(), &BarcodeFormat::DATA_MATRIX);
|
||||
|
||||
assert_eq!(results[2].getText(), "Hello world");
|
||||
assert_eq!(results[2].getBarcodeFormat(), &BarcodeFormat::DATA_MATRIX);
|
||||
}
|
||||
|
||||
#[cfg(feature = "image")]
|
||||
#[test]
|
||||
fn zxing_bench_grey_image_issue_luma8_image() {
|
||||
use image::DynamicImage;
|
||||
use rxing::{
|
||||
common::HybridBinarizer,
|
||||
multi::{GenericMultipleBarcodeReader, MultipleBarcodeReader},
|
||||
BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource, DecodeHintType, DecodeHintValue,
|
||||
DecodingHintDictionary, Exceptions, MultiUseMultiFormatReader,
|
||||
};
|
||||
|
||||
const FILE_NAME : &str = "test_resources/blackbox/github_issue_cases/170050507-1f10f0ef-82ca-4e14-a2d2-4b288ec54809.png";
|
||||
|
||||
let mut hints = DecodingHintDictionary::default();
|
||||
|
||||
let img = DynamicImage::from(
|
||||
image::open(FILE_NAME)
|
||||
.map_err(|e| Exceptions::runtime_with(format!("couldn't read {FILE_NAME}: {e}")))
|
||||
.unwrap()
|
||||
.to_luma8(),
|
||||
);
|
||||
let multi_format_reader = MultiUseMultiFormatReader::default();
|
||||
let mut scanner = GenericMultipleBarcodeReader::new(multi_format_reader);
|
||||
|
||||
hints
|
||||
.entry(DecodeHintType::TRY_HARDER)
|
||||
.or_insert(DecodeHintValue::TryHarder(true));
|
||||
|
||||
let results = scanner
|
||||
.decode_multiple_with_hints(
|
||||
&mut BinaryBitmap::new(HybridBinarizer::new(BufferedImageLuminanceSource::new(img))),
|
||||
&hints,
|
||||
)
|
||||
.expect("must not fault during read");
|
||||
|
||||
assert_eq!(
|
||||
results.len(),
|
||||
9,
|
||||
"must detect 9 barcodes, found: {}",
|
||||
results.len()
|
||||
);
|
||||
|
||||
assert_eq!(results[0].getText(), "CODE39");
|
||||
assert_eq!(results[0].getBarcodeFormat(), &BarcodeFormat::CODE_39);
|
||||
|
||||
assert_eq!(results[1].getText(), "012345");
|
||||
assert_eq!(results[1].getBarcodeFormat(), &BarcodeFormat::CODABAR);
|
||||
|
||||
assert_eq!(results[2].getText(), "CODE128");
|
||||
assert_eq!(results[2].getBarcodeFormat(), &BarcodeFormat::CODE_128);
|
||||
|
||||
assert_eq!(results[3].getText(), "00123456");
|
||||
assert_eq!(results[3].getBarcodeFormat(), &BarcodeFormat::ITF);
|
||||
|
||||
assert_eq!(results[4].getText(), "CODE93");
|
||||
assert_eq!(results[4].getBarcodeFormat(), &BarcodeFormat::CODE_93);
|
||||
|
||||
assert_eq!(results[5].getText(), "012345678905");
|
||||
assert_eq!(results[5].getBarcodeFormat(), &BarcodeFormat::UPC_A);
|
||||
|
||||
assert_eq!(results[6].getText(), "01234565");
|
||||
assert_eq!(results[6].getBarcodeFormat(), &BarcodeFormat::EAN_8);
|
||||
|
||||
assert_eq!(results[7].getText(), "01234565");
|
||||
assert_eq!(results[7].getBarcodeFormat(), &BarcodeFormat::UPC_E);
|
||||
|
||||
assert_eq!(results[8].getText(), "1234567890128");
|
||||
assert_eq!(results[8].getBarcodeFormat(), &BarcodeFormat::EAN_13);
|
||||
|
||||
/*
|
||||
Found 9 results
|
||||
Result 0:
|
||||
(code 39) CODE39
|
||||
Result 1:
|
||||
(codabar) 012345
|
||||
Result 2:
|
||||
(code 128) CODE128
|
||||
Result 3:
|
||||
(itf) 00123456
|
||||
Result 4:
|
||||
(code 93) CODE93
|
||||
Result 5:
|
||||
(upc a) 012345678905
|
||||
Result 6:
|
||||
(ean 8) 01234565
|
||||
Result 7:
|
||||
(upc e) 01234565
|
||||
Result 8:
|
||||
(ean 13) 1234567890128
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
#[cfg(feature = "image")]
|
||||
#[test]
|
||||
fn zxing_bench_grey_image_issue_raw_luma8() {
|
||||
use rxing::{
|
||||
common::HybridBinarizer,
|
||||
multi::{GenericMultipleBarcodeReader, MultipleBarcodeReader},
|
||||
BarcodeFormat, BinaryBitmap, DecodeHintType, DecodeHintValue, DecodingHintDictionary,
|
||||
Exceptions, Luma8LuminanceSource, MultiUseMultiFormatReader,
|
||||
};
|
||||
|
||||
const FILE_NAME : &str = "test_resources/blackbox/github_issue_cases/170050507-1f10f0ef-82ca-4e14-a2d2-4b288ec54809.png";
|
||||
|
||||
let mut hints = DecodingHintDictionary::default();
|
||||
|
||||
let img = image::open(FILE_NAME)
|
||||
.map_err(|e| Exceptions::runtime_with(format!("couldn't read {FILE_NAME}: {e}")))
|
||||
.unwrap();
|
||||
let multi_format_reader = MultiUseMultiFormatReader::default();
|
||||
let mut scanner = GenericMultipleBarcodeReader::new(multi_format_reader);
|
||||
|
||||
hints
|
||||
.entry(DecodeHintType::TRY_HARDER)
|
||||
.or_insert(DecodeHintValue::TryHarder(true));
|
||||
|
||||
let results = scanner
|
||||
.decode_multiple_with_hints(
|
||||
&mut BinaryBitmap::new(HybridBinarizer::new(Luma8LuminanceSource::new(
|
||||
img.to_luma8().into_raw(),
|
||||
img.width(),
|
||||
img.height(),
|
||||
))),
|
||||
&hints,
|
||||
)
|
||||
.expect("must not fault during read");
|
||||
|
||||
assert_eq!(
|
||||
results.len(),
|
||||
9,
|
||||
"must detect 9 barcodes, found: {}",
|
||||
results.len()
|
||||
);
|
||||
|
||||
assert_eq!(results[0].getText(), "CODE39");
|
||||
assert_eq!(results[0].getBarcodeFormat(), &BarcodeFormat::CODE_39);
|
||||
|
||||
assert_eq!(results[1].getText(), "012345");
|
||||
assert_eq!(results[1].getBarcodeFormat(), &BarcodeFormat::CODABAR);
|
||||
|
||||
assert_eq!(results[2].getText(), "CODE128");
|
||||
assert_eq!(results[2].getBarcodeFormat(), &BarcodeFormat::CODE_128);
|
||||
|
||||
assert_eq!(results[3].getText(), "00123456");
|
||||
assert_eq!(results[3].getBarcodeFormat(), &BarcodeFormat::ITF);
|
||||
|
||||
assert_eq!(results[4].getText(), "CODE93");
|
||||
assert_eq!(results[4].getBarcodeFormat(), &BarcodeFormat::CODE_93);
|
||||
|
||||
assert_eq!(results[5].getText(), "012345678905");
|
||||
assert_eq!(results[5].getBarcodeFormat(), &BarcodeFormat::UPC_A);
|
||||
|
||||
assert_eq!(results[6].getText(), "01234565");
|
||||
assert_eq!(results[6].getBarcodeFormat(), &BarcodeFormat::EAN_8);
|
||||
|
||||
assert_eq!(results[7].getText(), "01234565");
|
||||
assert_eq!(results[7].getBarcodeFormat(), &BarcodeFormat::UPC_E);
|
||||
|
||||
assert_eq!(results[8].getText(), "1234567890128");
|
||||
assert_eq!(results[8].getBarcodeFormat(), &BarcodeFormat::EAN_13);
|
||||
|
||||
/*
|
||||
Found 9 results
|
||||
Result 0:
|
||||
(code 39) CODE39
|
||||
Result 1:
|
||||
(codabar) 012345
|
||||
Result 2:
|
||||
(code 128) CODE128
|
||||
Result 3:
|
||||
(itf) 00123456
|
||||
Result 4:
|
||||
(code 93) CODE93
|
||||
Result 5:
|
||||
(upc a) 012345678905
|
||||
Result 6:
|
||||
(ean 8) 01234565
|
||||
Result 7:
|
||||
(upc e) 01234565
|
||||
Result 8:
|
||||
(ean 13) 1234567890128
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user