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

@@ -55,7 +55,7 @@ fn test_no_crop() {
assert_equals(&Y, 0, &source.getMatrix(), 0, Y.len());
for r in 0..ROWS {
// 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 (int r = 0; r < ROWS - 2; r++) {
assert_equals(
&Y,
(r + 1) * COLS + 1,
&source.getRow(r, &vec![0; 0]),
0,
COLS - 2,
);
assert_equals(&Y, (r + 1) * COLS + 1, &source.getRow(r), 0, COLS - 2);
}
}

View File

@@ -38,7 +38,7 @@ fn testCrop() {
let cropped = SOURCE.crop(1, 1, 1, 1).unwrap();
assert_eq!(1, cropped.getHeight());
assert_eq!(1, cropped.getWidth());
assert_eq!(vec![0x7F], cropped.getRow(0, &vec![0; 0]));
assert_eq!(vec![0x7F], cropped.getRow(0));
}
#[test]
@@ -62,7 +62,7 @@ fn testMatrix() {
fn testGetRow() {
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]

View File

@@ -40,13 +40,13 @@ impl Reader for AztecReader {
* @throws NotFoundException if a Data Matrix code cannot be found
* @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())
}
fn decode_with_hints(
&mut self,
image: &BinaryBitmap,
image: &mut BinaryBitmap,
hints: &HashMap<DecodeHintType, DecodeHintValue>,
) -> Result<RXingResult, Exceptions> {
// let notFoundException = None;

View File

@@ -16,7 +16,7 @@
//package com.google.zxing;
use std::rc::Rc;
use std::{cell::RefCell, rc::Rc};
use crate::{
common::{BitArray, BitMatrix},
@@ -51,7 +51,7 @@ pub trait Binarizer {
* @return The array of bits for this row (true means black).
* @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
@@ -62,7 +62,7 @@ pub trait Binarizer {
* @return The 2D array of bits for the image (true means black).
* @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
@@ -72,7 +72,7 @@ pub trait Binarizer {
* @param source The LuminanceSource this Binarizer will operate on.
* @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;

View File

@@ -16,7 +16,7 @@
//package com.google.zxing;
use std::{fmt, rc::Rc};
use std::{cell::RefCell, fmt, rc::Rc};
use crate::{
common::{BitArray, BitMatrix},
@@ -29,16 +29,16 @@ use crate::{
*
* @author dswitkin@google.com (Daniel Switkin)
*/
#[derive(Clone)]
pub struct BinaryBitmap {
binarizer: Rc<dyn Binarizer>,
matrix: BitMatrix,
binarizer: Rc<RefCell<dyn Binarizer>>,
matrix: Option<BitMatrix>,
}
impl BinaryBitmap {
pub fn new(binarizer: Rc<dyn Binarizer>) -> Self {
pub fn new(binarizer: Rc<RefCell<dyn Binarizer>>) -> Self {
Self {
matrix: binarizer.getBlackMatrix().unwrap(),
matrix: None,
binarizer: binarizer,
}
}
@@ -47,14 +47,14 @@ impl BinaryBitmap {
* @return The width of the bitmap.
*/
pub fn getWidth(&self) -> usize {
return self.binarizer.getWidth();
return self.binarizer.borrow().getWidth();
}
/**
* @return The height of the bitmap.
*/
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).
* @throws NotFoundException if row can't be binarized
*/
pub fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions> {
return self.binarizer.getBlackRow(y, row);
pub fn getBlackRow(&mut self, y: usize) -> Result<BitArray, Exceptions> {
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
// 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.
&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).
* @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
// reasons for this:
// 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.
// 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.
*/
pub fn isCropSupported(&self) -> bool {
let b = &self.binarizer;
let r = &b.getLuminanceSource();
let b = self.binarizer.borrow();
let r = b.getLuminanceSource();
let isCropOk = r.isCropSupported();
return isCropOk;
}
@@ -128,22 +146,32 @@ impl BinaryBitmap {
* @param height The height of the rectangle to crop.
* @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
.binarizer
.borrow()
.getLuminanceSource()
.crop(left, top, width, height);
return BinaryBitmap::new(
self.binarizer
.borrow()
.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.
*/
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.
*/
pub fn rotateCounterClockwise(&self) -> BinaryBitmap {
let newSource = self.binarizer.getLuminanceSource().rotateCounterClockwise();
pub fn rotateCounterClockwise(&mut self) -> BinaryBitmap {
let newSource = self
.binarizer
.borrow()
.getLuminanceSource()
.rotateCounterClockwise();
return BinaryBitmap::new(
self.binarizer
.borrow()
.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 {
let newSource = self
.binarizer
.borrow()
.getLuminanceSource()
.rotateCounterClockwise45();
return BinaryBitmap::new(
self.binarizer
.borrow()
.createBinarizer(newSource.expect("new lum source expected")),
);
}
@@ -180,6 +222,6 @@ impl BinaryBitmap {
impl fmt::Display for BinaryBitmap {
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.
*/
// package com.google.zxing;
// import java.awt.Graphics2D;
// import java.awt.geom.AffineTransform;
// import java.awt.image.BufferedImage;
// import java.awt.image.WritableRaster;
use std::rc::Rc;
use image::{DynamicImage, ImageBuffer, Luma};
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 {
// extends LuminanceSource {
image: DynamicImage,
image: Rc<DynamicImage>,
width: usize,
height: usize,
left: u32,
@@ -151,7 +146,7 @@ impl BufferedImageLuminanceSource {
// let ib:ImageBuffer<Luma<u8>, Vec<u8>> = ImageBuffer::from_raw(image.width() , image.height(), raster).unwrap();
Self {
image: DynamicImage::from(raster),
image: Rc::new(DynamicImage::from(raster)),
width: width,
height: height,
left: left,
@@ -169,33 +164,59 @@ impl BufferedImageLuminanceSource {
}
impl LuminanceSource for BufferedImageLuminanceSource {
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
let width = self.getWidth();
let mut row = if row.len() >= width {
row.to_vec()
} else {
vec![0; width]
};
fn getRow(&self, y: usize) -> Vec<u8> {
let width = self.getWidth(); // - self.left as usize;
let pixels: Vec<u8> = self
.image
.clone()
.into_luma8()
.rows()
.nth(y)
.as_luma8()
.unwrap()
.rows()
.nth(y + self.top as usize)
.unwrap()
.skip(self.left as usize)
.take(width)
.map(|&p| p.0[0])
.collect();
// 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> {
return self.image.as_bytes().to_vec();
if self.height == self.image.height() as usize && self.width == self.image.width() as usize
{
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 {
@@ -207,7 +228,10 @@ impl LuminanceSource for BufferedImageLuminanceSource {
}
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 {
@@ -230,9 +254,10 @@ impl LuminanceSource for BufferedImageLuminanceSource {
// height,
// )))
Ok(Box::new(Self {
image: self
.image
.crop_imm(left as u32, top as u32, width as u32, height as u32),
// image: self
// .image
// .crop_imm(left as u32, top as u32, width as u32, height as u32),
image: self.image.clone(),
width,
height,
left: self.left + left as u32,
@@ -254,7 +279,7 @@ impl LuminanceSource for BufferedImageLuminanceSource {
Ok(Box::new(Self {
width: img.width() as usize,
height: img.height() as usize,
image: img,
image: Rc::new(img),
left: 0,
top: 0,
}))
@@ -276,7 +301,7 @@ impl LuminanceSource for BufferedImageLuminanceSource {
Ok(Box::new(Self {
width: new_img.width() as usize,
height: new_img.height() as usize,
image: new_img,
image: Rc::new(new_img),
left: 0,
top: 0,
}))

View File

@@ -27,8 +27,6 @@
// */
// public final class BitMatrixTestCase extends Assert {
use crate::common::BitArray;
use super::BitMatrix;
static BIT_MATRIX_POINTS: [u32; 6] = [1, 2, 2, 0, 3, 1];
@@ -151,17 +149,17 @@ fn test_get_row() {
}
// Should allocate
let array = matrix.getRow(2, BitArray::new());
let array = matrix.getRow(2);
assert_eq!(102, array.getSize());
// Should reallocate
let mut array2 = BitArray::with_size(60);
array2 = matrix.getRow(2, array2);
// let mut array2 = BitArray::with_size(60);
let array2 = matrix.getRow(2);
assert_eq!(102, array2.getSize());
// Should use provided object, with original BitArray size
let mut array3 = BitArray::with_size(200);
array3 = matrix.getRow(2, array3);
// let mut array3 = BitArray::with_size(200);
let array3 = matrix.getRow(2);
assert_eq!(200, array3.getSize());
for x in 0..102 {

View File

@@ -81,7 +81,7 @@ impl BitArray {
* @return true iff bit i is set
*/
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(),
));
}
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 (int y = 0; y < height; y++) {
let offset = y as usize * self.row_size;
rowArray = mask.getRow(y, rowArray);
let rowArray = mask.getRow(y);
let row = rowArray.getBitArray();
for x in 0..self.row_size {
//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
* your own row
*/
pub fn getRow(&self, y: u32, row: BitArray) -> BitArray {
let mut rw: BitArray = if row.getSize() < self.width as usize {
BitArray::with_size(self.width as usize)
} else {
let mut z = row; //row.clone();
z.clear();
z
// row.clear();
// row.clone()
};
pub fn getRow(&self, y: u32) -> BitArray {
// let mut rw: BitArray = if row.getSize() < self.width as usize {
// BitArray::with_size(self.width as usize)
// } else {
// let mut z = row; //row.clone();
// z.clear();
// z
// // row.clear();
// // row.clone()
// };
let mut rw = BitArray::with_size(self.width as usize);
let offset = y as usize * 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
*/
pub fn rotate180(&mut self) {
let mut topRow = BitArray::with_size(self.width as usize);
let mut bottomRow = 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 maxHeight = (self.height + 1) / 2;
for i in 0..maxHeight {
//for (int i = 0; i < maxHeight; i++) {
topRow = self.getRow(i, topRow);
let mut topRow = self.getRow(i);
let bottomRowIndex = self.height - 1 - i;
bottomRow = self.getRow(bottomRowIndex, bottomRow);
let mut bottomRow = self.getRow(bottomRowIndex);
topRow.reverse();
bottomRow.reverse();
self.setRow(i, &bottomRow);
@@ -632,6 +633,25 @@ impl BitMatrix {
// public BitMatrix 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 {

View File

@@ -20,7 +20,7 @@
// import com.google.zxing.LuminanceSource;
// import com.google.zxing.NotFoundException;
use std::rc::Rc;
use std::{cell::RefCell, rc::Rc};
use crate::{Binarizer, Exceptions, LuminanceSource};
@@ -38,11 +38,12 @@ use super::{BitArray, BitMatrix};
* @author Sean Owen
*/
pub struct GlobalHistogramBinarizer {
luminances: Vec<u8>,
buckets: Vec<u32>,
_luminances: Vec<u8>,
width: usize,
height: usize,
source: Box<dyn LuminanceSource>,
black_matrix: Option<BitMatrix>,
black_row_cache: Vec<Option<BitArray>>,
}
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.
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 width = source.getWidth();
let mut row = if row.getSize() < width {
BitArray::with_size(width)
} else {
let mut z = row.clone();
z.clear();
z
};
let mut row = BitArray::with_size(width);
// self.initArrays(width);
let localLuminances = source.getRow(y, &self.luminances);
let mut localBuckets = self.buckets.clone();
let localLuminances = source.getRow(y);
let mut localBuckets = [0; GlobalHistogramBinarizer::LUMINANCE_BUCKETS]; //self.buckets.clone();
for x in 0..width {
// for (int x = 0; x < width; x++) {
localBuckets
[((localLuminances[x]) >> GlobalHistogramBinarizer::LUMINANCE_SHIFT) as usize] += 1;
}
let blackPoint = self.estimateBlackPoint(&localBuckets)?;
let blackPoint = Self::estimateBlackPoint(&localBuckets)?;
if width < 3 {
// Special case for very small images
@@ -94,12 +92,54 @@ impl Binarizer for GlobalHistogramBinarizer {
center = right;
}
}
self.black_row_cache[y] = Some(row.clone());
Ok(row)
}
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
fn getBlackMatrix(&self) -> Result<BitMatrix, Exceptions> {
let source = self.getLuminanceSource();
fn getBlackMatrix(&mut self) -> Result<&BitMatrix, Exceptions> {
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 height = source.getHeight();
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
// more robust on the blackbox tests than sampling a diagonal as we used to do.
// 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 (int y = 1; y < 5; y++) {
let row = height * y / 5;
let localLuminances = source.getRow(row, &self.luminances);
let localLuminances = source.getRow(row);
let right = (width * 4) / 5;
let mut x = width / 5;
while x < right {
@@ -121,7 +161,7 @@ impl Binarizer for GlobalHistogramBinarizer {
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.
// 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)
}
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) {
// // if self.luminances.len() < luminanceSize {
// // 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.
let numBuckets = buckets.len();
let mut maxBucketCount = 0;

View File

@@ -20,7 +20,7 @@
// import com.google.zxing.LuminanceSource;
// import com.google.zxing.NotFoundException;
use std::rc::Rc;
use std::{cell::RefCell, rc::Rc};
use crate::{Binarizer, Exceptions, LuminanceSource};
@@ -48,15 +48,15 @@ pub struct HybridBinarizer {
//height: usize,
//source: Box<dyn LuminanceSource>,
ghb: GlobalHistogramBinarizer,
// matrix :Option<BitMatrix>,
black_matrix: Option<BitMatrix>,
}
impl Binarizer for HybridBinarizer {
fn getLuminanceSource(&self) -> &Box<dyn LuminanceSource> {
self.ghb.getLuminanceSource()
}
fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions> {
self.ghb.getBlackRow(y, row)
fn getBlackRow(&mut self, y: usize) -> Result<BitArray, Exceptions> {
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
* profiling easier, and not doing heavy lifting when callers don't expect it.
*/
fn getBlackMatrix(&self) -> Result<BitMatrix, Exceptions> {
// if self.matrix.is_some() {
// return Ok(self.matrix.clone().unwrap())
// }
fn getBlackMatrix(&mut self) -> Result<&BitMatrix, Exceptions> {
if self.black_matrix.is_none() {
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 source = self.getLuminanceSource();
let source = ghb.getLuminanceSource();
let width = source.getWidth();
let height = source.getHeight();
if width >= HybridBinarizer::MINIMUM_DIMENSION
@@ -102,41 +138,14 @@ impl Binarizer for HybridBinarizer {
&black_points,
&mut new_matrix,
);
matrix = new_matrix;
matrix = Ok(new_matrix);
} else {
// 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());
Ok(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,
}
matrix
}
/**

View File

@@ -52,7 +52,7 @@ impl Reader for DataMatrixReader {
*/
fn decode(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.decode_with_hints(image, &HashMap::new())
}
@@ -67,7 +67,7 @@ impl Reader for DataMatrixReader {
*/
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
let decoderRXingResult;

View File

@@ -45,7 +45,7 @@ pub trait LuminanceSource {
* Always use the returned object, and ignore the .length of the array.
* @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:

View File

@@ -40,7 +40,7 @@ impl Reader for MaxiCodeReader {
*/
fn decode(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.decode_with_hints(image, &HashMap::new())
}
@@ -55,7 +55,7 @@ impl Reader for MaxiCodeReader {
*/
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
// 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> {
fn decode(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.decode_with_hints(image, &HashMap::new())
}
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
let width = image.getWidth();
@@ -49,7 +49,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
// try {
let attempt = self
.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
match attempt {
// Ok() => return attempt,
@@ -63,7 +63,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
// try {
let result = self
.0
.decode_with_hints(&image.crop(halfWidth, 0, halfWidth, halfHeight), hints);
.decode_with_hints(&mut image.crop(halfWidth, 0, halfWidth, halfHeight), hints);
match result {
Ok(res) => {
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
.0
.decode_with_hints(&image.crop(0, halfHeight, halfWidth, halfHeight), hints);
.decode_with_hints(&mut image.crop(0, halfHeight, halfWidth, halfHeight), hints);
match result {
Ok(res) => {
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(
&image.crop(halfWidth, halfHeight, halfWidth, halfHeight),
&mut image.crop(halfWidth, halfHeight, halfWidth, halfHeight),
hints,
);
match result {
@@ -124,8 +124,8 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
let quarterWidth = halfWidth / 2;
let quarterHeight = halfHeight / 2;
let center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
let result = self.0.decode_with_hints(&center, hints)?;
let mut center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
let result = self.0.decode_with_hints(&mut center, hints)?;
let points = Self::makeAbsolute(
result.getRXingResultPoints(),

View File

@@ -42,14 +42,14 @@ pub struct GenericMultipleBarcodeReader<T: Reader>(T);
impl<T: Reader> MultipleBarcodeReader for GenericMultipleBarcodeReader<T> {
fn decode_multiple(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
self.decode_multiple_with_hints(image, &HashMap::new())
}
fn decode_multiple_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
let mut results = Vec::new();
@@ -70,7 +70,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
fn doDecodeMultiple(
&mut self,
image: &BinaryBitmap,
image: &mut BinaryBitmap,
hints: &DecodingHintDictionary,
results: &mut Vec<RXingResult>,
xOffset: u32,
@@ -110,7 +110,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
let mut minY: f32 = height as f32;
let mut maxX: f32 = 0.0;
let mut maxY: f32 = 0.0;
for point in resultPoints {
for point in &resultPoints {
// if (point == null) {
// continue;
// }
@@ -133,7 +133,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
// Decode left of barcode
if minX > Self::MIN_DIMENSION_TO_RECUR {
self.doDecodeMultiple(
&image.crop(0, 0, minX as usize, height),
&mut image.crop(0, 0, minX as usize, height),
hints,
results,
xOffset,
@@ -144,7 +144,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
// Decode above barcode
if minY > Self::MIN_DIMENSION_TO_RECUR {
self.doDecodeMultiple(
&image.crop(0, 0, width, minY as usize),
&mut image.crop(0, 0, width, minY as usize),
hints,
results,
xOffset,
@@ -155,7 +155,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
// Decode right of barcode
if maxX < (width as f32) - Self::MIN_DIMENSION_TO_RECUR {
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,
results,
xOffset + maxX as u32,
@@ -166,7 +166,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
// Decode below barcode
if maxY < (height as f32) - Self::MIN_DIMENSION_TO_RECUR {
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,
results,
xOffset,

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
use std::{collections::HashSet, path::PathBuf, rc::Rc};
use std::{cell::RefCell, collections::HashSet, path::PathBuf, rc::Rc};
use crate::{
common::HybridBinarizer, BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
@@ -38,10 +38,14 @@ fn testMulti() {
.decode()
.expect("must decode");
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 results = reader.decode_multiple(&bitmap).expect("must decode multi");
let results = reader
.decode_multiple(&mut bitmap)
.expect("must decode multi");
// assertNotNull(results);
assert_eq!(2, results.len());
@@ -63,10 +67,14 @@ fn testMultiQR() {
.decode()
.expect("must decode");
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 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());
let mut barcodeContents = HashSet::new();

View File

@@ -23,11 +23,12 @@ use crate::{BinaryBitmap, DecodingHintDictionary, Exceptions, RXingResult};
* @author Sean Owen
*/
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(
&mut self,
image: &BinaryBitmap,
image: &mut BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<Vec<RXingResult>, Exceptions>;
}

View File

@@ -38,14 +38,14 @@ pub struct QRCodeMultiReader(QRCodeReader);
impl MultipleBarcodeReader for QRCodeMultiReader {
fn decode_multiple(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
self.decode_multiple_with_hints(image, &HashMap::new())
}
fn decode_multiple_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
let mut results = Vec::new();
@@ -221,7 +221,7 @@ mod multi_qr_code_test_case {
* limitations under the License.
*/
use std::{collections::HashSet, path::PathBuf, rc::Rc};
use std::{cell::RefCell, collections::HashSet, path::PathBuf, rc::Rc};
use image;
@@ -249,10 +249,12 @@ mod multi_qr_code_test_case {
.decode()
.expect("must decode");
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 results = reader.decode_multiple(&bitmap).expect("must decode");
let results = reader.decode_multiple(&mut bitmap).expect("must decode");
// assertNotNull(results);
assert_eq!(4, results.len());

View File

@@ -48,7 +48,7 @@ impl Reader for MultiFormatReader {
*/
fn decode(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.set_ints(&HashMap::new());
self.decode_internal(image)
@@ -64,7 +64,7 @@ impl Reader for MultiFormatReader {
*/
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.set_ints(hints);
@@ -89,7 +89,10 @@ impl MultiFormatReader {
* @return The contents of the image
* @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
if self.readers.is_empty() {
self.set_ints(&HashMap::new());
@@ -166,7 +169,7 @@ impl MultiFormatReader {
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() {
for reader in self.readers.iter_mut() {
// I'm not sure how to model this in rust
@@ -184,13 +187,13 @@ impl MultiFormatReader {
}
if self.hints.contains_key(&DecodeHintType::ALSO_INVERTED) {
// Calling all readers again with inverted image
let mut image = image.clone();
// let mut image = image.clone();
image.getBlackMatrixMut().flip_self();
for reader in self.readers.iter_mut() {
// if (Thread.currentThread().isInterrupted()) {
// 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() {
return res;
}

View File

@@ -37,7 +37,7 @@ use std::collections::HashMap;
use lazy_static::lazy_static;
use crate::{
common::{BitArray, BitMatrix, BitMatrixTestCase},
common::{BitMatrix, BitMatrixTestCase},
oned::{Code128Reader, OneDReader},
BarcodeFormat, EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions, Writer,
};
@@ -483,18 +483,18 @@ fn encode(toEncode: &str, compact: bool, expectedLoopback: &str) -> Result<BitMa
let encRXingResult =
WRITER.encode_with_hints(toEncode, &BarcodeFormat::CODE_128, 0, 0, &hints)?;
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 actual = rtRXingResult.getText();
assert_eq!(expectedLoopback, actual);
}
if compact {
//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 actual = rtRXingResult.getText();
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())?;
assert_eq!(rtRXingResult.getText(), actual);
}

View File

@@ -392,7 +392,7 @@ mod code_39_extended_mode_test_case {
use std::collections::HashMap;
use crate::{
common::{BitArray, BitMatrix},
common::BitMatrix,
oned::{Code39Reader, OneDReader},
};
#[test]
@@ -412,8 +412,8 @@ mod code_39_extended_mode_test_case {
let mut sut = Code39Reader::with_all_config(false, true);
let matrix =
BitMatrix::parse_strings(encodedRXingResult, "1", "0").expect("bitmatrix parse");
let row = BitArray::with_size(matrix.getWidth() as usize);
let row = matrix.getRow(0, row);
// let row = BitArray::with_size(matrix.getWidth() as usize);
let row = matrix.getRow(0);
let result = sut.decodeRow(0, &row, &HashMap::new()).expect("decode row");
assert_eq!(expectedRXingResult, result.getText());
}

View File

@@ -350,10 +350,7 @@ impl Code93Reader {
mod Code93ReaderTestCase {
use std::collections::HashMap;
use crate::{
common::{BitArray, BitMatrix},
oned::OneDReader,
};
use crate::{common::BitMatrix, oned::OneDReader};
use super::Code93Reader;
@@ -366,8 +363,8 @@ mod Code93ReaderTestCase {
fn doTest(expectedRXingResult: &str, encodedRXingResult: &str) {
let mut sut = Code93Reader::new();
let matrix = BitMatrix::parse_strings(encodedRXingResult, "1", "0").expect("must parse");
let mut row = BitArray::with_size(matrix.getWidth() as usize);
row = matrix.getRow(0, row);
// let mut row = BitArray::with_size(matrix.getWidth() as usize);
let row = matrix.getRow(0);
let result = sut
.decodeRow(0, &row, &HashMap::new())
.expect("must decode");

View File

@@ -120,14 +120,17 @@ use crate::Reader;
use std::collections::HashMap;
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())
}
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<crate::RXingResult, Exceptions> {
if let Ok(res) = self.doDecode(image, hints) {
@@ -135,8 +138,8 @@ impl Reader for MultiFormatOneDReader {
} else {
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
if tryHarder && image.isRotateSupported() {
let rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&rotatedImage, hints)?;
let mut rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&mut rotatedImage, hints)?;
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
let metadata = result.getRXingResultMetadata();
let mut orientation = 270;

View File

@@ -147,14 +147,17 @@ use crate::RXingResultPoint;
use std::collections::HashMap;
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())
}
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<crate::RXingResult, Exceptions> {
if let Ok(res) = self.doDecode(image, hints) {
@@ -162,8 +165,8 @@ impl Reader for MultiFormatUPCEANReader {
} else {
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
if tryHarder && image.isRotateSupported() {
let rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&rotatedImage, hints)?;
let mut rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&mut rotatedImage, hints)?;
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
let metadata = result.getRXingResultMetadata();
let mut orientation = 270;

View File

@@ -44,13 +44,13 @@ pub trait OneDReader: Reader {
*/
fn doDecode(
&mut self,
image: &BinaryBitmap,
image: &mut BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<RXingResult, Exceptions> {
let mut hints = hints.clone();
let width = image.getWidth();
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 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:
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
} else {
continue;

View File

@@ -24,16 +24,15 @@
* 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 Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
use crate::{
common::{BitArray, GlobalHistogramBinarizer},
oned::rss::expanded::RSSExpandedReader,
BinaryBitmap, BufferedImageLuminanceSource,
common::GlobalHistogramBinarizer, oned::rss::expanded::RSSExpandedReader, BinaryBitmap,
BufferedImageLuminanceSource,
};
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 image = image::open(path).expect("file exists");
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(image),
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(image)),
))));
let rowNumber = binaryMap.getHeight() / 2;
let row = binaryMap
.getBlackRow(rowNumber, &mut BitArray::new())
.expect("row");
let row = binaryMap.getBlackRow(rowNumber).expect("row");
// let pairs = Vec::new();
// try {

View File

@@ -29,11 +29,11 @@
*
*/
use std::{collections::HashMap, rc::Rc};
use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::{
client::result::{ExpandedProductParsedRXingResult, ParsedClientResult},
common::{BitArray, GlobalHistogramBinarizer},
common::GlobalHistogramBinarizer,
oned::{rss::expanded::RSSExpandedReader, OneDReader},
BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
};
@@ -71,13 +71,11 @@ fn assertCorrectImage2result(fileName: &str, expected: ExpandedProductParsedRXin
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
let image = image::open(path).expect("image must exist");
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(image),
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(image)),
))));
let rowNumber = binaryMap.getHeight() as usize / 2;
let row = binaryMap
.getBlackRow(rowNumber, &mut BitArray::new())
.expect("get row");
let row = binaryMap.getBlackRow(rowNumber).expect("get row");
let mut rssExpandedReader = RSSExpandedReader::new();
let theRXingResult = rssExpandedReader

View File

@@ -24,10 +24,10 @@
* http://www.piramidepse.com/
*/
use std::{collections::HashMap, rc::Rc};
use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::{
common::{BitArray, GlobalHistogramBinarizer},
common::GlobalHistogramBinarizer,
oned::{rss::expanded::RSSExpandedReader, OneDReader},
BarcodeFormat, BinaryBitmap, BufferedImageLuminanceSource,
};
@@ -184,13 +184,11 @@ fn assertCorrectImage2string(fileName: &str, expected: &str) {
let path = format!("test_resources/blackbox/rssexpanded-1/{}", fileName);
let image = image::open(path).expect("load image");
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(image),
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(image)),
))));
let rowNumber = binaryMap.getHeight() / 2;
let row = binaryMap
.getBlackRow(rowNumber, &mut BitArray::new())
.expect("get row");
let row = binaryMap.getBlackRow(rowNumber).expect("get row");
let mut rssExpandedReader = RSSExpandedReader::new();
let result = rssExpandedReader

View File

@@ -24,10 +24,10 @@
* http://www.piramidepse.com/
*/
use std::rc::Rc;
use std::{cell::RefCell, rc::Rc};
use crate::{
common::{BitArray, GlobalHistogramBinarizer},
common::GlobalHistogramBinarizer,
oned::rss::{DataCharacterTrait, FinderPattern},
BinaryBitmap, BufferedImageLuminanceSource,
};
@@ -42,13 +42,11 @@ use super::RSSExpandedReader;
#[test]
fn testFindFinderPatterns() {
let image = readImage("2.png");
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(image),
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(image)),
))));
let rowNumber = binaryMap.getHeight() as u32 / 2;
let row = binaryMap
.getBlackRow(rowNumber as usize, &mut BitArray::new())
.expect("ok");
let row = binaryMap.getBlackRow(rowNumber as usize).expect("ok");
let mut previousPairs = Vec::new(); //new ArrayList<>();
let mut rssExpandedReader = RSSExpandedReader::new();
@@ -90,13 +88,11 @@ fn testFindFinderPatterns() {
#[test]
fn testRetrieveNextPairPatterns() {
let image = readImage("3.png");
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(image),
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(image)),
))));
let rowNumber = binaryMap.getHeight() as u32 / 2;
let row = binaryMap
.getBlackRow(rowNumber as usize, &mut BitArray::new())
.expect("create");
let row = binaryMap.getBlackRow(rowNumber as usize).expect("create");
let mut previousPairs = Vec::new(); //new ArrayList<>();
let mut rssExpandedReader = RSSExpandedReader::new();
@@ -120,11 +116,11 @@ fn testRetrieveNextPairPatterns() {
#[test]
fn testDecodeCheckCharacter() {
let image = readImage("3.png");
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(image.clone()),
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(image.clone())),
))));
let row = binaryMap
.getBlackRow(binaryMap.getHeight() / 2, &mut BitArray::new())
.getBlackRow(binaryMap.getHeight() / 2)
.expect("create");
let startEnd = [145, 243]; //image pixels where the A1 pattern starts (at 124) and ends (at 214)
@@ -148,11 +144,11 @@ fn testDecodeCheckCharacter() {
#[test]
fn testDecodeDataCharacter() {
let image = readImage("3.png");
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(image.clone()),
let mut binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(image.clone())),
))));
let row = binaryMap
.getBlackRow(binaryMap.getHeight() / 2, &mut BitArray::new())
.getBlackRow(binaryMap.getHeight() / 2)
.expect("create");
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 {
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())
}
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<crate::RXingResult, Exceptions> {
if let Ok(res) = self.doDecode(image, hints) {
@@ -194,8 +197,8 @@ impl Reader for RSSExpandedReader {
} else {
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
if tryHarder && image.isRotateSupported() {
let rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&rotatedImage, hints)?;
let mut rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&mut rotatedImage, hints)?;
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
let metadata = result.getRXingResultMetadata();
let mut orientation = 270;

View File

@@ -24,7 +24,7 @@
* 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};
@@ -36,12 +36,10 @@ use super::{test_case_util, RSSExpandedReader};
fn testDecodingRowByRow() {
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 firstRow = binaryMap
.getBlackRow(firstRowNumber, &mut BitArray::new())
.expect("get row");
let firstRow = binaryMap.getBlackRow(firstRowNumber).expect("get row");
// let tester = ;
@@ -74,9 +72,7 @@ fn testDecodingRowByRow() {
.getStartEndMut()[1] = 0;
let secondRowNumber = 2 * binaryMap.getHeight() / 3;
let mut secondRow = binaryMap
.getBlackRow(secondRowNumber, &mut BitArray::new())
.expect("get row");
let mut secondRow = binaryMap.getBlackRow(secondRowNumber).expect("get row");
secondRow.reverse();
let totalPairs = rssExpandedReader
@@ -91,8 +87,8 @@ fn testDecodingRowByRow() {
fn testCompleteDecode() {
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());
}

View File

@@ -24,7 +24,7 @@
* http://www.piramidepse.com/
*/
use std::rc::Rc;
use std::{cell::RefCell, rc::Rc};
use image::DynamicImage;
@@ -40,8 +40,8 @@ fn getBufferedImage(fileName: &str) -> DynamicImage {
pub(crate) fn getBinaryBitmap(fileName: &str) -> BinaryBitmap {
let bufferedImage = getBufferedImage(fileName);
let binaryMap = BinaryBitmap::new(Rc::new(GlobalHistogramBinarizer::new(Box::new(
BufferedImageLuminanceSource::new(bufferedImage),
let binaryMap = BinaryBitmap::new(Rc::new(RefCell::new(GlobalHistogramBinarizer::new(
Box::new(BufferedImageLuminanceSource::new(bufferedImage)),
))));
binaryMap

View File

@@ -72,14 +72,17 @@ impl OneDReader 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())
}
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<crate::RXingResult, Exceptions> {
if let Ok(res) = self.doDecode(image, hints) {
@@ -87,8 +90,8 @@ impl Reader for RSS14Reader {
} else {
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
if tryHarder && image.isRotateSupported() {
let rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&rotatedImage, hints)?;
let mut rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&mut rotatedImage, hints)?;
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
let metadata = result.getRXingResultMetadata();
let mut orientation = 270;

View File

@@ -27,13 +27,16 @@ use super::{EAN13Reader, OneDReader, UPCEANReader};
pub struct UPCAReader(EAN13Reader);
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)?)
}
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, Exceptions> {
Self::maybeReturnRXingResult(self.0.decode_with_hints(image, hints)?)

View File

@@ -551,13 +551,13 @@ impl OneDReader 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!()
}
fn decode_with_hints(
&mut self,
_image: &crate::BinaryBitmap,
_image: &mut crate::BinaryBitmap,
_hints: &crate::DecodingHintDictionary,
) -> Result<RXingResult, Exceptions> {
todo!()

View File

@@ -63,7 +63,7 @@ const ROTATIONS: [u32; 4] = [0, 180, 270, 90];
* @throws NotFoundException if no PDF417 Code can be found
*/
pub fn detect_with_hints(
image: &BinaryBitmap,
image: &mut BinaryBitmap,
_hints: &DecodingHintDictionary,
multiple: bool,
) -> Result<PDF417DetectorRXingResult, Exceptions> {

View File

@@ -44,14 +44,14 @@ impl Reader for PDF417Reader {
*/
fn decode(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.decode_with_hints(image, &HashMap::new())
}
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
let result = Self::decode(image, hints, false)?;
@@ -65,14 +65,14 @@ impl Reader for PDF417Reader {
impl MultipleBarcodeReader for PDF417Reader {
fn decode_multiple(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
self.decode_multiple_with_hints(image, &HashMap::new())
}
fn decode_multiple_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
//try {
@@ -95,7 +95,7 @@ impl PDF417Reader {
}
fn decode(
image: &BinaryBitmap,
image: &mut BinaryBitmap,
hints: &DecodingHintDictionary,
multiple: bool,
) -> Result<Vec<RXingResult>, Exceptions> {

View File

@@ -248,7 +248,7 @@ impl 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() {
//throw new IllegalArgumentException("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 mut row = if row.len() >= width {
row.to_vec()
} else {
vec![0; width]
};
let mut row = vec![0; width];
row[..width].clone_from_slice(&self.yuv_data[offset..width + offset]);
//System.arraycopy(yuvData, offset, row, 0, width);

View File

@@ -49,14 +49,14 @@ impl Reader for QRCodeReader {
*/
fn decode(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.decode_with_hints(image, &HashMap::new())
}
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
image: &mut crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
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 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
@@ -58,7 +58,7 @@ pub trait Reader {
*/
fn decode_with_hints(
&mut self,
image: &BinaryBitmap,
image: &mut BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<RXingResult, Exceptions>;

View File

@@ -38,7 +38,7 @@ pub struct 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() {
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 mut row = if row.len() >= width {
row.to_vec()
} else {
vec![0; width]
};
let mut row = vec![0; width];
row[..width].clone_from_slice(&self.luminances[offset..offset + width]);
//System.arraycopy(self.luminances, offset, row, 0, width);