diff --git a/Cargo.toml b/Cargo.toml index 44c79c9..5d01f53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rxing" -version = "0.1.4" +version = "0.2.0" description="A rust port of the zxing barcode library." license="Apache-2.0" repository="https://github.com/hschimke/rxing" @@ -26,7 +26,8 @@ image = {version = "0.24", optional = true} imageproc = {version = "0.23.0", optional = true} unicode-segmentation = "1.10.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" [dev-dependencies] diff --git a/README.md b/README.md index 826290b..2dd1461 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ used to enable the use of the `image` crate is currently on by default. Turning ## Example ``` -use std::{collections::HashMap, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; use rxing::multi::MultipleBarcodeReader; @@ -46,21 +46,38 @@ fn main() { let file_name = "test_image.jpeg"; 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 mut scanner = rxing::multi::GenericMultipleBarcodeReader::new(multi_format_reader); - let results = scanner.decode_multiple_with_hints( - &rxing::BinaryBitmap::new(Rc::new(rxing::common::HybridBinarizer::new(Box::new( - rxing::BufferedImageLuminanceSource::new(img), - )))), - &HashMap::new(), - ).expect("decodes"); + let results = scanner + .decode_multiple_with_hints( + &mut rxing::BinaryBitmap::new(Rc::new(RefCell::new( + rxing::common::HybridBinarizer::new(Box::new( + rxing::BufferedImageLuminanceSource::new(img), + )), + ))), + &hints, + ) + .expect("decodes"); for result in results { - println!("{} -> {}",result.getBarcodeFormat(), result.getText()) + println!("{} -> {}", result.getBarcodeFormat(), result.getText()) } } + ``` ## Latest Release Notes -v0.1.4 -> Dramatically improve performance for MultiFormatReader and for multiple barcode detection. \ No newline at end of file +v0.2.0 -> Dramatically improve performance when cropping a BufferedImageLuminanceSource. + +v0.1.4 -> Dramatically improve performance for MultiFormatReader and for multiple barcode detection. + +## Known Issues +Performance is low for GenericMultipleBarcodeReader. \ No newline at end of file diff --git a/src/PlanarYUVLuminanceSourceTestCase.rs b/src/PlanarYUVLuminanceSourceTestCase.rs index 158a84d..e21b5a5 100644 --- a/src/PlanarYUVLuminanceSourceTestCase.rs +++ b/src/PlanarYUVLuminanceSourceTestCase.rs @@ -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); } } diff --git a/src/RGBLuminanceSourceTestCase.rs b/src/RGBLuminanceSourceTestCase.rs index bbdfb3e..d2f915a 100644 --- a/src/RGBLuminanceSourceTestCase.rs +++ b/src/RGBLuminanceSourceTestCase.rs @@ -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] diff --git a/src/aztec/aztec_reader.rs b/src/aztec/aztec_reader.rs index 9faad3f..8790b8e 100644 --- a/src/aztec/aztec_reader.rs +++ b/src/aztec/aztec_reader.rs @@ -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 { + fn decode(&mut self, image: &mut BinaryBitmap) -> Result { self.decode_with_hints(image, &HashMap::new()) } fn decode_with_hints( &mut self, - image: &BinaryBitmap, + image: &mut BinaryBitmap, hints: &HashMap, ) -> Result { // let notFoundException = None; diff --git a/src/binarizer.rs b/src/binarizer.rs index 93ccd6a..eb3cb47 100644 --- a/src/binarizer.rs +++ b/src/binarizer.rs @@ -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; + fn getBlackRow(&mut self, y: usize) -> Result; /** * 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; + 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) -> Rc; + fn createBinarizer(&self, source: Box) -> Rc>; fn getWidth(&self) -> usize; diff --git a/src/binary_bitmap.rs b/src/binary_bitmap.rs index 5d0f293..409e10b 100644 --- a/src/binary_bitmap.rs +++ b/src/binary_bitmap.rs @@ -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, - matrix: BitMatrix, + binarizer: Rc>, + matrix: Option, } impl BinaryBitmap { - pub fn new(binarizer: Rc) -> Self { + pub fn new(binarizer: Rc>) -> 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 { - return self.binarizer.getBlackRow(y, row); + pub fn getBlackRow(&mut self, y: usize) -> Result { + 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) } } diff --git a/src/buffered_image_luminance_source.rs b/src/buffered_image_luminance_source.rs index c2efa6b..53f81ee 100644 --- a/src/buffered_image_luminance_source.rs +++ b/src/buffered_image_luminance_source.rs @@ -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, width: usize, height: usize, left: u32, @@ -151,7 +146,7 @@ impl BufferedImageLuminanceSource { // let ib:ImageBuffer, Vec> = 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) -> Vec { - let width = self.getWidth(); - - let mut row = if row.len() >= width { - row.to_vec() - } else { - vec![0; width] - }; + fn getRow(&self, y: usize) -> Vec { + let width = self.getWidth(); // - self.left as usize; let pixels: Vec = 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 { - 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::>(); // 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, })) diff --git a/src/common/BitMatrixTestCase.rs b/src/common/BitMatrixTestCase.rs index 969bb73..aa4f4f9 100644 --- a/src/common/BitMatrixTestCase.rs +++ b/src/common/BitMatrixTestCase.rs @@ -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 { diff --git a/src/common/bit_array.rs b/src/common/bit_array.rs index f478a72..ffa4c64 100644 --- a/src/common/bit_array.rs +++ b/src/common/bit_array.rs @@ -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 } /** diff --git a/src/common/bit_matrix.rs b/src/common/bit_matrix.rs index 754a06e..5e917a2 100644 --- a/src/common/bit_matrix.rs +++ b/src/common/bit_matrix.rs @@ -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::>(); + // let new_bits = area.chunks(self.row_size) + // .skip(left).take(width).flatten().copied().collect::>(); + // 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 { diff --git a/src/common/global_histogram_binarizer.rs b/src/common/global_histogram_binarizer.rs index 1a78afa..f737121 100644 --- a/src/common/global_histogram_binarizer.rs +++ b/src/common/global_histogram_binarizer.rs @@ -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, - buckets: Vec, + _luminances: Vec, width: usize, height: usize, source: Box, + black_matrix: Option, + black_row_cache: Vec>, } 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 { + fn getBlackRow(&mut self, y: usize) -> Result { + 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 { - 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, + ) -> Rc> { + 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) -> 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) -> Result { + // 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) -> Rc { - 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) -> 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 { + fn estimateBlackPoint(buckets: &[u32]) -> Result { // Find the tallest peak in the histogram. let numBuckets = buckets.len(); let mut maxBucketCount = 0; diff --git a/src/common/hybrid_binarizer.rs b/src/common/hybrid_binarizer.rs index 93accce..7322f5a 100644 --- a/src/common/hybrid_binarizer.rs +++ b/src/common/hybrid_binarizer.rs @@ -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, ghb: GlobalHistogramBinarizer, - // matrix :Option, + black_matrix: Option, } impl Binarizer for HybridBinarizer { fn getLuminanceSource(&self) -> &Box { self.ghb.getLuminanceSource() } - fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result { - self.ghb.getBlackRow(y, row) + fn getBlackRow(&mut self, y: usize) -> Result { + 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 { - // 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) -> Rc> { + 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) -> Self { + let ghb = GlobalHistogramBinarizer::new(source); + Self { + black_matrix: None, + ghb: ghb, + } + } + + fn calculateBlackMatrix(ghb: &mut GlobalHistogramBinarizer) -> Result { 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) -> Rc { - 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) -> Self { - Self { - ghb: GlobalHistogramBinarizer::new(source), - // matrix: None, - } + matrix } /** diff --git a/src/datamatrix/data_matrix_reader.rs b/src/datamatrix/data_matrix_reader.rs index 1d66beb..10028eb 100644 --- a/src/datamatrix/data_matrix_reader.rs +++ b/src/datamatrix/data_matrix_reader.rs @@ -52,7 +52,7 @@ impl Reader for DataMatrixReader { */ fn decode( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, ) -> Result { 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 { let decoderRXingResult; diff --git a/src/luminance_source.rs b/src/luminance_source.rs index cc59eab..2ca9d60 100644 --- a/src/luminance_source.rs +++ b/src/luminance_source.rs @@ -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) -> Vec; + fn getRow(&self, y: usize) -> Vec; /** * Fetches luminance data for the underlying bitmap. Values should be fetched using: diff --git a/src/maxicode/maxi_code_reader.rs b/src/maxicode/maxi_code_reader.rs index 3142093..43022dc 100644 --- a/src/maxicode/maxi_code_reader.rs +++ b/src/maxicode/maxi_code_reader.rs @@ -40,7 +40,7 @@ impl Reader for MaxiCodeReader { */ fn decode( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, ) -> Result { 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 { // Note that MaxiCode reader effectively always assumes PURE_BARCODE mode diff --git a/src/multi/by_quadrant_reader.rs b/src/multi/by_quadrant_reader.rs index 36ad36d..89586a4 100644 --- a/src/multi/by_quadrant_reader.rs +++ b/src/multi/by_quadrant_reader.rs @@ -31,14 +31,14 @@ pub struct ByQuadrantReader(T); impl Reader for ByQuadrantReader { fn decode( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, ) -> Result { self.decode_with_hints(image, &HashMap::new()) } fn decode_with_hints( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, hints: &crate::DecodingHintDictionary, ) -> Result { let width = image.getWidth(); @@ -49,7 +49,7 @@ impl Reader for ByQuadrantReader { // 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 Reader for ByQuadrantReader { // 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 Reader for ByQuadrantReader { 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 Reader for ByQuadrantReader { // } 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 Reader for ByQuadrantReader { let quarterWidth = halfWidth / 2; let quarterHeight = halfHeight / 2; - let center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight); - let result = self.0.decode_with_hints(¢er, 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(), diff --git a/src/multi/generic_multiple_barcode_reader.rs b/src/multi/generic_multiple_barcode_reader.rs index acde7fa..405c38f 100644 --- a/src/multi/generic_multiple_barcode_reader.rs +++ b/src/multi/generic_multiple_barcode_reader.rs @@ -42,14 +42,14 @@ pub struct GenericMultipleBarcodeReader(T); impl MultipleBarcodeReader for GenericMultipleBarcodeReader { fn decode_multiple( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, ) -> Result, 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, crate::Exceptions> { let mut results = Vec::new(); @@ -70,7 +70,7 @@ impl GenericMultipleBarcodeReader { fn doDecodeMultiple( &mut self, - image: &BinaryBitmap, + image: &mut BinaryBitmap, hints: &DecodingHintDictionary, results: &mut Vec, xOffset: u32, @@ -110,7 +110,7 @@ impl GenericMultipleBarcodeReader { 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 GenericMultipleBarcodeReader { // 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 GenericMultipleBarcodeReader { // 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 GenericMultipleBarcodeReader { // 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 GenericMultipleBarcodeReader { // 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, diff --git a/src/multi/multi_test_case.rs b/src/multi/multi_test_case.rs index 7db76df..b743c40 100644 --- a/src/multi/multi_test_case.rs +++ b/src/multi/multi_test_case.rs @@ -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(); diff --git a/src/multi/multiple_barcode_reader.rs b/src/multi/multiple_barcode_reader.rs index fa567fd..12fecfc 100644 --- a/src/multi/multiple_barcode_reader.rs +++ b/src/multi/multiple_barcode_reader.rs @@ -23,11 +23,12 @@ use crate::{BinaryBitmap, DecodingHintDictionary, Exceptions, RXingResult}; * @author Sean Owen */ pub trait MultipleBarcodeReader { - fn decode_multiple(&mut self, image: &BinaryBitmap) -> Result, Exceptions>; + fn decode_multiple(&mut self, image: &mut BinaryBitmap) + -> Result, Exceptions>; fn decode_multiple_with_hints( &mut self, - image: &BinaryBitmap, + image: &mut BinaryBitmap, hints: &DecodingHintDictionary, ) -> Result, Exceptions>; } diff --git a/src/multi/qrcode/qr_code_multi_reader.rs b/src/multi/qrcode/qr_code_multi_reader.rs index ca9bfdb..3c97054 100644 --- a/src/multi/qrcode/qr_code_multi_reader.rs +++ b/src/multi/qrcode/qr_code_multi_reader.rs @@ -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, 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, 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()); diff --git a/src/multi_format_reader.rs b/src/multi_format_reader.rs index a851392..f8c2cfb 100644 --- a/src/multi_format_reader.rs +++ b/src/multi_format_reader.rs @@ -48,7 +48,7 @@ impl Reader for MultiFormatReader { */ fn decode( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, ) -> Result { 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 { 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 { + pub fn decode_with_state( + &mut self, + image: &mut BinaryBitmap, + ) -> Result { // 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 { + pub fn decode_internal(&mut self, image: &mut BinaryBitmap) -> Result { 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; } diff --git a/src/oned/code_128_writer_test_tase.rs b/src/oned/code_128_writer_test_tase.rs index 25b8b9d..6fc671a 100644 --- a/src/oned/code_128_writer_test_tase.rs +++ b/src/oned/code_128_writer_test_tase.rs @@ -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 Result { + fn decode( + &mut self, + image: &mut crate::BinaryBitmap, + ) -> Result { 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 { 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; diff --git a/src/oned/multi_format_upc_ean_reader.rs b/src/oned/multi_format_upc_ean_reader.rs index 2557dd3..5b196c5 100644 --- a/src/oned/multi_format_upc_ean_reader.rs +++ b/src/oned/multi_format_upc_ean_reader.rs @@ -147,14 +147,17 @@ use crate::RXingResultPoint; use std::collections::HashMap; impl Reader for MultiFormatUPCEANReader { - fn decode(&mut self, image: &crate::BinaryBitmap) -> Result { + fn decode( + &mut self, + image: &mut crate::BinaryBitmap, + ) -> Result { 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 { 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; diff --git a/src/oned/one_d_reader.rs b/src/oned/one_d_reader.rs index 80f43c7..b8939cc 100644 --- a/src/oned/one_d_reader.rs +++ b/src/oned/one_d_reader.rs @@ -44,13 +44,13 @@ pub trait OneDReader: Reader { */ fn doDecode( &mut self, - image: &BinaryBitmap, + image: &mut BinaryBitmap, hints: &DecodingHintDictionary, ) -> Result { 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; diff --git a/src/oned/rss/expanded/rss_expanded_image_2_binary_test_tase.rs b/src/oned/rss/expanded/rss_expanded_image_2_binary_test_tase.rs index 3bc9cbf..2739e86 100644 --- a/src/oned/rss/expanded/rss_expanded_image_2_binary_test_tase.rs +++ b/src/oned/rss/expanded/rss_expanded_image_2_binary_test_tase.rs @@ -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 { diff --git a/src/oned/rss/expanded/rss_expanded_image_2_result_test_case.rs b/src/oned/rss/expanded/rss_expanded_image_2_result_test_case.rs index 31fa2ff..0273f9f 100644 --- a/src/oned/rss/expanded/rss_expanded_image_2_result_test_case.rs +++ b/src/oned/rss/expanded/rss_expanded_image_2_result_test_case.rs @@ -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 diff --git a/src/oned/rss/expanded/rss_expanded_image_2_string_test_case.rs b/src/oned/rss/expanded/rss_expanded_image_2_string_test_case.rs index 64c331e..d3736f0 100644 --- a/src/oned/rss/expanded/rss_expanded_image_2_string_test_case.rs +++ b/src/oned/rss/expanded/rss_expanded_image_2_string_test_case.rs @@ -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 diff --git a/src/oned/rss/expanded/rss_expanded_internal_test_case.rs b/src/oned/rss/expanded/rss_expanded_internal_test_case.rs index cf16149..0691800 100644 --- a/src/oned/rss/expanded/rss_expanded_internal_test_case.rs +++ b/src/oned/rss/expanded/rss_expanded_internal_test_case.rs @@ -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) diff --git a/src/oned/rss/expanded/rss_expanded_reader.rs b/src/oned/rss/expanded/rss_expanded_reader.rs index c7bf68a..0379316 100644 --- a/src/oned/rss/expanded/rss_expanded_reader.rs +++ b/src/oned/rss/expanded/rss_expanded_reader.rs @@ -179,14 +179,17 @@ impl OneDReader for RSSExpandedReader { } } impl Reader for RSSExpandedReader { - fn decode(&mut self, image: &crate::BinaryBitmap) -> Result { + fn decode( + &mut self, + image: &mut crate::BinaryBitmap, + ) -> Result { 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 { 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; diff --git a/src/oned/rss/expanded/rss_expanded_stacked_internal_test_case.rs b/src/oned/rss/expanded/rss_expanded_stacked_internal_test_case.rs index cf2f1ec..c26d705 100644 --- a/src/oned/rss/expanded/rss_expanded_stacked_internal_test_case.rs +++ b/src/oned/rss/expanded/rss_expanded_stacked_internal_test_case.rs @@ -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()); } diff --git a/src/oned/rss/expanded/test_case_util.rs b/src/oned/rss/expanded/test_case_util.rs index c844d0d..ad5a830 100644 --- a/src/oned/rss/expanded/test_case_util.rs +++ b/src/oned/rss/expanded/test_case_util.rs @@ -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 diff --git a/src/oned/rss/rss_14_reader.rs b/src/oned/rss/rss_14_reader.rs index 760b5c7..27a2186 100644 --- a/src/oned/rss/rss_14_reader.rs +++ b/src/oned/rss/rss_14_reader.rs @@ -72,14 +72,17 @@ impl OneDReader for RSS14Reader { } } impl Reader for RSS14Reader { - fn decode(&mut self, image: &crate::BinaryBitmap) -> Result { + fn decode( + &mut self, + image: &mut crate::BinaryBitmap, + ) -> Result { 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 { 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; diff --git a/src/oned/upc_a_reader.rs b/src/oned/upc_a_reader.rs index f70cd7a..49a9b26 100644 --- a/src/oned/upc_a_reader.rs +++ b/src/oned/upc_a_reader.rs @@ -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 { + fn decode( + &mut self, + image: &mut crate::BinaryBitmap, + ) -> Result { Self::maybeReturnRXingResult(self.0.decode(image)?) } fn decode_with_hints( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, hints: &crate::DecodingHintDictionary, ) -> Result { Self::maybeReturnRXingResult(self.0.decode_with_hints(image, hints)?) diff --git a/src/oned/upc_ean_reader.rs b/src/oned/upc_ean_reader.rs index 5a1bdcc..425b516 100644 --- a/src/oned/upc_ean_reader.rs +++ b/src/oned/upc_ean_reader.rs @@ -551,13 +551,13 @@ impl OneDReader for StandInStruct { } impl Reader for StandInStruct { - fn decode(&mut self, _image: &crate::BinaryBitmap) -> Result { + fn decode(&mut self, _image: &mut crate::BinaryBitmap) -> Result { todo!() } fn decode_with_hints( &mut self, - _image: &crate::BinaryBitmap, + _image: &mut crate::BinaryBitmap, _hints: &crate::DecodingHintDictionary, ) -> Result { todo!() diff --git a/src/pdf417/detector/detector.rs b/src/pdf417/detector/detector.rs index 41bac2e..5377a1b 100644 --- a/src/pdf417/detector/detector.rs +++ b/src/pdf417/detector/detector.rs @@ -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 { diff --git a/src/pdf417/pdf_417_reader.rs b/src/pdf417/pdf_417_reader.rs index 08c7904..01675c5 100644 --- a/src/pdf417/pdf_417_reader.rs +++ b/src/pdf417/pdf_417_reader.rs @@ -44,14 +44,14 @@ impl Reader for PDF417Reader { */ fn decode( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, ) -> Result { self.decode_with_hints(image, &HashMap::new()) } fn decode_with_hints( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, hints: &crate::DecodingHintDictionary, ) -> Result { 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, 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, crate::Exceptions> { //try { @@ -95,7 +95,7 @@ impl PDF417Reader { } fn decode( - image: &BinaryBitmap, + image: &mut BinaryBitmap, hints: &DecodingHintDictionary, multiple: bool, ) -> Result, Exceptions> { diff --git a/src/planar_yuv_luminance_source.rs b/src/planar_yuv_luminance_source.rs index c2d5780..1593973 100644 --- a/src/planar_yuv_luminance_source.rs +++ b/src/planar_yuv_luminance_source.rs @@ -248,7 +248,7 @@ impl PlanarYUVLuminanceSource { } impl LuminanceSource for PlanarYUVLuminanceSource { - fn getRow(&self, y: usize, row: &Vec) -> Vec { + fn getRow(&self, y: usize) -> Vec { 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); diff --git a/src/qrcode/qr_code_reader.rs b/src/qrcode/qr_code_reader.rs index 4b9ce70..f20bf58 100644 --- a/src/qrcode/qr_code_reader.rs +++ b/src/qrcode/qr_code_reader.rs @@ -49,14 +49,14 @@ impl Reader for QRCodeReader { */ fn decode( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, ) -> Result { self.decode_with_hints(image, &HashMap::new()) } fn decode_with_hints( &mut self, - image: &crate::BinaryBitmap, + image: &mut crate::BinaryBitmap, hints: &crate::DecodingHintDictionary, ) -> Result { let decoderRXingResult: DecoderRXingResult; diff --git a/src/reader.rs b/src/reader.rs index 20e35fb..5224f9a 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -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; + fn decode(&mut self, image: &mut BinaryBitmap) -> Result; /** * 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; diff --git a/src/rgb_luminance_source.rs b/src/rgb_luminance_source.rs index 4f8ec20..2e88b8d 100644 --- a/src/rgb_luminance_source.rs +++ b/src/rgb_luminance_source.rs @@ -38,7 +38,7 @@ pub struct RGBLuminanceSource { } impl LuminanceSource for RGBLuminanceSource { - fn getRow(&self, y: usize, row: &Vec) -> Vec { + fn getRow(&self, y: usize) -> Vec { 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); diff --git a/tests/common/abstract_black_box_test_case.rs b/tests/common/abstract_black_box_test_case.rs index 72393d0..76498b8 100644 --- a/tests/common/abstract_black_box_test_case.rs +++ b/tests/common/abstract_black_box_test_case.rs @@ -16,6 +16,7 @@ */ use std::{ + cell::RefCell, collections::HashMap, fs::{read_dir, read_to_string, File}, io::Read, @@ -237,7 +238,9 @@ impl AbstractBlackBoxTestCase { let rotation = self.test_rxing_results.get(x).unwrap().get_rotation(); let rotated_image = Self::rotate_image(&image, rotation); 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" { // let mut f = File::create("test_file_output.txt").unwrap(); @@ -246,9 +249,13 @@ impl AbstractBlackBoxTestCase { // Self::rotate_image(&image, rotation).save("test_image.png").unwrap(); // } - if let Ok(decoded) = - self.decode(&bitmap, rotation, &expected_text, &expected_metadata, false) - { + if let Ok(decoded) = self.decode( + &mut bitmap, + rotation, + &expected_text, + &expected_metadata, + false, + ) { if decoded { passed_counts[x] += 1; } else { @@ -266,9 +273,13 @@ impl AbstractBlackBoxTestCase { // } catch (ReaderException ignored) { // log::fine(format!("could not read at rotation {}", rotation)); // } - if let Ok(decoded) = - self.decode(&bitmap, rotation, &expected_text, &expected_metadata, true) - { + if let Ok(decoded) = self.decode( + &mut bitmap, + rotation, + &expected_text, + &expected_metadata, + true, + ) { if decoded { try_harder_counts[x] += 1; } else { @@ -404,7 +415,7 @@ impl AbstractBlackBoxTestCase { fn decode( &mut self, - source: &BinaryBitmap, + source: &mut BinaryBitmap, rotation: f32, expected_text: &str, expected_metadata: &HashMap, diff --git a/tests/common/pdf_417_multiimage_span.rs b/tests/common/pdf_417_multiimage_span.rs index 9050efa..ff24e76 100644 --- a/tests/common/pdf_417_multiimage_span.rs +++ b/tests/common/pdf_417_multiimage_span.rs @@ -16,6 +16,7 @@ */ use std::{ + cell::RefCell, collections::HashMap, fs::{read_dir, read_to_string, File}, io::Read, @@ -178,9 +179,13 @@ impl PDF417MultiImageSpanAbstractBlackBoxTest let rotation: f32 = self.test_rxing_results.get(x).expect("ok").get_rotation(); let rotated_image = Self::rotate_image(&image, rotation); 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 { results.push(r); } @@ -383,7 +388,9 @@ impl PDF417MultiImageSpanAbstractBlackBoxTest let rotation = self.test_rxing_results.get(x).unwrap().get_rotation(); let rotated_image = Self::rotate_image(&image, rotation); 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" { // let mut f = File::create("test_file_output.txt").unwrap(); @@ -392,9 +399,13 @@ impl PDF417MultiImageSpanAbstractBlackBoxTest // Self::rotate_image(&image, rotation).save("test_image.png").unwrap(); // } - if let Ok(decoded) = - self.decode(&bitmap, rotation, &expected_text, &expected_metadata, false) - { + if let Ok(decoded) = self.decode( + &mut bitmap, + rotation, + &expected_text, + &expected_metadata, + false, + ) { if decoded { passed_counts[x] += 1; } else { @@ -412,9 +423,13 @@ impl PDF417MultiImageSpanAbstractBlackBoxTest // } catch (ReaderException ignored) { // log::fine(format!("could not read at rotation {}", rotation)); // } - if let Ok(decoded) = - self.decode(&bitmap, rotation, &expected_text, &expected_metadata, true) - { + if let Ok(decoded) = self.decode( + &mut bitmap, + rotation, + &expected_text, + &expected_metadata, + true, + ) { if decoded { try_harder_counts[x] += 1; } else { @@ -550,7 +565,7 @@ impl PDF417MultiImageSpanAbstractBlackBoxTest fn decode( &mut self, - source: &BinaryBitmap, + source: &mut BinaryBitmap, rotation: f32, expected_text: &str, expected_metadata: &HashMap, @@ -739,7 +754,7 @@ impl PDF417MultiImageSpanAbstractBlackBoxTest } fn decode_pdf417( - source: &BinaryBitmap, + source: &mut BinaryBitmap, try_harder: bool, barcode_reader: &mut T, ) -> Result, Exceptions> {