mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
update for shared state and improved performance
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rxing"
|
name = "rxing"
|
||||||
version = "0.1.4"
|
version = "0.2.0"
|
||||||
description="A rust port of the zxing barcode library."
|
description="A rust port of the zxing barcode library."
|
||||||
license="Apache-2.0"
|
license="Apache-2.0"
|
||||||
repository="https://github.com/hschimke/rxing"
|
repository="https://github.com/hschimke/rxing"
|
||||||
@@ -26,7 +26,8 @@ image = {version = "0.24", optional = true}
|
|||||||
imageproc = {version = "0.23.0", optional = true}
|
imageproc = {version = "0.23.0", optional = true}
|
||||||
unicode-segmentation = "1.10.0"
|
unicode-segmentation = "1.10.0"
|
||||||
codepage-437 = "0.1.0"
|
codepage-437 = "0.1.0"
|
||||||
rxing-one-d-proc-derive = "0.1"
|
#rxing-one-d-proc-derive = "0.1"
|
||||||
|
rxing-one-d-proc-derive = {path ="../rxing-one-d-proc-derive"}
|
||||||
num = "0.4.0"
|
num = "0.4.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -34,7 +34,7 @@ used to enable the use of the `image` crate is currently on by default. Turning
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```
|
```
|
||||||
use std::{collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use rxing::multi::MultipleBarcodeReader;
|
use rxing::multi::MultipleBarcodeReader;
|
||||||
|
|
||||||
@@ -46,21 +46,38 @@ fn main() {
|
|||||||
let file_name = "test_image.jpeg";
|
let file_name = "test_image.jpeg";
|
||||||
|
|
||||||
let img = image::open(file_name).unwrap();
|
let img = image::open(file_name).unwrap();
|
||||||
|
// let img = img.resize(768, 1024, image::imageops::FilterType::Gaussian);
|
||||||
|
|
||||||
|
let mut hints: rxing::DecodingHintDictionary = HashMap::new();
|
||||||
|
hints.insert(
|
||||||
|
rxing::DecodeHintType::TRY_HARDER,
|
||||||
|
rxing::DecodeHintValue::TryHarder(true),
|
||||||
|
);
|
||||||
|
|
||||||
let multi_format_reader = rxing::MultiFormatReader::default();
|
let multi_format_reader = rxing::MultiFormatReader::default();
|
||||||
let mut scanner = rxing::multi::GenericMultipleBarcodeReader::new(multi_format_reader);
|
let mut scanner = rxing::multi::GenericMultipleBarcodeReader::new(multi_format_reader);
|
||||||
let results = scanner.decode_multiple_with_hints(
|
let results = scanner
|
||||||
&rxing::BinaryBitmap::new(Rc::new(rxing::common::HybridBinarizer::new(Box::new(
|
.decode_multiple_with_hints(
|
||||||
|
&mut rxing::BinaryBitmap::new(Rc::new(RefCell::new(
|
||||||
|
rxing::common::HybridBinarizer::new(Box::new(
|
||||||
rxing::BufferedImageLuminanceSource::new(img),
|
rxing::BufferedImageLuminanceSource::new(img),
|
||||||
)))),
|
)),
|
||||||
&HashMap::new(),
|
))),
|
||||||
).expect("decodes");
|
&hints,
|
||||||
|
)
|
||||||
|
.expect("decodes");
|
||||||
|
|
||||||
for result in results {
|
for result in results {
|
||||||
println!("{} -> {}",result.getBarcodeFormat(), result.getText())
|
println!("{} -> {}", result.getBarcodeFormat(), result.getText())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Latest Release Notes
|
## Latest Release Notes
|
||||||
|
v0.2.0 -> Dramatically improve performance when cropping a BufferedImageLuminanceSource.
|
||||||
|
|
||||||
v0.1.4 -> Dramatically improve performance for MultiFormatReader and for multiple barcode detection.
|
v0.1.4 -> Dramatically improve performance for MultiFormatReader and for multiple barcode detection.
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
Performance is low for GenericMultipleBarcodeReader.
|
||||||
@@ -55,7 +55,7 @@ fn test_no_crop() {
|
|||||||
assert_equals(&Y, 0, &source.getMatrix(), 0, Y.len());
|
assert_equals(&Y, 0, &source.getMatrix(), 0, Y.len());
|
||||||
for r in 0..ROWS {
|
for r in 0..ROWS {
|
||||||
// for (int r = 0; r < ROWS; r++) {
|
// for (int r = 0; r < ROWS; r++) {
|
||||||
assert_equals(&Y, r * COLS, &source.getRow(r, &vec![0; 0]), 0, COLS);
|
assert_equals(&Y, r * COLS, &source.getRow(r), 0, COLS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,13 +87,7 @@ fn test_crop() {
|
|||||||
}
|
}
|
||||||
for r in 0..ROWS - 2 {
|
for r in 0..ROWS - 2 {
|
||||||
// for (int r = 0; r < ROWS - 2; r++) {
|
// for (int r = 0; r < ROWS - 2; r++) {
|
||||||
assert_equals(
|
assert_equals(&Y, (r + 1) * COLS + 1, &source.getRow(r), 0, COLS - 2);
|
||||||
&Y,
|
|
||||||
(r + 1) * COLS + 1,
|
|
||||||
&source.getRow(r, &vec![0; 0]),
|
|
||||||
0,
|
|
||||||
COLS - 2,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ fn testCrop() {
|
|||||||
let cropped = SOURCE.crop(1, 1, 1, 1).unwrap();
|
let cropped = SOURCE.crop(1, 1, 1, 1).unwrap();
|
||||||
assert_eq!(1, cropped.getHeight());
|
assert_eq!(1, cropped.getHeight());
|
||||||
assert_eq!(1, cropped.getWidth());
|
assert_eq!(1, cropped.getWidth());
|
||||||
assert_eq!(vec![0x7F], cropped.getRow(0, &vec![0; 0]));
|
assert_eq!(vec![0x7F], cropped.getRow(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -62,7 +62,7 @@ fn testMatrix() {
|
|||||||
fn testGetRow() {
|
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]));
|
assert_eq!(vec![0x3F, 0x7F, 0x3F], SOURCE.getRow(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ impl Reader for AztecReader {
|
|||||||
* @throws NotFoundException if a Data Matrix code cannot be found
|
* @throws NotFoundException if a Data Matrix code cannot be found
|
||||||
* @throws FormatException if a Data Matrix code cannot be decoded
|
* @throws FormatException if a Data Matrix code cannot be decoded
|
||||||
*/
|
*/
|
||||||
fn decode(&mut self, image: &BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
fn decode(&mut self, image: &mut BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &BinaryBitmap,
|
image: &mut BinaryBitmap,
|
||||||
hints: &HashMap<DecodeHintType, DecodeHintValue>,
|
hints: &HashMap<DecodeHintType, DecodeHintValue>,
|
||||||
) -> Result<RXingResult, Exceptions> {
|
) -> Result<RXingResult, Exceptions> {
|
||||||
// let notFoundException = None;
|
// let notFoundException = None;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//package com.google.zxing;
|
//package com.google.zxing;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitArray, BitMatrix},
|
common::{BitArray, BitMatrix},
|
||||||
@@ -51,7 +51,7 @@ pub trait Binarizer {
|
|||||||
* @return The array of bits for this row (true means black).
|
* @return The array of bits for this row (true means black).
|
||||||
* @throws NotFoundException if row can't be binarized
|
* @throws NotFoundException if row can't be binarized
|
||||||
*/
|
*/
|
||||||
fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions>;
|
fn getBlackRow(&mut self, y: usize) -> Result<BitArray, Exceptions>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive
|
* Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive
|
||||||
@@ -62,7 +62,7 @@ pub trait Binarizer {
|
|||||||
* @return The 2D array of bits for the image (true means black).
|
* @return The 2D array of bits for the image (true means black).
|
||||||
* @throws NotFoundException if image can't be binarized to make a matrix
|
* @throws NotFoundException if image can't be binarized to make a matrix
|
||||||
*/
|
*/
|
||||||
fn getBlackMatrix(&self) -> Result<BitMatrix, Exceptions>;
|
fn getBlackMatrix(&mut self) -> Result<&BitMatrix, Exceptions>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new object with the same type as this Binarizer implementation, but with pristine
|
* Creates a new object with the same type as this Binarizer implementation, but with pristine
|
||||||
@@ -72,7 +72,7 @@ pub trait Binarizer {
|
|||||||
* @param source The LuminanceSource this Binarizer will operate on.
|
* @param source The LuminanceSource this Binarizer will operate on.
|
||||||
* @return A new concrete Binarizer implementation object.
|
* @return A new concrete Binarizer implementation object.
|
||||||
*/
|
*/
|
||||||
fn createBinarizer(&self, source: Box<dyn LuminanceSource>) -> Rc<dyn Binarizer>;
|
fn createBinarizer(&self, source: Box<dyn LuminanceSource>) -> Rc<RefCell<dyn Binarizer>>;
|
||||||
|
|
||||||
fn getWidth(&self) -> usize;
|
fn getWidth(&self) -> usize;
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//package com.google.zxing;
|
//package com.google.zxing;
|
||||||
|
|
||||||
use std::{fmt, rc::Rc};
|
use std::{cell::RefCell, fmt, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitArray, BitMatrix},
|
common::{BitArray, BitMatrix},
|
||||||
@@ -29,16 +29,16 @@ use crate::{
|
|||||||
*
|
*
|
||||||
* @author dswitkin@google.com (Daniel Switkin)
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
*/
|
*/
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct BinaryBitmap {
|
pub struct BinaryBitmap {
|
||||||
binarizer: Rc<dyn Binarizer>,
|
binarizer: Rc<RefCell<dyn Binarizer>>,
|
||||||
matrix: BitMatrix,
|
matrix: Option<BitMatrix>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryBitmap {
|
impl BinaryBitmap {
|
||||||
pub fn new(binarizer: Rc<dyn Binarizer>) -> Self {
|
pub fn new(binarizer: Rc<RefCell<dyn Binarizer>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
matrix: binarizer.getBlackMatrix().unwrap(),
|
matrix: None,
|
||||||
binarizer: binarizer,
|
binarizer: binarizer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,14 +47,14 @@ impl BinaryBitmap {
|
|||||||
* @return The width of the bitmap.
|
* @return The width of the bitmap.
|
||||||
*/
|
*/
|
||||||
pub fn getWidth(&self) -> usize {
|
pub fn getWidth(&self) -> usize {
|
||||||
return self.binarizer.getWidth();
|
return self.binarizer.borrow().getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The height of the bitmap.
|
* @return The height of the bitmap.
|
||||||
*/
|
*/
|
||||||
pub fn getHeight(&self) -> usize {
|
pub fn getHeight(&self) -> usize {
|
||||||
return self.binarizer.getHeight();
|
return self.binarizer.borrow().getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,8 +68,8 @@ impl BinaryBitmap {
|
|||||||
* @return The array of bits for this row (true means black).
|
* @return The array of bits for this row (true means black).
|
||||||
* @throws NotFoundException if row can't be binarized
|
* @throws NotFoundException if row can't be binarized
|
||||||
*/
|
*/
|
||||||
pub fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions> {
|
pub fn getBlackRow(&mut self, y: usize) -> Result<BitArray, Exceptions> {
|
||||||
return self.binarizer.getBlackRow(y, row);
|
return self.binarizer.borrow_mut().getBlackRow(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,7 +87,16 @@ impl BinaryBitmap {
|
|||||||
// 1. This work will never be done if the caller only installs 1D Reader objects, or if a
|
// 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.
|
// 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.
|
// 2. This work will only be done once even if the caller installs multiple 2D Readers.
|
||||||
&mut self.matrix
|
if self.matrix.is_none() {
|
||||||
|
self.matrix = Some(
|
||||||
|
self.binarizer
|
||||||
|
.borrow_mut()
|
||||||
|
.getBlackMatrix()
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.matrix.as_mut().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,21 +108,30 @@ impl BinaryBitmap {
|
|||||||
* @return The 2D array of bits for the image (true means black).
|
* @return The 2D array of bits for the image (true means black).
|
||||||
* @throws NotFoundException if image can't be binarized to make a matrix
|
* @throws NotFoundException if image can't be binarized to make a matrix
|
||||||
*/
|
*/
|
||||||
pub fn getBlackMatrix(&self) -> &BitMatrix {
|
pub fn getBlackMatrix(&mut self) -> &BitMatrix {
|
||||||
// The matrix is created on demand the first time it is requested, then cached. There are two
|
// The matrix is created on demand the first time it is requested, then cached. There are two
|
||||||
// reasons for this:
|
// reasons for this:
|
||||||
// 1. This work will never be done if the caller only installs 1D Reader objects, or if a
|
// 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.
|
// 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.
|
// 2. This work will only be done once even if the caller installs multiple 2D Readers.
|
||||||
&self.matrix
|
if self.matrix.is_none() {
|
||||||
|
self.matrix = Some(
|
||||||
|
self.binarizer
|
||||||
|
.borrow_mut()
|
||||||
|
.getBlackMatrix()
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
&self.matrix.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether this bitmap can be cropped.
|
* @return Whether this bitmap can be cropped.
|
||||||
*/
|
*/
|
||||||
pub fn isCropSupported(&self) -> bool {
|
pub fn isCropSupported(&self) -> bool {
|
||||||
let b = &self.binarizer;
|
let b = self.binarizer.borrow();
|
||||||
let r = &b.getLuminanceSource();
|
let r = b.getLuminanceSource();
|
||||||
let isCropOk = r.isCropSupported();
|
let isCropOk = r.isCropSupported();
|
||||||
return isCropOk;
|
return isCropOk;
|
||||||
}
|
}
|
||||||
@@ -128,22 +146,32 @@ impl BinaryBitmap {
|
|||||||
* @param height The height of the rectangle to crop.
|
* @param height The height of the rectangle to crop.
|
||||||
* @return A cropped version of this object.
|
* @return A cropped version of this object.
|
||||||
*/
|
*/
|
||||||
pub fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> BinaryBitmap {
|
pub fn crop(&mut self, left: usize, top: usize, width: usize, height: usize) -> BinaryBitmap {
|
||||||
let newSource = self
|
let newSource = self
|
||||||
.binarizer
|
.binarizer
|
||||||
|
.borrow()
|
||||||
.getLuminanceSource()
|
.getLuminanceSource()
|
||||||
.crop(left, top, width, height);
|
.crop(left, top, width, height);
|
||||||
return BinaryBitmap::new(
|
return BinaryBitmap::new(
|
||||||
self.binarizer
|
self.binarizer
|
||||||
|
.borrow()
|
||||||
.createBinarizer(newSource.expect("new lum source expected")),
|
.createBinarizer(newSource.expect("new lum source expected")),
|
||||||
);
|
);
|
||||||
|
// Self {
|
||||||
|
// binarizer: self.binarizer.clone(),
|
||||||
|
// matrix: Some(self.getBlackMatrix().crop(top, left, height, width)),
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether this bitmap supports counter-clockwise rotation.
|
* @return Whether this bitmap supports counter-clockwise rotation.
|
||||||
*/
|
*/
|
||||||
pub fn isRotateSupported(&self) -> bool {
|
pub fn isRotateSupported(&self) -> bool {
|
||||||
return self.binarizer.getLuminanceSource().isRotateSupported();
|
return self
|
||||||
|
.binarizer
|
||||||
|
.borrow()
|
||||||
|
.getLuminanceSource()
|
||||||
|
.isRotateSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,12 +180,24 @@ impl BinaryBitmap {
|
|||||||
*
|
*
|
||||||
* @return A rotated version of this object.
|
* @return A rotated version of this object.
|
||||||
*/
|
*/
|
||||||
pub fn rotateCounterClockwise(&self) -> BinaryBitmap {
|
pub fn rotateCounterClockwise(&mut self) -> BinaryBitmap {
|
||||||
let newSource = self.binarizer.getLuminanceSource().rotateCounterClockwise();
|
let newSource = self
|
||||||
|
.binarizer
|
||||||
|
.borrow()
|
||||||
|
.getLuminanceSource()
|
||||||
|
.rotateCounterClockwise();
|
||||||
return BinaryBitmap::new(
|
return BinaryBitmap::new(
|
||||||
self.binarizer
|
self.binarizer
|
||||||
|
.borrow()
|
||||||
.createBinarizer(newSource.expect("new lum source expected")),
|
.createBinarizer(newSource.expect("new lum source expected")),
|
||||||
);
|
);
|
||||||
|
// let mut new_matrix = self.getBlackMatrix().clone();
|
||||||
|
// new_matrix.rotate90();
|
||||||
|
|
||||||
|
// Self {
|
||||||
|
// binarizer: self.binarizer.clone(),
|
||||||
|
// matrix: Some(new_matrix),
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,10 +209,12 @@ impl BinaryBitmap {
|
|||||||
pub fn rotateCounterClockwise45(&self) -> BinaryBitmap {
|
pub fn rotateCounterClockwise45(&self) -> BinaryBitmap {
|
||||||
let newSource = self
|
let newSource = self
|
||||||
.binarizer
|
.binarizer
|
||||||
|
.borrow()
|
||||||
.getLuminanceSource()
|
.getLuminanceSource()
|
||||||
.rotateCounterClockwise45();
|
.rotateCounterClockwise45();
|
||||||
return BinaryBitmap::new(
|
return BinaryBitmap::new(
|
||||||
self.binarizer
|
self.binarizer
|
||||||
|
.borrow()
|
||||||
.createBinarizer(newSource.expect("new lum source expected")),
|
.createBinarizer(newSource.expect("new lum source expected")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -180,6 +222,6 @@ impl BinaryBitmap {
|
|||||||
|
|
||||||
impl fmt::Display for BinaryBitmap {
|
impl fmt::Display for BinaryBitmap {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.getBlackMatrix())
|
write!(f, "{:?}", self.matrix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// package com.google.zxing;
|
use std::rc::Rc;
|
||||||
|
|
||||||
// import java.awt.Graphics2D;
|
|
||||||
// import java.awt.geom.AffineTransform;
|
|
||||||
// import java.awt.image.BufferedImage;
|
|
||||||
// import java.awt.image.WritableRaster;
|
|
||||||
|
|
||||||
use image::{DynamicImage, ImageBuffer, Luma};
|
use image::{DynamicImage, ImageBuffer, Luma};
|
||||||
use imageproc::geometric_transformations::rotate_about_center;
|
use imageproc::geometric_transformations::rotate_about_center;
|
||||||
@@ -38,7 +33,7 @@ const MINUS_45_IN_RADIANS: f32 = std::f32::consts::FRAC_PI_4;
|
|||||||
*/
|
*/
|
||||||
pub struct BufferedImageLuminanceSource {
|
pub struct BufferedImageLuminanceSource {
|
||||||
// extends LuminanceSource {
|
// extends LuminanceSource {
|
||||||
image: DynamicImage,
|
image: Rc<DynamicImage>,
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
left: u32,
|
left: u32,
|
||||||
@@ -151,7 +146,7 @@ impl BufferedImageLuminanceSource {
|
|||||||
// let ib:ImageBuffer<Luma<u8>, Vec<u8>> = ImageBuffer::from_raw(image.width() , image.height(), raster).unwrap();
|
// let ib:ImageBuffer<Luma<u8>, Vec<u8>> = ImageBuffer::from_raw(image.width() , image.height(), raster).unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
image: DynamicImage::from(raster),
|
image: Rc::new(DynamicImage::from(raster)),
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
left: left,
|
left: left,
|
||||||
@@ -169,34 +164,60 @@ impl BufferedImageLuminanceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LuminanceSource for BufferedImageLuminanceSource {
|
impl LuminanceSource for BufferedImageLuminanceSource {
|
||||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
fn getRow(&self, y: usize) -> Vec<u8> {
|
||||||
let width = self.getWidth();
|
let width = self.getWidth(); // - self.left as usize;
|
||||||
|
|
||||||
let mut row = if row.len() >= width {
|
|
||||||
row.to_vec()
|
|
||||||
} else {
|
|
||||||
vec![0; width]
|
|
||||||
};
|
|
||||||
|
|
||||||
let pixels: Vec<u8> = self
|
let pixels: Vec<u8> = self
|
||||||
.image
|
.image
|
||||||
.clone()
|
.as_luma8()
|
||||||
.into_luma8()
|
|
||||||
.rows()
|
|
||||||
.nth(y)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.rows()
|
||||||
|
.nth(y + self.top as usize)
|
||||||
|
.unwrap()
|
||||||
|
.skip(self.left as usize)
|
||||||
|
.take(width)
|
||||||
.map(|&p| p.0[0])
|
.map(|&p| p.0[0])
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// The underlying raster of image consists of bytes with the luminance values
|
// The underlying raster of image consists of bytes with the luminance values
|
||||||
row[..width].clone_from_slice(&pixels[..]);
|
// row[..width].clone_from_slice(&pixels[..]);
|
||||||
|
|
||||||
return row;
|
pixels
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getMatrix(&self) -> Vec<u8> {
|
fn getMatrix(&self) -> Vec<u8> {
|
||||||
|
if self.height == self.image.height() as usize && self.width == self.image.width() as usize
|
||||||
|
{
|
||||||
return self.image.as_bytes().to_vec();
|
return self.image.as_bytes().to_vec();
|
||||||
}
|
}
|
||||||
|
let skip = self.top * self.image.width();
|
||||||
|
let row_skip = self.left;
|
||||||
|
let total_row_take = self.width;
|
||||||
|
let total_rows_to_take = self.image.width() * self.height as u32;
|
||||||
|
|
||||||
|
let unmanaged = self
|
||||||
|
.image
|
||||||
|
.as_bytes()
|
||||||
|
.iter()
|
||||||
|
.skip(skip as usize) // get to the row we want
|
||||||
|
.take(total_rows_to_take as usize)
|
||||||
|
.collect::<Vec<&u8>>(); // get all the rows we want to look at
|
||||||
|
|
||||||
|
let data = unmanaged
|
||||||
|
.chunks(self.image.width() as usize)
|
||||||
|
.into_iter() // Get rows
|
||||||
|
.map(|f| {
|
||||||
|
f.into_iter()
|
||||||
|
.skip(row_skip as usize)
|
||||||
|
.take(total_row_take as usize)
|
||||||
|
.copied()
|
||||||
|
}) // Take data from each row
|
||||||
|
.flatten() // flatten this all out
|
||||||
|
.copied() // copy it over so that it's u8
|
||||||
|
.collect(); // collect into a vec
|
||||||
|
|
||||||
|
data
|
||||||
|
}
|
||||||
|
|
||||||
fn getWidth(&self) -> usize {
|
fn getWidth(&self) -> usize {
|
||||||
self.width
|
self.width
|
||||||
@@ -207,7 +228,10 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn invert(&mut self) {
|
fn invert(&mut self) {
|
||||||
self.image.invert();
|
// self.image.borrow_mut().invert();
|
||||||
|
let mut img = (*self.image).clone();
|
||||||
|
img.invert();
|
||||||
|
self.image = Rc::new(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isCropSupported(&self) -> bool {
|
fn isCropSupported(&self) -> bool {
|
||||||
@@ -230,9 +254,10 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
|||||||
// height,
|
// height,
|
||||||
// )))
|
// )))
|
||||||
Ok(Box::new(Self {
|
Ok(Box::new(Self {
|
||||||
image: self
|
// image: self
|
||||||
.image
|
// .image
|
||||||
.crop_imm(left as u32, top as u32, width as u32, height as u32),
|
// .crop_imm(left as u32, top as u32, width as u32, height as u32),
|
||||||
|
image: self.image.clone(),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
left: self.left + left as u32,
|
left: self.left + left as u32,
|
||||||
@@ -254,7 +279,7 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
|||||||
Ok(Box::new(Self {
|
Ok(Box::new(Self {
|
||||||
width: img.width() as usize,
|
width: img.width() as usize,
|
||||||
height: img.height() as usize,
|
height: img.height() as usize,
|
||||||
image: img,
|
image: Rc::new(img),
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
}))
|
}))
|
||||||
@@ -276,7 +301,7 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
|||||||
Ok(Box::new(Self {
|
Ok(Box::new(Self {
|
||||||
width: new_img.width() as usize,
|
width: new_img.width() as usize,
|
||||||
height: new_img.height() as usize,
|
height: new_img.height() as usize,
|
||||||
image: new_img,
|
image: Rc::new(new_img),
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -27,8 +27,6 @@
|
|||||||
// */
|
// */
|
||||||
// public final class BitMatrixTestCase extends Assert {
|
// public final class BitMatrixTestCase extends Assert {
|
||||||
|
|
||||||
use crate::common::BitArray;
|
|
||||||
|
|
||||||
use super::BitMatrix;
|
use super::BitMatrix;
|
||||||
|
|
||||||
static BIT_MATRIX_POINTS: [u32; 6] = [1, 2, 2, 0, 3, 1];
|
static BIT_MATRIX_POINTS: [u32; 6] = [1, 2, 2, 0, 3, 1];
|
||||||
@@ -151,17 +149,17 @@ fn test_get_row() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Should allocate
|
// Should allocate
|
||||||
let array = matrix.getRow(2, BitArray::new());
|
let array = matrix.getRow(2);
|
||||||
assert_eq!(102, array.getSize());
|
assert_eq!(102, array.getSize());
|
||||||
|
|
||||||
// Should reallocate
|
// Should reallocate
|
||||||
let mut array2 = BitArray::with_size(60);
|
// let mut array2 = BitArray::with_size(60);
|
||||||
array2 = matrix.getRow(2, array2);
|
let array2 = matrix.getRow(2);
|
||||||
assert_eq!(102, array2.getSize());
|
assert_eq!(102, array2.getSize());
|
||||||
|
|
||||||
// Should use provided object, with original BitArray size
|
// Should use provided object, with original BitArray size
|
||||||
let mut array3 = BitArray::with_size(200);
|
// let mut array3 = BitArray::with_size(200);
|
||||||
array3 = matrix.getRow(2, array3);
|
let array3 = matrix.getRow(2);
|
||||||
assert_eq!(200, array3.getSize());
|
assert_eq!(200, array3.getSize());
|
||||||
|
|
||||||
for x in 0..102 {
|
for x in 0..102 {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ impl BitArray {
|
|||||||
* @return true iff bit i is set
|
* @return true iff bit i is set
|
||||||
*/
|
*/
|
||||||
pub fn get(&self, i: usize) -> bool {
|
pub fn get(&self, i: usize) -> bool {
|
||||||
return (self.bits[i / 32] & (1 << (i & 0x1F))) != 0;
|
(self.bits[i / 32] & (1 << (i & 0x1F))) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -267,11 +267,11 @@ impl BitMatrix {
|
|||||||
"input matrix dimensions do not match".to_owned(),
|
"input matrix dimensions do not match".to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let mut rowArray = BitArray::with_size(self.width as usize);
|
// let mut rowArray = BitArray::with_size(self.width as usize);
|
||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
//for (int y = 0; y < height; y++) {
|
//for (int y = 0; y < height; y++) {
|
||||||
let offset = y as usize * self.row_size;
|
let offset = y as usize * self.row_size;
|
||||||
rowArray = mask.getRow(y, rowArray);
|
let rowArray = mask.getRow(y);
|
||||||
let row = rowArray.getBitArray();
|
let row = rowArray.getBitArray();
|
||||||
for x in 0..self.row_size {
|
for x in 0..self.row_size {
|
||||||
//for (int x = 0; x < rowSize; x++) {
|
//for (int x = 0; x < rowSize; x++) {
|
||||||
@@ -344,16 +344,17 @@ impl BitMatrix {
|
|||||||
* @return The resulting BitArray - this reference should always be used even when passing
|
* @return The resulting BitArray - this reference should always be used even when passing
|
||||||
* your own row
|
* your own row
|
||||||
*/
|
*/
|
||||||
pub fn getRow(&self, y: u32, row: BitArray) -> BitArray {
|
pub fn getRow(&self, y: u32) -> BitArray {
|
||||||
let mut rw: BitArray = if row.getSize() < self.width as usize {
|
// let mut rw: BitArray = if row.getSize() < self.width as usize {
|
||||||
BitArray::with_size(self.width as usize)
|
// BitArray::with_size(self.width as usize)
|
||||||
} else {
|
// } else {
|
||||||
let mut z = row; //row.clone();
|
// let mut z = row; //row.clone();
|
||||||
z.clear();
|
// z.clear();
|
||||||
z
|
// z
|
||||||
// row.clear();
|
// // row.clear();
|
||||||
// row.clone()
|
// // row.clone()
|
||||||
};
|
// };
|
||||||
|
let mut rw = BitArray::with_size(self.width as usize);
|
||||||
|
|
||||||
let offset = y as usize * self.row_size;
|
let offset = y as usize * self.row_size;
|
||||||
for x in 0..self.row_size {
|
for x in 0..self.row_size {
|
||||||
@@ -404,14 +405,14 @@ impl BitMatrix {
|
|||||||
* Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
|
* Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
|
||||||
*/
|
*/
|
||||||
pub fn rotate180(&mut self) {
|
pub fn rotate180(&mut self) {
|
||||||
let mut topRow = BitArray::with_size(self.width as usize);
|
// let mut topRow = BitArray::with_size(self.width as usize);
|
||||||
let mut bottomRow = BitArray::with_size(self.width as usize);
|
// let mut bottomRow = BitArray::with_size(self.width as usize);
|
||||||
let maxHeight = (self.height + 1) / 2;
|
let maxHeight = (self.height + 1) / 2;
|
||||||
for i in 0..maxHeight {
|
for i in 0..maxHeight {
|
||||||
//for (int i = 0; i < maxHeight; i++) {
|
//for (int i = 0; i < maxHeight; i++) {
|
||||||
topRow = self.getRow(i, topRow);
|
let mut topRow = self.getRow(i);
|
||||||
let bottomRowIndex = self.height - 1 - i;
|
let bottomRowIndex = self.height - 1 - i;
|
||||||
bottomRow = self.getRow(bottomRowIndex, bottomRow);
|
let mut bottomRow = self.getRow(bottomRowIndex);
|
||||||
topRow.reverse();
|
topRow.reverse();
|
||||||
bottomRow.reverse();
|
bottomRow.reverse();
|
||||||
self.setRow(i, &bottomRow);
|
self.setRow(i, &bottomRow);
|
||||||
@@ -632,6 +633,25 @@ impl BitMatrix {
|
|||||||
// public BitMatrix clone() {
|
// public BitMatrix clone() {
|
||||||
// return new BitMatrix(width, height, rowSize, bits.clone());
|
// return new BitMatrix(width, height, rowSize, bits.clone());
|
||||||
// }
|
// }
|
||||||
|
// pub fn crop(&self, top:usize, left:usize, height: usize, width: usize) -> BitMatrix {
|
||||||
|
// let area = self.bits.iter().skip(self.row_size * top).take(self.row_size * height)
|
||||||
|
// .copied().collect::<Vec<u32>>();
|
||||||
|
// let new_bits = area.chunks(self.row_size)
|
||||||
|
// .skip(left).take(width).flatten().copied().collect::<Vec<u32>>();
|
||||||
|
// Self { width: width, height: height, row_size: width, bits: () }
|
||||||
|
// }
|
||||||
|
pub fn crop(&self, top: usize, left: usize, height: usize, width: usize) -> BitMatrix {
|
||||||
|
let mut new_bm = BitMatrix::new(width as u32, height as u32).expect("create empty");
|
||||||
|
for y in top..top + height {
|
||||||
|
// let row = self.getRow(y as u32);
|
||||||
|
for x in left..left + width {
|
||||||
|
if self.get(x as u32, y as u32) {
|
||||||
|
new_bm.set(x as u32, y as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_bm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BitMatrix {
|
impl fmt::Display for BitMatrix {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
// import com.google.zxing.LuminanceSource;
|
// import com.google.zxing.LuminanceSource;
|
||||||
// import com.google.zxing.NotFoundException;
|
// import com.google.zxing.NotFoundException;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{Binarizer, Exceptions, LuminanceSource};
|
use crate::{Binarizer, Exceptions, LuminanceSource};
|
||||||
|
|
||||||
@@ -38,11 +38,12 @@ use super::{BitArray, BitMatrix};
|
|||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
pub struct GlobalHistogramBinarizer {
|
pub struct GlobalHistogramBinarizer {
|
||||||
luminances: Vec<u8>,
|
_luminances: Vec<u8>,
|
||||||
buckets: Vec<u32>,
|
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
source: Box<dyn LuminanceSource>,
|
source: Box<dyn LuminanceSource>,
|
||||||
|
black_matrix: Option<BitMatrix>,
|
||||||
|
black_row_cache: Vec<Option<BitArray>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Binarizer for GlobalHistogramBinarizer {
|
impl Binarizer for GlobalHistogramBinarizer {
|
||||||
@@ -51,26 +52,23 @@ impl Binarizer for GlobalHistogramBinarizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Applies simple sharpening to the row data to improve performance of the 1D Readers.
|
// Applies simple sharpening to the row data to improve performance of the 1D Readers.
|
||||||
fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions> {
|
fn getBlackRow(&mut self, y: usize) -> Result<BitArray, Exceptions> {
|
||||||
|
if let Some(black_row) = &self.black_row_cache[y] {
|
||||||
|
return Ok(black_row.clone());
|
||||||
|
}
|
||||||
let source = self.getLuminanceSource();
|
let source = self.getLuminanceSource();
|
||||||
let width = source.getWidth();
|
let width = source.getWidth();
|
||||||
let mut row = if row.getSize() < width {
|
let mut row = BitArray::with_size(width);
|
||||||
BitArray::with_size(width)
|
|
||||||
} else {
|
|
||||||
let mut z = row.clone();
|
|
||||||
z.clear();
|
|
||||||
z
|
|
||||||
};
|
|
||||||
|
|
||||||
// self.initArrays(width);
|
// self.initArrays(width);
|
||||||
let localLuminances = source.getRow(y, &self.luminances);
|
let localLuminances = source.getRow(y);
|
||||||
let mut localBuckets = self.buckets.clone();
|
let mut localBuckets = [0; GlobalHistogramBinarizer::LUMINANCE_BUCKETS]; //self.buckets.clone();
|
||||||
for x in 0..width {
|
for x in 0..width {
|
||||||
// for (int x = 0; x < width; x++) {
|
// for (int x = 0; x < width; x++) {
|
||||||
localBuckets
|
localBuckets
|
||||||
[((localLuminances[x]) >> GlobalHistogramBinarizer::LUMINANCE_SHIFT) as usize] += 1;
|
[((localLuminances[x]) >> GlobalHistogramBinarizer::LUMINANCE_SHIFT) as usize] += 1;
|
||||||
}
|
}
|
||||||
let blackPoint = self.estimateBlackPoint(&localBuckets)?;
|
let blackPoint = Self::estimateBlackPoint(&localBuckets)?;
|
||||||
|
|
||||||
if width < 3 {
|
if width < 3 {
|
||||||
// Special case for very small images
|
// Special case for very small images
|
||||||
@@ -94,12 +92,54 @@ impl Binarizer for GlobalHistogramBinarizer {
|
|||||||
center = right;
|
center = right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.black_row_cache[y] = Some(row.clone());
|
||||||
Ok(row)
|
Ok(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
|
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
|
||||||
fn getBlackMatrix(&self) -> Result<BitMatrix, Exceptions> {
|
fn getBlackMatrix(&mut self) -> Result<&BitMatrix, Exceptions> {
|
||||||
let source = self.getLuminanceSource();
|
if self.black_matrix.is_none() {
|
||||||
|
self.black_matrix =
|
||||||
|
Some(Self::build_black_matrix(&self.source).expect("matrix must generate"))
|
||||||
|
}
|
||||||
|
Ok(self.black_matrix.as_ref().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createBinarizer(
|
||||||
|
&self,
|
||||||
|
source: Box<dyn crate::LuminanceSource>,
|
||||||
|
) -> Rc<RefCell<dyn Binarizer>> {
|
||||||
|
return Rc::new(RefCell::new(GlobalHistogramBinarizer::new(source)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getWidth(&self) -> usize {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getHeight(&self) -> usize {
|
||||||
|
self.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
pub fn new(source: Box<dyn LuminanceSource>) -> Self {
|
||||||
|
Self {
|
||||||
|
_luminances: vec![0; source.getWidth()],
|
||||||
|
width: source.getWidth(),
|
||||||
|
height: source.getHeight(),
|
||||||
|
black_matrix: None,
|
||||||
|
black_row_cache: vec![None; source.getHeight()],
|
||||||
|
source: source,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_black_matrix(source: &Box<dyn LuminanceSource>) -> Result<BitMatrix, Exceptions> {
|
||||||
|
// let source = source.getLuminanceSource();
|
||||||
let width = source.getWidth();
|
let width = source.getWidth();
|
||||||
let height = source.getHeight();
|
let height = source.getHeight();
|
||||||
let mut matrix = BitMatrix::new(width as u32, height as u32)?;
|
let mut matrix = BitMatrix::new(width as u32, height as u32)?;
|
||||||
@@ -107,11 +147,11 @@ impl Binarizer for GlobalHistogramBinarizer {
|
|||||||
// Quickly calculates the histogram by sampling four rows from the image. This proved to be
|
// Quickly calculates the histogram by sampling four rows from the image. This proved to be
|
||||||
// more robust on the blackbox tests than sampling a diagonal as we used to do.
|
// more robust on the blackbox tests than sampling a diagonal as we used to do.
|
||||||
// self.initArrays(width);
|
// self.initArrays(width);
|
||||||
let mut localBuckets = self.buckets.clone();
|
let mut localBuckets = [0; GlobalHistogramBinarizer::LUMINANCE_BUCKETS]; //self.buckets.clone();
|
||||||
for y in 1..5 {
|
for y in 1..5 {
|
||||||
// for (int y = 1; y < 5; y++) {
|
// for (int y = 1; y < 5; y++) {
|
||||||
let row = height * y / 5;
|
let row = height * y / 5;
|
||||||
let localLuminances = source.getRow(row, &self.luminances);
|
let localLuminances = source.getRow(row);
|
||||||
let right = (width * 4) / 5;
|
let right = (width * 4) / 5;
|
||||||
let mut x = width / 5;
|
let mut x = width / 5;
|
||||||
while x < right {
|
while x < right {
|
||||||
@@ -121,7 +161,7 @@ impl Binarizer for GlobalHistogramBinarizer {
|
|||||||
x += 1;
|
x += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let blackPoint = self.estimateBlackPoint(&localBuckets)?;
|
let blackPoint = Self::estimateBlackPoint(&localBuckets)?;
|
||||||
|
|
||||||
// We delay reading the entire image luminance until the black point estimation succeeds.
|
// We delay reading the entire image luminance until the black point estimation succeeds.
|
||||||
// Although we end up reading four rows twice, it is consistent with our motto of
|
// Although we end up reading four rows twice, it is consistent with our motto of
|
||||||
@@ -142,35 +182,6 @@ impl Binarizer for GlobalHistogramBinarizer {
|
|||||||
Ok(matrix)
|
Ok(matrix)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createBinarizer(&self, source: Box<dyn crate::LuminanceSource>) -> Rc<dyn Binarizer> {
|
|
||||||
return Rc::new(GlobalHistogramBinarizer::new(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getWidth(&self) -> usize {
|
|
||||||
self.width
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getHeight(&self) -> usize {
|
|
||||||
self.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
|
||||||
|
|
||||||
pub fn new(source: Box<dyn LuminanceSource>) -> Self {
|
|
||||||
Self {
|
|
||||||
luminances: vec![0; source.getWidth()],
|
|
||||||
buckets: vec![0; GlobalHistogramBinarizer::LUMINANCE_BUCKETS],
|
|
||||||
width: source.getWidth(),
|
|
||||||
height: source.getHeight(),
|
|
||||||
source: source,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn initArrays(&mut self, luminanceSize: usize) {
|
// fn initArrays(&mut self, luminanceSize: usize) {
|
||||||
// // if self.luminances.len() < luminanceSize {
|
// // if self.luminances.len() < luminanceSize {
|
||||||
// // self.luminances = ;
|
// // self.luminances = ;
|
||||||
@@ -181,7 +192,7 @@ impl GlobalHistogramBinarizer {
|
|||||||
// // }
|
// // }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn estimateBlackPoint(&self, buckets: &[u32]) -> Result<u32, Exceptions> {
|
fn estimateBlackPoint(buckets: &[u32]) -> Result<u32, Exceptions> {
|
||||||
// Find the tallest peak in the histogram.
|
// Find the tallest peak in the histogram.
|
||||||
let numBuckets = buckets.len();
|
let numBuckets = buckets.len();
|
||||||
let mut maxBucketCount = 0;
|
let mut maxBucketCount = 0;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
// import com.google.zxing.LuminanceSource;
|
// import com.google.zxing.LuminanceSource;
|
||||||
// import com.google.zxing.NotFoundException;
|
// import com.google.zxing.NotFoundException;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{Binarizer, Exceptions, LuminanceSource};
|
use crate::{Binarizer, Exceptions, LuminanceSource};
|
||||||
|
|
||||||
@@ -48,15 +48,15 @@ pub struct HybridBinarizer {
|
|||||||
//height: usize,
|
//height: usize,
|
||||||
//source: Box<dyn LuminanceSource>,
|
//source: Box<dyn LuminanceSource>,
|
||||||
ghb: GlobalHistogramBinarizer,
|
ghb: GlobalHistogramBinarizer,
|
||||||
// matrix :Option<BitMatrix>,
|
black_matrix: Option<BitMatrix>,
|
||||||
}
|
}
|
||||||
impl Binarizer for HybridBinarizer {
|
impl Binarizer for HybridBinarizer {
|
||||||
fn getLuminanceSource(&self) -> &Box<dyn LuminanceSource> {
|
fn getLuminanceSource(&self) -> &Box<dyn LuminanceSource> {
|
||||||
self.ghb.getLuminanceSource()
|
self.ghb.getLuminanceSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions> {
|
fn getBlackRow(&mut self, y: usize) -> Result<BitArray, Exceptions> {
|
||||||
self.ghb.getBlackRow(y, row)
|
self.ghb.getBlackRow(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,12 +64,48 @@ impl Binarizer for HybridBinarizer {
|
|||||||
* constructor instead, but there are some advantages to doing it lazily, such as making
|
* constructor instead, but there are some advantages to doing it lazily, such as making
|
||||||
* profiling easier, and not doing heavy lifting when callers don't expect it.
|
* profiling easier, and not doing heavy lifting when callers don't expect it.
|
||||||
*/
|
*/
|
||||||
fn getBlackMatrix(&self) -> Result<BitMatrix, Exceptions> {
|
fn getBlackMatrix(&mut self) -> Result<&BitMatrix, Exceptions> {
|
||||||
// if self.matrix.is_some() {
|
if self.black_matrix.is_none() {
|
||||||
// return Ok(self.matrix.clone().unwrap())
|
self.black_matrix = Some(
|
||||||
// }
|
Self::calculateBlackMatrix(&mut self.ghb)
|
||||||
|
.expect("generate black matrix must complete"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Ok(self.black_matrix.as_ref().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createBinarizer(&self, source: Box<dyn LuminanceSource>) -> Rc<RefCell<dyn Binarizer>> {
|
||||||
|
Rc::new(RefCell::new(HybridBinarizer::new(source)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getWidth(&self) -> usize {
|
||||||
|
self.ghb.getWidth()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getHeight(&self) -> usize {
|
||||||
|
self.ghb.getHeight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl HybridBinarizer {
|
||||||
|
// This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.
|
||||||
|
// So this is the smallest dimension in each axis we can accept.
|
||||||
|
const BLOCK_SIZE_POWER: usize = 3;
|
||||||
|
const BLOCK_SIZE: usize = 1 << HybridBinarizer::BLOCK_SIZE_POWER; // ...0100...00
|
||||||
|
const BLOCK_SIZE_MASK: usize = HybridBinarizer::BLOCK_SIZE - 1; // ...0011...11
|
||||||
|
const MINIMUM_DIMENSION: usize = HybridBinarizer::BLOCK_SIZE * 5;
|
||||||
|
const MIN_DYNAMIC_RANGE: usize = 24;
|
||||||
|
|
||||||
|
pub fn new(source: Box<dyn LuminanceSource>) -> Self {
|
||||||
|
let ghb = GlobalHistogramBinarizer::new(source);
|
||||||
|
Self {
|
||||||
|
black_matrix: None,
|
||||||
|
ghb: ghb,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculateBlackMatrix(ghb: &mut GlobalHistogramBinarizer) -> Result<BitMatrix, Exceptions> {
|
||||||
let matrix;
|
let matrix;
|
||||||
let source = self.getLuminanceSource();
|
let source = ghb.getLuminanceSource();
|
||||||
let width = source.getWidth();
|
let width = source.getWidth();
|
||||||
let height = source.getHeight();
|
let height = source.getHeight();
|
||||||
if width >= HybridBinarizer::MINIMUM_DIMENSION
|
if width >= HybridBinarizer::MINIMUM_DIMENSION
|
||||||
@@ -102,41 +138,14 @@ impl Binarizer for HybridBinarizer {
|
|||||||
&black_points,
|
&black_points,
|
||||||
&mut new_matrix,
|
&mut new_matrix,
|
||||||
);
|
);
|
||||||
matrix = new_matrix;
|
matrix = Ok(new_matrix);
|
||||||
} else {
|
} else {
|
||||||
// If the image is too small, fall back to the global histogram approach.
|
// If the image is too small, fall back to the global histogram approach.
|
||||||
matrix = self.ghb.getBlackMatrix()?;
|
let m = ghb.getBlackMatrix()?;
|
||||||
|
matrix = Ok(m.clone());
|
||||||
}
|
}
|
||||||
// dbg!(matrix.to_string());
|
// dbg!(matrix.to_string());
|
||||||
Ok(matrix)
|
matrix
|
||||||
}
|
|
||||||
|
|
||||||
fn createBinarizer(&self, source: Box<dyn LuminanceSource>) -> Rc<dyn Binarizer> {
|
|
||||||
Rc::new(HybridBinarizer::new(source))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getWidth(&self) -> usize {
|
|
||||||
self.ghb.getWidth()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getHeight(&self) -> usize {
|
|
||||||
self.ghb.getHeight()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl HybridBinarizer {
|
|
||||||
// This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.
|
|
||||||
// So this is the smallest dimension in each axis we can accept.
|
|
||||||
const BLOCK_SIZE_POWER: usize = 3;
|
|
||||||
const BLOCK_SIZE: usize = 1 << HybridBinarizer::BLOCK_SIZE_POWER; // ...0100...00
|
|
||||||
const BLOCK_SIZE_MASK: usize = HybridBinarizer::BLOCK_SIZE - 1; // ...0011...11
|
|
||||||
const MINIMUM_DIMENSION: usize = HybridBinarizer::BLOCK_SIZE * 5;
|
|
||||||
const MIN_DYNAMIC_RANGE: usize = 24;
|
|
||||||
|
|
||||||
pub fn new(source: Box<dyn LuminanceSource>) -> Self {
|
|
||||||
Self {
|
|
||||||
ghb: GlobalHistogramBinarizer::new(source),
|
|
||||||
// matrix: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ impl Reader for DataMatrixReader {
|
|||||||
*/
|
*/
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ impl Reader for DataMatrixReader {
|
|||||||
*/
|
*/
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
let decoderRXingResult;
|
let decoderRXingResult;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ pub trait LuminanceSource {
|
|||||||
* Always use the returned object, and ignore the .length of the array.
|
* Always use the returned object, and ignore the .length of the array.
|
||||||
* @return An array containing the luminance data.
|
* @return An array containing the luminance data.
|
||||||
*/
|
*/
|
||||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8>;
|
fn getRow(&self, y: usize) -> Vec<u8>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
* Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ impl Reader for MaxiCodeReader {
|
|||||||
*/
|
*/
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ impl Reader for MaxiCodeReader {
|
|||||||
*/
|
*/
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
// Note that MaxiCode reader effectively always assumes PURE_BARCODE mode
|
// Note that MaxiCode reader effectively always assumes PURE_BARCODE mode
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ pub struct ByQuadrantReader<T: Reader>(T);
|
|||||||
impl<T: Reader> Reader for ByQuadrantReader<T> {
|
impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
let width = image.getWidth();
|
let width = image.getWidth();
|
||||||
@@ -49,7 +49,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
|||||||
// try {
|
// try {
|
||||||
let attempt = self
|
let attempt = self
|
||||||
.0
|
.0
|
||||||
.decode_with_hints(&image.crop(0, 0, halfWidth, halfHeight), hints);
|
.decode_with_hints(&mut image.crop(0, 0, halfWidth, halfHeight), hints);
|
||||||
// No need to call makeAbsolute as results will be relative to original top left here
|
// No need to call makeAbsolute as results will be relative to original top left here
|
||||||
match attempt {
|
match attempt {
|
||||||
// Ok() => return attempt,
|
// Ok() => return attempt,
|
||||||
@@ -63,7 +63,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
|||||||
// try {
|
// try {
|
||||||
let result = self
|
let result = self
|
||||||
.0
|
.0
|
||||||
.decode_with_hints(&image.crop(halfWidth, 0, halfWidth, halfHeight), hints);
|
.decode_with_hints(&mut image.crop(halfWidth, 0, halfWidth, halfHeight), hints);
|
||||||
match result {
|
match result {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
let points = Self::makeAbsolute(res.getRXingResultPoints(), halfWidth as f32, 0.0);
|
let points = Self::makeAbsolute(res.getRXingResultPoints(), halfWidth as f32, 0.0);
|
||||||
@@ -80,7 +80,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
|||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.0
|
.0
|
||||||
.decode_with_hints(&image.crop(0, halfHeight, halfWidth, halfHeight), hints);
|
.decode_with_hints(&mut image.crop(0, halfHeight, halfWidth, halfHeight), hints);
|
||||||
match result {
|
match result {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
let points = Self::makeAbsolute(res.getRXingResultPoints(), 0.0, halfHeight as f32);
|
let points = Self::makeAbsolute(res.getRXingResultPoints(), 0.0, halfHeight as f32);
|
||||||
@@ -98,7 +98,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
let result = self.0.decode_with_hints(
|
let result = self.0.decode_with_hints(
|
||||||
&image.crop(halfWidth, halfHeight, halfWidth, halfHeight),
|
&mut image.crop(halfWidth, halfHeight, halfWidth, halfHeight),
|
||||||
hints,
|
hints,
|
||||||
);
|
);
|
||||||
match result {
|
match result {
|
||||||
@@ -124,8 +124,8 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
|||||||
|
|
||||||
let quarterWidth = halfWidth / 2;
|
let quarterWidth = halfWidth / 2;
|
||||||
let quarterHeight = halfHeight / 2;
|
let quarterHeight = halfHeight / 2;
|
||||||
let center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
|
let mut center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
|
||||||
let result = self.0.decode_with_hints(¢er, hints)?;
|
let result = self.0.decode_with_hints(&mut center, hints)?;
|
||||||
|
|
||||||
let points = Self::makeAbsolute(
|
let points = Self::makeAbsolute(
|
||||||
result.getRXingResultPoints(),
|
result.getRXingResultPoints(),
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ pub struct GenericMultipleBarcodeReader<T: Reader>(T);
|
|||||||
impl<T: Reader> MultipleBarcodeReader for GenericMultipleBarcodeReader<T> {
|
impl<T: Reader> MultipleBarcodeReader for GenericMultipleBarcodeReader<T> {
|
||||||
fn decode_multiple(
|
fn decode_multiple(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
||||||
self.decode_multiple_with_hints(image, &HashMap::new())
|
self.decode_multiple_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_multiple_with_hints(
|
fn decode_multiple_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
@@ -70,7 +70,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
|||||||
|
|
||||||
fn doDecodeMultiple(
|
fn doDecodeMultiple(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &BinaryBitmap,
|
image: &mut BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
results: &mut Vec<RXingResult>,
|
results: &mut Vec<RXingResult>,
|
||||||
xOffset: u32,
|
xOffset: u32,
|
||||||
@@ -110,7 +110,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
|||||||
let mut minY: f32 = height as f32;
|
let mut minY: f32 = height as f32;
|
||||||
let mut maxX: f32 = 0.0;
|
let mut maxX: f32 = 0.0;
|
||||||
let mut maxY: f32 = 0.0;
|
let mut maxY: f32 = 0.0;
|
||||||
for point in resultPoints {
|
for point in &resultPoints {
|
||||||
// if (point == null) {
|
// if (point == null) {
|
||||||
// continue;
|
// continue;
|
||||||
// }
|
// }
|
||||||
@@ -133,7 +133,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
|||||||
// Decode left of barcode
|
// Decode left of barcode
|
||||||
if minX > Self::MIN_DIMENSION_TO_RECUR {
|
if minX > Self::MIN_DIMENSION_TO_RECUR {
|
||||||
self.doDecodeMultiple(
|
self.doDecodeMultiple(
|
||||||
&image.crop(0, 0, minX as usize, height),
|
&mut image.crop(0, 0, minX as usize, height),
|
||||||
hints,
|
hints,
|
||||||
results,
|
results,
|
||||||
xOffset,
|
xOffset,
|
||||||
@@ -144,7 +144,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
|||||||
// Decode above barcode
|
// Decode above barcode
|
||||||
if minY > Self::MIN_DIMENSION_TO_RECUR {
|
if minY > Self::MIN_DIMENSION_TO_RECUR {
|
||||||
self.doDecodeMultiple(
|
self.doDecodeMultiple(
|
||||||
&image.crop(0, 0, width, minY as usize),
|
&mut image.crop(0, 0, width, minY as usize),
|
||||||
hints,
|
hints,
|
||||||
results,
|
results,
|
||||||
xOffset,
|
xOffset,
|
||||||
@@ -155,7 +155,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
|||||||
// Decode right of barcode
|
// Decode right of barcode
|
||||||
if maxX < (width as f32) - Self::MIN_DIMENSION_TO_RECUR {
|
if maxX < (width as f32) - Self::MIN_DIMENSION_TO_RECUR {
|
||||||
self.doDecodeMultiple(
|
self.doDecodeMultiple(
|
||||||
&image.crop(maxX as usize, 0, width - maxX as usize, height),
|
&mut image.crop(maxX as usize, 0, width - maxX as usize, height),
|
||||||
hints,
|
hints,
|
||||||
results,
|
results,
|
||||||
xOffset + maxX as u32,
|
xOffset + maxX as u32,
|
||||||
@@ -166,7 +166,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
|||||||
// Decode below barcode
|
// Decode below barcode
|
||||||
if maxY < (height as f32) - Self::MIN_DIMENSION_TO_RECUR {
|
if maxY < (height as f32) - Self::MIN_DIMENSION_TO_RECUR {
|
||||||
self.doDecodeMultiple(
|
self.doDecodeMultiple(
|
||||||
&image.crop(0, maxY as usize, width, height - maxY as usize),
|
&mut image.crop(0, maxY as usize, width, height - maxY as usize),
|
||||||
hints,
|
hints,
|
||||||
results,
|
results,
|
||||||
xOffset,
|
xOffset,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{collections::HashSet, path::PathBuf, rc::Rc};
|
use std::{cell::RefCell, collections::HashSet, path::PathBuf, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::HybridBinarizer, BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
|
common::HybridBinarizer, BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
|
||||||
@@ -38,10 +38,14 @@ fn testMulti() {
|
|||||||
.decode()
|
.decode()
|
||||||
.expect("must decode");
|
.expect("must decode");
|
||||||
let source = BufferedImageLuminanceSource::new(image);
|
let source = BufferedImageLuminanceSource::new(image);
|
||||||
let bitmap = BinaryBitmap::new(Rc::new(HybridBinarizer::new(Box::new(source))));
|
let mut bitmap = BinaryBitmap::new(Rc::new(RefCell::new(HybridBinarizer::new(Box::new(
|
||||||
|
source,
|
||||||
|
)))));
|
||||||
|
|
||||||
let mut reader = GenericMultipleBarcodeReader::new(MultiFormatReader::default());
|
let mut reader = GenericMultipleBarcodeReader::new(MultiFormatReader::default());
|
||||||
let results = reader.decode_multiple(&bitmap).expect("must decode multi");
|
let results = reader
|
||||||
|
.decode_multiple(&mut bitmap)
|
||||||
|
.expect("must decode multi");
|
||||||
// assertNotNull(results);
|
// assertNotNull(results);
|
||||||
assert_eq!(2, results.len());
|
assert_eq!(2, results.len());
|
||||||
|
|
||||||
@@ -63,10 +67,14 @@ fn testMultiQR() {
|
|||||||
.decode()
|
.decode()
|
||||||
.expect("must decode");
|
.expect("must decode");
|
||||||
let source = BufferedImageLuminanceSource::new(image);
|
let source = BufferedImageLuminanceSource::new(image);
|
||||||
let bitmap = BinaryBitmap::new(Rc::new(HybridBinarizer::new(Box::new(source))));
|
let mut bitmap = BinaryBitmap::new(Rc::new(RefCell::new(HybridBinarizer::new(Box::new(
|
||||||
|
source,
|
||||||
|
)))));
|
||||||
|
|
||||||
let mut reader = GenericMultipleBarcodeReader::new(MultiFormatReader::default());
|
let mut reader = GenericMultipleBarcodeReader::new(MultiFormatReader::default());
|
||||||
let results = reader.decode_multiple(&bitmap).expect("must decode multi");
|
let results = reader
|
||||||
|
.decode_multiple(&mut bitmap)
|
||||||
|
.expect("must decode multi");
|
||||||
assert_eq!(4, results.len());
|
assert_eq!(4, results.len());
|
||||||
|
|
||||||
let mut barcodeContents = HashSet::new();
|
let mut barcodeContents = HashSet::new();
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ use crate::{BinaryBitmap, DecodingHintDictionary, Exceptions, RXingResult};
|
|||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
pub trait MultipleBarcodeReader {
|
pub trait MultipleBarcodeReader {
|
||||||
fn decode_multiple(&mut self, image: &BinaryBitmap) -> Result<Vec<RXingResult>, Exceptions>;
|
fn decode_multiple(&mut self, image: &mut BinaryBitmap)
|
||||||
|
-> Result<Vec<RXingResult>, Exceptions>;
|
||||||
|
|
||||||
fn decode_multiple_with_hints(
|
fn decode_multiple_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &BinaryBitmap,
|
image: &mut BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
) -> Result<Vec<RXingResult>, Exceptions>;
|
) -> Result<Vec<RXingResult>, Exceptions>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ pub struct QRCodeMultiReader(QRCodeReader);
|
|||||||
impl MultipleBarcodeReader for QRCodeMultiReader {
|
impl MultipleBarcodeReader for QRCodeMultiReader {
|
||||||
fn decode_multiple(
|
fn decode_multiple(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
||||||
self.decode_multiple_with_hints(image, &HashMap::new())
|
self.decode_multiple_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_multiple_with_hints(
|
fn decode_multiple_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
@@ -221,7 +221,7 @@ mod multi_qr_code_test_case {
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{collections::HashSet, path::PathBuf, rc::Rc};
|
use std::{cell::RefCell, collections::HashSet, path::PathBuf, rc::Rc};
|
||||||
|
|
||||||
use image;
|
use image;
|
||||||
|
|
||||||
@@ -249,10 +249,12 @@ mod multi_qr_code_test_case {
|
|||||||
.decode()
|
.decode()
|
||||||
.expect("must decode");
|
.expect("must decode");
|
||||||
let source = BufferedImageLuminanceSource::new(image);
|
let source = BufferedImageLuminanceSource::new(image);
|
||||||
let bitmap = BinaryBitmap::new(Rc::new(HybridBinarizer::new(Box::new(source))));
|
let mut bitmap = BinaryBitmap::new(Rc::new(RefCell::new(HybridBinarizer::new(Box::new(
|
||||||
|
source,
|
||||||
|
)))));
|
||||||
|
|
||||||
let mut reader = QRCodeMultiReader::new();
|
let mut reader = QRCodeMultiReader::new();
|
||||||
let results = reader.decode_multiple(&bitmap).expect("must decode");
|
let results = reader.decode_multiple(&mut bitmap).expect("must decode");
|
||||||
// assertNotNull(results);
|
// assertNotNull(results);
|
||||||
assert_eq!(4, results.len());
|
assert_eq!(4, results.len());
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ impl Reader for MultiFormatReader {
|
|||||||
*/
|
*/
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
self.set_ints(&HashMap::new());
|
self.set_ints(&HashMap::new());
|
||||||
self.decode_internal(image)
|
self.decode_internal(image)
|
||||||
@@ -64,7 +64,7 @@ impl Reader for MultiFormatReader {
|
|||||||
*/
|
*/
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
self.set_ints(hints);
|
self.set_ints(hints);
|
||||||
@@ -89,7 +89,10 @@ impl MultiFormatReader {
|
|||||||
* @return The contents of the image
|
* @return The contents of the image
|
||||||
* @throws NotFoundException Any errors which occurred
|
* @throws NotFoundException Any errors which occurred
|
||||||
*/
|
*/
|
||||||
pub fn decode_with_state(&mut self, image: &BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
pub fn decode_with_state(
|
||||||
|
&mut self,
|
||||||
|
image: &mut BinaryBitmap,
|
||||||
|
) -> Result<RXingResult, Exceptions> {
|
||||||
// Make sure to set up the default state so we don't crash
|
// Make sure to set up the default state so we don't crash
|
||||||
if self.readers.is_empty() {
|
if self.readers.is_empty() {
|
||||||
self.set_ints(&HashMap::new());
|
self.set_ints(&HashMap::new());
|
||||||
@@ -166,7 +169,7 @@ impl MultiFormatReader {
|
|||||||
self.readers = readers; //Vec::new(); //readers.toArray(EMPTY_READER_ARRAY);
|
self.readers = readers; //Vec::new(); //readers.toArray(EMPTY_READER_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_internal(&mut self, image: &BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
pub fn decode_internal(&mut self, image: &mut BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
||||||
if !self.readers.is_empty() {
|
if !self.readers.is_empty() {
|
||||||
for reader in self.readers.iter_mut() {
|
for reader in self.readers.iter_mut() {
|
||||||
// I'm not sure how to model this in rust
|
// I'm not sure how to model this in rust
|
||||||
@@ -184,13 +187,13 @@ impl MultiFormatReader {
|
|||||||
}
|
}
|
||||||
if self.hints.contains_key(&DecodeHintType::ALSO_INVERTED) {
|
if self.hints.contains_key(&DecodeHintType::ALSO_INVERTED) {
|
||||||
// Calling all readers again with inverted image
|
// Calling all readers again with inverted image
|
||||||
let mut image = image.clone();
|
// let mut image = image.clone();
|
||||||
image.getBlackMatrixMut().flip_self();
|
image.getBlackMatrixMut().flip_self();
|
||||||
for reader in self.readers.iter_mut() {
|
for reader in self.readers.iter_mut() {
|
||||||
// if (Thread.currentThread().isInterrupted()) {
|
// if (Thread.currentThread().isInterrupted()) {
|
||||||
// throw NotFoundException.getNotFoundInstance();
|
// throw NotFoundException.getNotFoundInstance();
|
||||||
// }
|
// }
|
||||||
let res = reader.decode_with_hints(&image, &self.hints);
|
let res = reader.decode_with_hints(image, &self.hints);
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ use std::collections::HashMap;
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitArray, BitMatrix, BitMatrixTestCase},
|
common::{BitMatrix, BitMatrixTestCase},
|
||||||
oned::{Code128Reader, OneDReader},
|
oned::{Code128Reader, OneDReader},
|
||||||
BarcodeFormat, EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions, Writer,
|
BarcodeFormat, EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions, Writer,
|
||||||
};
|
};
|
||||||
@@ -483,18 +483,18 @@ fn encode(toEncode: &str, compact: bool, expectedLoopback: &str) -> Result<BitMa
|
|||||||
let encRXingResult =
|
let encRXingResult =
|
||||||
WRITER.encode_with_hints(toEncode, &BarcodeFormat::CODE_128, 0, 0, &hints)?;
|
WRITER.encode_with_hints(toEncode, &BarcodeFormat::CODE_128, 0, 0, &hints)?;
|
||||||
if !expectedLoopback.is_empty() {
|
if !expectedLoopback.is_empty() {
|
||||||
let row = encRXingResult.getRow(0, BitArray::new());
|
let row = encRXingResult.getRow(0);
|
||||||
let rtRXingResult = reader.decodeRow(0, &row, &HashMap::new())?;
|
let rtRXingResult = reader.decodeRow(0, &row, &HashMap::new())?;
|
||||||
let actual = rtRXingResult.getText();
|
let actual = rtRXingResult.getText();
|
||||||
assert_eq!(expectedLoopback, actual);
|
assert_eq!(expectedLoopback, actual);
|
||||||
}
|
}
|
||||||
if compact {
|
if compact {
|
||||||
//check that what is encoded compactly yields the same on loopback as what was encoded fast.
|
//check that what is encoded compactly yields the same on loopback as what was encoded fast.
|
||||||
let row = encRXingResult.getRow(0, BitArray::new());
|
let row = encRXingResult.getRow(0);
|
||||||
let rtRXingResult = reader.decodeRow(0, &row, &HashMap::new())?;
|
let rtRXingResult = reader.decodeRow(0, &row, &HashMap::new())?;
|
||||||
let actual = rtRXingResult.getText();
|
let actual = rtRXingResult.getText();
|
||||||
let encRXingResultFast = WRITER.encode(toEncode, &BarcodeFormat::CODE_128, 0, 0)?;
|
let encRXingResultFast = WRITER.encode(toEncode, &BarcodeFormat::CODE_128, 0, 0)?;
|
||||||
let row = encRXingResultFast.getRow(0, BitArray::new());
|
let row = encRXingResultFast.getRow(0);
|
||||||
let rtRXingResult = reader.decodeRow(0, &row, &HashMap::new())?;
|
let rtRXingResult = reader.decodeRow(0, &row, &HashMap::new())?;
|
||||||
assert_eq!(rtRXingResult.getText(), actual);
|
assert_eq!(rtRXingResult.getText(), actual);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ mod code_39_extended_mode_test_case {
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitArray, BitMatrix},
|
common::BitMatrix,
|
||||||
oned::{Code39Reader, OneDReader},
|
oned::{Code39Reader, OneDReader},
|
||||||
};
|
};
|
||||||
#[test]
|
#[test]
|
||||||
@@ -412,8 +412,8 @@ mod code_39_extended_mode_test_case {
|
|||||||
let mut sut = Code39Reader::with_all_config(false, true);
|
let mut sut = Code39Reader::with_all_config(false, true);
|
||||||
let matrix =
|
let matrix =
|
||||||
BitMatrix::parse_strings(encodedRXingResult, "1", "0").expect("bitmatrix parse");
|
BitMatrix::parse_strings(encodedRXingResult, "1", "0").expect("bitmatrix parse");
|
||||||
let row = BitArray::with_size(matrix.getWidth() as usize);
|
// let row = BitArray::with_size(matrix.getWidth() as usize);
|
||||||
let row = matrix.getRow(0, row);
|
let row = matrix.getRow(0);
|
||||||
let result = sut.decodeRow(0, &row, &HashMap::new()).expect("decode row");
|
let result = sut.decodeRow(0, &row, &HashMap::new()).expect("decode row");
|
||||||
assert_eq!(expectedRXingResult, result.getText());
|
assert_eq!(expectedRXingResult, result.getText());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,7 @@ impl Code93Reader {
|
|||||||
mod Code93ReaderTestCase {
|
mod Code93ReaderTestCase {
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{common::BitMatrix, oned::OneDReader};
|
||||||
common::{BitArray, BitMatrix},
|
|
||||||
oned::OneDReader,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::Code93Reader;
|
use super::Code93Reader;
|
||||||
|
|
||||||
@@ -366,8 +363,8 @@ mod Code93ReaderTestCase {
|
|||||||
fn doTest(expectedRXingResult: &str, encodedRXingResult: &str) {
|
fn doTest(expectedRXingResult: &str, encodedRXingResult: &str) {
|
||||||
let mut sut = Code93Reader::new();
|
let mut sut = Code93Reader::new();
|
||||||
let matrix = BitMatrix::parse_strings(encodedRXingResult, "1", "0").expect("must parse");
|
let matrix = BitMatrix::parse_strings(encodedRXingResult, "1", "0").expect("must parse");
|
||||||
let mut row = BitArray::with_size(matrix.getWidth() as usize);
|
// let mut row = BitArray::with_size(matrix.getWidth() as usize);
|
||||||
row = matrix.getRow(0, row);
|
let row = matrix.getRow(0);
|
||||||
let result = sut
|
let result = sut
|
||||||
.decodeRow(0, &row, &HashMap::new())
|
.decodeRow(0, &row, &HashMap::new())
|
||||||
.expect("must decode");
|
.expect("must decode");
|
||||||
|
|||||||
@@ -120,14 +120,17 @@ use crate::Reader;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
impl Reader for MultiFormatOneDReader {
|
impl Reader for MultiFormatOneDReader {
|
||||||
fn decode(&mut self, image: &crate::BinaryBitmap) -> Result<crate::RXingResult, Exceptions> {
|
fn decode(
|
||||||
|
&mut self,
|
||||||
|
image: &mut crate::BinaryBitmap,
|
||||||
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, Exceptions> {
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
if let Ok(res) = self.doDecode(image, hints) {
|
if let Ok(res) = self.doDecode(image, hints) {
|
||||||
@@ -135,8 +138,8 @@ impl Reader for MultiFormatOneDReader {
|
|||||||
} else {
|
} else {
|
||||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||||
if tryHarder && image.isRotateSupported() {
|
if tryHarder && image.isRotateSupported() {
|
||||||
let rotatedImage = image.rotateCounterClockwise();
|
let mut rotatedImage = image.rotateCounterClockwise();
|
||||||
let mut result = self.doDecode(&rotatedImage, hints)?;
|
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||||
let metadata = result.getRXingResultMetadata();
|
let metadata = result.getRXingResultMetadata();
|
||||||
let mut orientation = 270;
|
let mut orientation = 270;
|
||||||
|
|||||||
@@ -147,14 +147,17 @@ use crate::RXingResultPoint;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
impl Reader for MultiFormatUPCEANReader {
|
impl Reader for MultiFormatUPCEANReader {
|
||||||
fn decode(&mut self, image: &crate::BinaryBitmap) -> Result<crate::RXingResult, Exceptions> {
|
fn decode(
|
||||||
|
&mut self,
|
||||||
|
image: &mut crate::BinaryBitmap,
|
||||||
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, Exceptions> {
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
if let Ok(res) = self.doDecode(image, hints) {
|
if let Ok(res) = self.doDecode(image, hints) {
|
||||||
@@ -162,8 +165,8 @@ impl Reader for MultiFormatUPCEANReader {
|
|||||||
} else {
|
} else {
|
||||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||||
if tryHarder && image.isRotateSupported() {
|
if tryHarder && image.isRotateSupported() {
|
||||||
let rotatedImage = image.rotateCounterClockwise();
|
let mut rotatedImage = image.rotateCounterClockwise();
|
||||||
let mut result = self.doDecode(&rotatedImage, hints)?;
|
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||||
let metadata = result.getRXingResultMetadata();
|
let metadata = result.getRXingResultMetadata();
|
||||||
let mut orientation = 270;
|
let mut orientation = 270;
|
||||||
|
|||||||
@@ -44,13 +44,13 @@ pub trait OneDReader: Reader {
|
|||||||
*/
|
*/
|
||||||
fn doDecode(
|
fn doDecode(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &BinaryBitmap,
|
image: &mut BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
) -> Result<RXingResult, Exceptions> {
|
) -> Result<RXingResult, Exceptions> {
|
||||||
let mut hints = hints.clone();
|
let mut hints = hints.clone();
|
||||||
let width = image.getWidth();
|
let width = image.getWidth();
|
||||||
let height = image.getHeight();
|
let height = image.getHeight();
|
||||||
let mut row = BitArray::with_size(width);
|
// let mut row = BitArray::with_size(width);
|
||||||
|
|
||||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||||
let rowStep = 1.max(height >> (if tryHarder { 8 } else { 5 }));
|
let rowStep = 1.max(height >> (if tryHarder { 8 } else { 5 }));
|
||||||
@@ -81,7 +81,7 @@ pub trait OneDReader: Reader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Estimate black point for this row and load it:
|
// Estimate black point for this row and load it:
|
||||||
let mut row = if let Ok(res) = image.getBlackRow(rowNumber as usize, &mut row) {
|
let mut row = if let Ok(res) = image.getBlackRow(rowNumber as usize) {
|
||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -24,16 +24,15 @@
|
|||||||
* http://www.piramidepse.com/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||||
*/
|
*/
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitArray, GlobalHistogramBinarizer},
|
common::GlobalHistogramBinarizer, oned::rss::expanded::RSSExpandedReader, BinaryBitmap,
|
||||||
oned::rss::expanded::RSSExpandedReader,
|
BufferedImageLuminanceSource,
|
||||||
BinaryBitmap, BufferedImageLuminanceSource,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::bit_array_builder;
|
use super::bit_array_builder;
|
||||||
@@ -175,13 +174,11 @@ fn assertCorrectImage2binary(fileName: &str, expected: &str) {
|
|||||||
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
|
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
|
||||||
|
|
||||||
let image = image::open(path).expect("file exists");
|
let image = image::open(path).expect("file exists");
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(image),
|
Box::new(BufferedImageLuminanceSource::new(image)),
|
||||||
))));
|
))));
|
||||||
let rowNumber = binaryMap.getHeight() / 2;
|
let rowNumber = binaryMap.getHeight() / 2;
|
||||||
let row = binaryMap
|
let row = binaryMap.getBlackRow(rowNumber).expect("row");
|
||||||
.getBlackRow(rowNumber, &mut BitArray::new())
|
|
||||||
.expect("row");
|
|
||||||
|
|
||||||
// let pairs = Vec::new();
|
// let pairs = Vec::new();
|
||||||
// try {
|
// try {
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::result::{ExpandedProductParsedRXingResult, ParsedClientResult},
|
client::result::{ExpandedProductParsedRXingResult, ParsedClientResult},
|
||||||
common::{BitArray, GlobalHistogramBinarizer},
|
common::GlobalHistogramBinarizer,
|
||||||
oned::{rss::expanded::RSSExpandedReader, OneDReader},
|
oned::{rss::expanded::RSSExpandedReader, OneDReader},
|
||||||
BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
|
BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
|
||||||
};
|
};
|
||||||
@@ -71,13 +71,11 @@ fn assertCorrectImage2result(fileName: &str, expected: ExpandedProductParsedRXin
|
|||||||
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
|
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
|
||||||
|
|
||||||
let image = image::open(path).expect("image must exist");
|
let image = image::open(path).expect("image must exist");
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(image),
|
Box::new(BufferedImageLuminanceSource::new(image)),
|
||||||
))));
|
))));
|
||||||
let rowNumber = binaryMap.getHeight() as usize / 2;
|
let rowNumber = binaryMap.getHeight() as usize / 2;
|
||||||
let row = binaryMap
|
let row = binaryMap.getBlackRow(rowNumber).expect("get row");
|
||||||
.getBlackRow(rowNumber, &mut BitArray::new())
|
|
||||||
.expect("get row");
|
|
||||||
|
|
||||||
let mut rssExpandedReader = RSSExpandedReader::new();
|
let mut rssExpandedReader = RSSExpandedReader::new();
|
||||||
let theRXingResult = rssExpandedReader
|
let theRXingResult = rssExpandedReader
|
||||||
|
|||||||
@@ -24,10 +24,10 @@
|
|||||||
* http://www.piramidepse.com/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitArray, GlobalHistogramBinarizer},
|
common::GlobalHistogramBinarizer,
|
||||||
oned::{rss::expanded::RSSExpandedReader, OneDReader},
|
oned::{rss::expanded::RSSExpandedReader, OneDReader},
|
||||||
BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
|
BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
|
||||||
};
|
};
|
||||||
@@ -184,13 +184,11 @@ fn assertCorrectImage2string(fileName: &str, expected: &str) {
|
|||||||
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
|
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
|
||||||
|
|
||||||
let image = image::open(path).expect("load image");
|
let image = image::open(path).expect("load image");
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(image),
|
Box::new(BufferedImageLuminanceSource::new(image)),
|
||||||
))));
|
))));
|
||||||
let rowNumber = binaryMap.getHeight() / 2;
|
let rowNumber = binaryMap.getHeight() / 2;
|
||||||
let row = binaryMap
|
let row = binaryMap.getBlackRow(rowNumber).expect("get row");
|
||||||
.getBlackRow(rowNumber, &mut BitArray::new())
|
|
||||||
.expect("get row");
|
|
||||||
|
|
||||||
let mut rssExpandedReader = RSSExpandedReader::new();
|
let mut rssExpandedReader = RSSExpandedReader::new();
|
||||||
let result = rssExpandedReader
|
let result = rssExpandedReader
|
||||||
|
|||||||
@@ -24,10 +24,10 @@
|
|||||||
* http://www.piramidepse.com/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitArray, GlobalHistogramBinarizer},
|
common::GlobalHistogramBinarizer,
|
||||||
oned::rss::{DataCharacterTrait, FinderPattern},
|
oned::rss::{DataCharacterTrait, FinderPattern},
|
||||||
BinaryBitmap, BufferedImageLuminanceSource,
|
BinaryBitmap, BufferedImageLuminanceSource,
|
||||||
};
|
};
|
||||||
@@ -42,13 +42,11 @@ use super::RSSExpandedReader;
|
|||||||
#[test]
|
#[test]
|
||||||
fn testFindFinderPatterns() {
|
fn testFindFinderPatterns() {
|
||||||
let image = readImage("2.png");
|
let image = readImage("2.png");
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(image),
|
Box::new(BufferedImageLuminanceSource::new(image)),
|
||||||
))));
|
))));
|
||||||
let rowNumber = binaryMap.getHeight() as u32 / 2;
|
let rowNumber = binaryMap.getHeight() as u32 / 2;
|
||||||
let row = binaryMap
|
let row = binaryMap.getBlackRow(rowNumber as usize).expect("ok");
|
||||||
.getBlackRow(rowNumber as usize, &mut BitArray::new())
|
|
||||||
.expect("ok");
|
|
||||||
let mut previousPairs = Vec::new(); //new ArrayList<>();
|
let mut previousPairs = Vec::new(); //new ArrayList<>();
|
||||||
|
|
||||||
let mut rssExpandedReader = RSSExpandedReader::new();
|
let mut rssExpandedReader = RSSExpandedReader::new();
|
||||||
@@ -90,13 +88,11 @@ fn testFindFinderPatterns() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn testRetrieveNextPairPatterns() {
|
fn testRetrieveNextPairPatterns() {
|
||||||
let image = readImage("3.png");
|
let image = readImage("3.png");
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(image),
|
Box::new(BufferedImageLuminanceSource::new(image)),
|
||||||
))));
|
))));
|
||||||
let rowNumber = binaryMap.getHeight() as u32 / 2;
|
let rowNumber = binaryMap.getHeight() as u32 / 2;
|
||||||
let row = binaryMap
|
let row = binaryMap.getBlackRow(rowNumber as usize).expect("create");
|
||||||
.getBlackRow(rowNumber as usize, &mut BitArray::new())
|
|
||||||
.expect("create");
|
|
||||||
let mut previousPairs = Vec::new(); //new ArrayList<>();
|
let mut previousPairs = Vec::new(); //new ArrayList<>();
|
||||||
|
|
||||||
let mut rssExpandedReader = RSSExpandedReader::new();
|
let mut rssExpandedReader = RSSExpandedReader::new();
|
||||||
@@ -120,11 +116,11 @@ fn testRetrieveNextPairPatterns() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn testDecodeCheckCharacter() {
|
fn testDecodeCheckCharacter() {
|
||||||
let image = readImage("3.png");
|
let image = readImage("3.png");
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(image.clone()),
|
Box::new(BufferedImageLuminanceSource::new(image.clone())),
|
||||||
))));
|
))));
|
||||||
let row = binaryMap
|
let row = binaryMap
|
||||||
.getBlackRow(binaryMap.getHeight() / 2, &mut BitArray::new())
|
.getBlackRow(binaryMap.getHeight() / 2)
|
||||||
.expect("create");
|
.expect("create");
|
||||||
|
|
||||||
let startEnd = [145, 243]; //image pixels where the A1 pattern starts (at 124) and ends (at 214)
|
let startEnd = [145, 243]; //image pixels where the A1 pattern starts (at 124) and ends (at 214)
|
||||||
@@ -148,11 +144,11 @@ fn testDecodeCheckCharacter() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn testDecodeDataCharacter() {
|
fn testDecodeDataCharacter() {
|
||||||
let image = readImage("3.png");
|
let image = readImage("3.png");
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(image.clone()),
|
Box::new(BufferedImageLuminanceSource::new(image.clone())),
|
||||||
))));
|
))));
|
||||||
let row = binaryMap
|
let row = binaryMap
|
||||||
.getBlackRow(binaryMap.getHeight() / 2, &mut BitArray::new())
|
.getBlackRow(binaryMap.getHeight() / 2)
|
||||||
.expect("create");
|
.expect("create");
|
||||||
|
|
||||||
let startEnd = [145, 243]; //image pixels where the A1 pattern starts (at 124) and ends (at 214)
|
let startEnd = [145, 243]; //image pixels where the A1 pattern starts (at 124) and ends (at 214)
|
||||||
|
|||||||
@@ -179,14 +179,17 @@ impl OneDReader for RSSExpandedReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Reader for RSSExpandedReader {
|
impl Reader for RSSExpandedReader {
|
||||||
fn decode(&mut self, image: &crate::BinaryBitmap) -> Result<crate::RXingResult, Exceptions> {
|
fn decode(
|
||||||
|
&mut self,
|
||||||
|
image: &mut crate::BinaryBitmap,
|
||||||
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, Exceptions> {
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
if let Ok(res) = self.doDecode(image, hints) {
|
if let Ok(res) = self.doDecode(image, hints) {
|
||||||
@@ -194,8 +197,8 @@ impl Reader for RSSExpandedReader {
|
|||||||
} else {
|
} else {
|
||||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||||
if tryHarder && image.isRotateSupported() {
|
if tryHarder && image.isRotateSupported() {
|
||||||
let rotatedImage = image.rotateCounterClockwise();
|
let mut rotatedImage = image.rotateCounterClockwise();
|
||||||
let mut result = self.doDecode(&rotatedImage, hints)?;
|
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||||
let metadata = result.getRXingResultMetadata();
|
let metadata = result.getRXingResultMetadata();
|
||||||
let mut orientation = 270;
|
let mut orientation = 270;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
* http://www.piramidepse.com/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::{common::BitArray, oned::rss::expanded::ExpandedPair, Exceptions, Reader};
|
use crate::{oned::rss::expanded::ExpandedPair, Exceptions, Reader};
|
||||||
|
|
||||||
use super::{test_case_util, RSSExpandedReader};
|
use super::{test_case_util, RSSExpandedReader};
|
||||||
|
|
||||||
@@ -36,12 +36,10 @@ use super::{test_case_util, RSSExpandedReader};
|
|||||||
fn testDecodingRowByRow() {
|
fn testDecodingRowByRow() {
|
||||||
let mut rssExpandedReader = RSSExpandedReader::new();
|
let mut rssExpandedReader = RSSExpandedReader::new();
|
||||||
|
|
||||||
let binaryMap = test_case_util::getBinaryBitmap("1000.png");
|
let mut binaryMap = test_case_util::getBinaryBitmap("1000.png");
|
||||||
|
|
||||||
let firstRowNumber = binaryMap.getHeight() / 3;
|
let firstRowNumber = binaryMap.getHeight() / 3;
|
||||||
let firstRow = binaryMap
|
let firstRow = binaryMap.getBlackRow(firstRowNumber).expect("get row");
|
||||||
.getBlackRow(firstRowNumber, &mut BitArray::new())
|
|
||||||
.expect("get row");
|
|
||||||
|
|
||||||
// let tester = ;
|
// let tester = ;
|
||||||
|
|
||||||
@@ -74,9 +72,7 @@ fn testDecodingRowByRow() {
|
|||||||
.getStartEndMut()[1] = 0;
|
.getStartEndMut()[1] = 0;
|
||||||
|
|
||||||
let secondRowNumber = 2 * binaryMap.getHeight() / 3;
|
let secondRowNumber = 2 * binaryMap.getHeight() / 3;
|
||||||
let mut secondRow = binaryMap
|
let mut secondRow = binaryMap.getBlackRow(secondRowNumber).expect("get row");
|
||||||
.getBlackRow(secondRowNumber, &mut BitArray::new())
|
|
||||||
.expect("get row");
|
|
||||||
secondRow.reverse();
|
secondRow.reverse();
|
||||||
|
|
||||||
let totalPairs = rssExpandedReader
|
let totalPairs = rssExpandedReader
|
||||||
@@ -91,8 +87,8 @@ fn testDecodingRowByRow() {
|
|||||||
fn testCompleteDecode() {
|
fn testCompleteDecode() {
|
||||||
let mut rssExpandedReader = RSSExpandedReader::new();
|
let mut rssExpandedReader = RSSExpandedReader::new();
|
||||||
|
|
||||||
let binaryMap = test_case_util::getBinaryBitmap("1000.png");
|
let mut binaryMap = test_case_util::getBinaryBitmap("1000.png");
|
||||||
|
|
||||||
let result = rssExpandedReader.decode(&binaryMap).expect("decode");
|
let result = rssExpandedReader.decode(&mut binaryMap).expect("decode");
|
||||||
assert_eq!("(01)98898765432106(3202)012345(15)991231", result.getText());
|
assert_eq!("(01)98898765432106(3202)012345(15)991231", result.getText());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
* http://www.piramidepse.com/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ fn getBufferedImage(fileName: &str) -> DynamicImage {
|
|||||||
|
|
||||||
pub(crate) fn getBinaryBitmap(fileName: &str) -> BinaryBitmap {
|
pub(crate) fn getBinaryBitmap(fileName: &str) -> BinaryBitmap {
|
||||||
let bufferedImage = getBufferedImage(fileName);
|
let bufferedImage = getBufferedImage(fileName);
|
||||||
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
|
let binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
|
||||||
BufferedImageLuminanceSource::new(bufferedImage),
|
Box::new(BufferedImageLuminanceSource::new(bufferedImage)),
|
||||||
))));
|
))));
|
||||||
|
|
||||||
binaryMap
|
binaryMap
|
||||||
|
|||||||
@@ -72,14 +72,17 @@ impl OneDReader for RSS14Reader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Reader for RSS14Reader {
|
impl Reader for RSS14Reader {
|
||||||
fn decode(&mut self, image: &crate::BinaryBitmap) -> Result<crate::RXingResult, Exceptions> {
|
fn decode(
|
||||||
|
&mut self,
|
||||||
|
image: &mut crate::BinaryBitmap,
|
||||||
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, Exceptions> {
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
if let Ok(res) = self.doDecode(image, hints) {
|
if let Ok(res) = self.doDecode(image, hints) {
|
||||||
@@ -87,8 +90,8 @@ impl Reader for RSS14Reader {
|
|||||||
} else {
|
} else {
|
||||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||||
if tryHarder && image.isRotateSupported() {
|
if tryHarder && image.isRotateSupported() {
|
||||||
let rotatedImage = image.rotateCounterClockwise();
|
let mut rotatedImage = image.rotateCounterClockwise();
|
||||||
let mut result = self.doDecode(&rotatedImage, hints)?;
|
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||||
let metadata = result.getRXingResultMetadata();
|
let metadata = result.getRXingResultMetadata();
|
||||||
let mut orientation = 270;
|
let mut orientation = 270;
|
||||||
|
|||||||
@@ -27,13 +27,16 @@ use super::{EAN13Reader, OneDReader, UPCEANReader};
|
|||||||
pub struct UPCAReader(EAN13Reader);
|
pub struct UPCAReader(EAN13Reader);
|
||||||
|
|
||||||
impl Reader for UPCAReader {
|
impl Reader for UPCAReader {
|
||||||
fn decode(&mut self, image: &crate::BinaryBitmap) -> Result<crate::RXingResult, Exceptions> {
|
fn decode(
|
||||||
|
&mut self,
|
||||||
|
image: &mut crate::BinaryBitmap,
|
||||||
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
Self::maybeReturnRXingResult(self.0.decode(image)?)
|
Self::maybeReturnRXingResult(self.0.decode(image)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, Exceptions> {
|
) -> Result<crate::RXingResult, Exceptions> {
|
||||||
Self::maybeReturnRXingResult(self.0.decode_with_hints(image, hints)?)
|
Self::maybeReturnRXingResult(self.0.decode_with_hints(image, hints)?)
|
||||||
|
|||||||
@@ -551,13 +551,13 @@ impl OneDReader for StandInStruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Reader for StandInStruct {
|
impl Reader for StandInStruct {
|
||||||
fn decode(&mut self, _image: &crate::BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
fn decode(&mut self, _image: &mut crate::BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
_image: &crate::BinaryBitmap,
|
_image: &mut crate::BinaryBitmap,
|
||||||
_hints: &crate::DecodingHintDictionary,
|
_hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<RXingResult, Exceptions> {
|
) -> Result<RXingResult, Exceptions> {
|
||||||
todo!()
|
todo!()
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const ROTATIONS: [u32; 4] = [0, 180, 270, 90];
|
|||||||
* @throws NotFoundException if no PDF417 Code can be found
|
* @throws NotFoundException if no PDF417 Code can be found
|
||||||
*/
|
*/
|
||||||
pub fn detect_with_hints(
|
pub fn detect_with_hints(
|
||||||
image: &BinaryBitmap,
|
image: &mut BinaryBitmap,
|
||||||
_hints: &DecodingHintDictionary,
|
_hints: &DecodingHintDictionary,
|
||||||
multiple: bool,
|
multiple: bool,
|
||||||
) -> Result<PDF417DetectorRXingResult, Exceptions> {
|
) -> Result<PDF417DetectorRXingResult, Exceptions> {
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ impl Reader for PDF417Reader {
|
|||||||
*/
|
*/
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
let result = Self::decode(image, hints, false)?;
|
let result = Self::decode(image, hints, false)?;
|
||||||
@@ -65,14 +65,14 @@ impl Reader for PDF417Reader {
|
|||||||
impl MultipleBarcodeReader for PDF417Reader {
|
impl MultipleBarcodeReader for PDF417Reader {
|
||||||
fn decode_multiple(
|
fn decode_multiple(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
||||||
self.decode_multiple_with_hints(image, &HashMap::new())
|
self.decode_multiple_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_multiple_with_hints(
|
fn decode_multiple_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
|
||||||
//try {
|
//try {
|
||||||
@@ -95,7 +95,7 @@ impl PDF417Reader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn decode(
|
fn decode(
|
||||||
image: &BinaryBitmap,
|
image: &mut BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
multiple: bool,
|
multiple: bool,
|
||||||
) -> Result<Vec<RXingResult>, Exceptions> {
|
) -> Result<Vec<RXingResult>, Exceptions> {
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ impl PlanarYUVLuminanceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LuminanceSource for PlanarYUVLuminanceSource {
|
impl LuminanceSource for PlanarYUVLuminanceSource {
|
||||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
fn getRow(&self, y: usize) -> Vec<u8> {
|
||||||
if y >= self.getHeight() {
|
if y >= self.getHeight() {
|
||||||
//throw new IllegalArgumentException("Requested row is outside the image: " + y);
|
//throw new IllegalArgumentException("Requested row is outside the image: " + y);
|
||||||
panic!("Requested row is outside the image: {}", y);
|
panic!("Requested row is outside the image: {}", y);
|
||||||
@@ -257,11 +257,7 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
|
|||||||
|
|
||||||
let offset = (y + self.top) * self.data_width + self.left;
|
let offset = (y + self.top) * self.data_width + self.left;
|
||||||
|
|
||||||
let mut row = if row.len() >= width {
|
let mut row = vec![0; width];
|
||||||
row.to_vec()
|
|
||||||
} else {
|
|
||||||
vec![0; width]
|
|
||||||
};
|
|
||||||
|
|
||||||
row[..width].clone_from_slice(&self.yuv_data[offset..width + offset]);
|
row[..width].clone_from_slice(&self.yuv_data[offset..width + offset]);
|
||||||
//System.arraycopy(yuvData, offset, row, 0, width);
|
//System.arraycopy(yuvData, offset, row, 0, width);
|
||||||
|
|||||||
@@ -49,14 +49,14 @@ impl Reader for QRCodeReader {
|
|||||||
*/
|
*/
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
self.decode_with_hints(image, &HashMap::new())
|
self.decode_with_hints(image, &HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &crate::BinaryBitmap,
|
image: &mut crate::BinaryBitmap,
|
||||||
hints: &crate::DecodingHintDictionary,
|
hints: &crate::DecodingHintDictionary,
|
||||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||||
let decoderRXingResult: DecoderRXingResult;
|
let decoderRXingResult: DecoderRXingResult;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ pub trait Reader {
|
|||||||
* @throws ChecksumException if a potential barcode is found but does not pass its checksum
|
* @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
|
* @throws FormatException if a potential barcode is found but format is invalid
|
||||||
*/
|
*/
|
||||||
fn decode(&mut self, image: &BinaryBitmap) -> Result<RXingResult, Exceptions>;
|
fn decode(&mut self, image: &mut BinaryBitmap) -> Result<RXingResult, Exceptions>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locates and decodes a barcode in some format within an image. This method also accepts
|
* Locates and decodes a barcode in some format within an image. This method also accepts
|
||||||
@@ -58,7 +58,7 @@ pub trait Reader {
|
|||||||
*/
|
*/
|
||||||
fn decode_with_hints(
|
fn decode_with_hints(
|
||||||
&mut self,
|
&mut self,
|
||||||
image: &BinaryBitmap,
|
image: &mut BinaryBitmap,
|
||||||
hints: &DecodingHintDictionary,
|
hints: &DecodingHintDictionary,
|
||||||
) -> Result<RXingResult, Exceptions>;
|
) -> Result<RXingResult, Exceptions>;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ pub struct RGBLuminanceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LuminanceSource for RGBLuminanceSource {
|
impl LuminanceSource for RGBLuminanceSource {
|
||||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
fn getRow(&self, y: usize) -> Vec<u8> {
|
||||||
if y >= self.getHeight() {
|
if y >= self.getHeight() {
|
||||||
panic!("Requested row is outside the image: {}", y);
|
panic!("Requested row is outside the image: {}", y);
|
||||||
}
|
}
|
||||||
@@ -46,11 +46,7 @@ impl LuminanceSource for RGBLuminanceSource {
|
|||||||
|
|
||||||
let offset = (y + self.top) * self.dataWidth + self.left;
|
let offset = (y + self.top) * self.dataWidth + self.left;
|
||||||
|
|
||||||
let mut row = if row.len() >= width {
|
let mut row = vec![0; width];
|
||||||
row.to_vec()
|
|
||||||
} else {
|
|
||||||
vec![0; width]
|
|
||||||
};
|
|
||||||
|
|
||||||
row[..width].clone_from_slice(&self.luminances[offset..offset + width]);
|
row[..width].clone_from_slice(&self.luminances[offset..offset + width]);
|
||||||
//System.arraycopy(self.luminances, offset, row, 0, width);
|
//System.arraycopy(self.luminances, offset, row, 0, width);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fs::{read_dir, read_to_string, File},
|
fs::{read_dir, read_to_string, File},
|
||||||
io::Read,
|
io::Read,
|
||||||
@@ -237,7 +238,9 @@ impl<T: Reader> AbstractBlackBoxTestCase<T> {
|
|||||||
let rotation = self.test_rxing_results.get(x).unwrap().get_rotation();
|
let rotation = self.test_rxing_results.get(x).unwrap().get_rotation();
|
||||||
let rotated_image = Self::rotate_image(&image, rotation);
|
let rotated_image = Self::rotate_image(&image, rotation);
|
||||||
let source = BufferedImageLuminanceSource::new(rotated_image);
|
let source = BufferedImageLuminanceSource::new(rotated_image);
|
||||||
let bitmap = BinaryBitmap::new(Rc::new(HybridBinarizer::new(Box::new(source))));
|
let mut bitmap = BinaryBitmap::new(Rc::new(RefCell::new(HybridBinarizer::new(
|
||||||
|
Box::new(source),
|
||||||
|
))));
|
||||||
|
|
||||||
// if file_base_name == "15" {
|
// if file_base_name == "15" {
|
||||||
// let mut f = File::create("test_file_output.txt").unwrap();
|
// let mut f = File::create("test_file_output.txt").unwrap();
|
||||||
@@ -246,9 +249,13 @@ impl<T: Reader> AbstractBlackBoxTestCase<T> {
|
|||||||
// Self::rotate_image(&image, rotation).save("test_image.png").unwrap();
|
// Self::rotate_image(&image, rotation).save("test_image.png").unwrap();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if let Ok(decoded) =
|
if let Ok(decoded) = self.decode(
|
||||||
self.decode(&bitmap, rotation, &expected_text, &expected_metadata, false)
|
&mut bitmap,
|
||||||
{
|
rotation,
|
||||||
|
&expected_text,
|
||||||
|
&expected_metadata,
|
||||||
|
false,
|
||||||
|
) {
|
||||||
if decoded {
|
if decoded {
|
||||||
passed_counts[x] += 1;
|
passed_counts[x] += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -266,9 +273,13 @@ impl<T: Reader> AbstractBlackBoxTestCase<T> {
|
|||||||
// } catch (ReaderException ignored) {
|
// } catch (ReaderException ignored) {
|
||||||
// log::fine(format!("could not read at rotation {}", rotation));
|
// log::fine(format!("could not read at rotation {}", rotation));
|
||||||
// }
|
// }
|
||||||
if let Ok(decoded) =
|
if let Ok(decoded) = self.decode(
|
||||||
self.decode(&bitmap, rotation, &expected_text, &expected_metadata, true)
|
&mut bitmap,
|
||||||
{
|
rotation,
|
||||||
|
&expected_text,
|
||||||
|
&expected_metadata,
|
||||||
|
true,
|
||||||
|
) {
|
||||||
if decoded {
|
if decoded {
|
||||||
try_harder_counts[x] += 1;
|
try_harder_counts[x] += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -404,7 +415,7 @@ impl<T: Reader> AbstractBlackBoxTestCase<T> {
|
|||||||
|
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
source: &BinaryBitmap,
|
source: &mut BinaryBitmap,
|
||||||
rotation: f32,
|
rotation: f32,
|
||||||
expected_text: &str,
|
expected_text: &str,
|
||||||
expected_metadata: &HashMap<RXingResultMetadataType, RXingResultMetadataValue>,
|
expected_metadata: &HashMap<RXingResultMetadataType, RXingResultMetadataValue>,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fs::{read_dir, read_to_string, File},
|
fs::{read_dir, read_to_string, File},
|
||||||
io::Read,
|
io::Read,
|
||||||
@@ -178,9 +179,13 @@ impl<T: MultipleBarcodeReader + Reader> PDF417MultiImageSpanAbstractBlackBoxTest
|
|||||||
let rotation: f32 = self.test_rxing_results.get(x).expect("ok").get_rotation();
|
let rotation: f32 = self.test_rxing_results.get(x).expect("ok").get_rotation();
|
||||||
let rotated_image = Self::rotate_image(&image, rotation);
|
let rotated_image = Self::rotate_image(&image, rotation);
|
||||||
let source = BufferedImageLuminanceSource::new(rotated_image);
|
let source = BufferedImageLuminanceSource::new(rotated_image);
|
||||||
let bitmap = BinaryBitmap::new(Rc::new(HybridBinarizer::new(Box::new(source))));
|
let mut bitmap = BinaryBitmap::new(Rc::new(RefCell::new(
|
||||||
|
HybridBinarizer::new(Box::new(source)),
|
||||||
|
)));
|
||||||
|
|
||||||
if let Ok(res) = Self::decode_pdf417(&bitmap, false, &mut self.barcode_reader) {
|
if let Ok(res) =
|
||||||
|
Self::decode_pdf417(&mut bitmap, false, &mut self.barcode_reader)
|
||||||
|
{
|
||||||
for r in res {
|
for r in res {
|
||||||
results.push(r);
|
results.push(r);
|
||||||
}
|
}
|
||||||
@@ -383,7 +388,9 @@ impl<T: MultipleBarcodeReader + Reader> PDF417MultiImageSpanAbstractBlackBoxTest
|
|||||||
let rotation = self.test_rxing_results.get(x).unwrap().get_rotation();
|
let rotation = self.test_rxing_results.get(x).unwrap().get_rotation();
|
||||||
let rotated_image = Self::rotate_image(&image, rotation);
|
let rotated_image = Self::rotate_image(&image, rotation);
|
||||||
let source = BufferedImageLuminanceSource::new(rotated_image);
|
let source = BufferedImageLuminanceSource::new(rotated_image);
|
||||||
let bitmap = BinaryBitmap::new(Rc::new(HybridBinarizer::new(Box::new(source))));
|
let mut bitmap = BinaryBitmap::new(Rc::new(RefCell::new(HybridBinarizer::new(
|
||||||
|
Box::new(source),
|
||||||
|
))));
|
||||||
|
|
||||||
// if file_base_name == "15" {
|
// if file_base_name == "15" {
|
||||||
// let mut f = File::create("test_file_output.txt").unwrap();
|
// let mut f = File::create("test_file_output.txt").unwrap();
|
||||||
@@ -392,9 +399,13 @@ impl<T: MultipleBarcodeReader + Reader> PDF417MultiImageSpanAbstractBlackBoxTest
|
|||||||
// Self::rotate_image(&image, rotation).save("test_image.png").unwrap();
|
// Self::rotate_image(&image, rotation).save("test_image.png").unwrap();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if let Ok(decoded) =
|
if let Ok(decoded) = self.decode(
|
||||||
self.decode(&bitmap, rotation, &expected_text, &expected_metadata, false)
|
&mut bitmap,
|
||||||
{
|
rotation,
|
||||||
|
&expected_text,
|
||||||
|
&expected_metadata,
|
||||||
|
false,
|
||||||
|
) {
|
||||||
if decoded {
|
if decoded {
|
||||||
passed_counts[x] += 1;
|
passed_counts[x] += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -412,9 +423,13 @@ impl<T: MultipleBarcodeReader + Reader> PDF417MultiImageSpanAbstractBlackBoxTest
|
|||||||
// } catch (ReaderException ignored) {
|
// } catch (ReaderException ignored) {
|
||||||
// log::fine(format!("could not read at rotation {}", rotation));
|
// log::fine(format!("could not read at rotation {}", rotation));
|
||||||
// }
|
// }
|
||||||
if let Ok(decoded) =
|
if let Ok(decoded) = self.decode(
|
||||||
self.decode(&bitmap, rotation, &expected_text, &expected_metadata, true)
|
&mut bitmap,
|
||||||
{
|
rotation,
|
||||||
|
&expected_text,
|
||||||
|
&expected_metadata,
|
||||||
|
true,
|
||||||
|
) {
|
||||||
if decoded {
|
if decoded {
|
||||||
try_harder_counts[x] += 1;
|
try_harder_counts[x] += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -550,7 +565,7 @@ impl<T: MultipleBarcodeReader + Reader> PDF417MultiImageSpanAbstractBlackBoxTest
|
|||||||
|
|
||||||
fn decode(
|
fn decode(
|
||||||
&mut self,
|
&mut self,
|
||||||
source: &BinaryBitmap,
|
source: &mut BinaryBitmap,
|
||||||
rotation: f32,
|
rotation: f32,
|
||||||
expected_text: &str,
|
expected_text: &str,
|
||||||
expected_metadata: &HashMap<RXingResultMetadataType, RXingResultMetadataValue>,
|
expected_metadata: &HashMap<RXingResultMetadataType, RXingResultMetadataValue>,
|
||||||
@@ -739,7 +754,7 @@ impl<T: MultipleBarcodeReader + Reader> PDF417MultiImageSpanAbstractBlackBoxTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn decode_pdf417(
|
fn decode_pdf417(
|
||||||
source: &BinaryBitmap,
|
source: &mut BinaryBitmap,
|
||||||
try_harder: bool,
|
try_harder: bool,
|
||||||
barcode_reader: &mut T,
|
barcode_reader: &mut T,
|
||||||
) -> Result<Vec<RXingResult>, Exceptions> {
|
) -> Result<Vec<RXingResult>, Exceptions> {
|
||||||
|
|||||||
Reference in New Issue
Block a user