update for shared state and improved performance

This commit is contained in:
Henry Schimke
2023-01-02 16:38:05 -06:00
parent 72f69dd6a0
commit 65f7c4d01b
46 changed files with 505 additions and 359 deletions

View File

@@ -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]

View File

@@ -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.

View File

@@ -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,
);
} }
} }

View File

@@ -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]

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)
} }
} }

View File

@@ -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,
})) }))

View File

@@ -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 {

View File

@@ -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
} }
/** /**

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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,
}
} }
/** /**

View File

@@ -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;

View File

@@ -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:

View File

@@ -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

View File

@@ -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(&center, hints)?; let result = self.0.decode_with_hints(&mut center, hints)?;
let points = Self::makeAbsolute( let points = Self::makeAbsolute(
result.getRXingResultPoints(), result.getRXingResultPoints(),

View File

@@ -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,

View File

@@ -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();

View File

@@ -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>;
} }

View File

@@ -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());

View File

@@ -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;
} }

View File

@@ -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);
} }

View File

@@ -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());
} }

View File

@@ -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");

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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());
} }

View File

@@ -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

View File

@@ -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;

View File

@@ -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)?)

View File

@@ -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!()

View File

@@ -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> {

View File

@@ -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> {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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>;

View File

@@ -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);

View File

@@ -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>,

View File

@@ -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> {