stage: moving performance enhancements into main

several incomplete features are gated behind the `experimental_features` flag.
This commit is contained in:
Henry Schimke
2024-02-07 13:22:07 -06:00
parent c554a469cd
commit 76e8998f4b
33 changed files with 684 additions and 548 deletions

View File

@@ -12,3 +12,6 @@ keywords = ["barcode", "2d_barcode", "1d_barcode", "barcode_reader", "barcode_wr
[dependencies]
clap = { version = "4.4.13", features = ["derive"] }
rxing = {path = "../../", version = "~0.5.7", features = ["image", "svg_read", "svg_write"] }
#[profile.release]
#debug = true

View File

@@ -66,6 +66,9 @@ impl BufferedImageLuminanceSource {
}
impl LuminanceSource for BufferedImageLuminanceSource {
const SUPPORTS_CROP: bool = true;
const SUPPORTS_ROTATION: bool = true;
fn get_row(&self, y: usize) -> Vec<u8> {
let width = self.get_width(); // - self.left as usize;
@@ -87,8 +90,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
}
fn get_column(&self, x: usize) -> Vec<u8> {
let width = self.get_height(); // - self.left as usize;
let pixels: Vec<u8> = || -> Option<Vec<u8>> {
Some(
self.image
@@ -153,10 +154,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
self.height
}
fn is_crop_supported(&self) -> bool {
true
}
fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> Result<Self> {
Ok(Self {
image: self.image.clone(),
@@ -167,10 +164,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
})
}
fn is_rotate_supported(&self) -> bool {
true
}
fn invert(&mut self) {
let mut img = (*self.image).clone();
img.invert();

View File

@@ -136,7 +136,7 @@ fn test_get_next_set5() {
#[test]
fn test_set_bulk() {
let mut array = BitArray::with_size(64);
array.setBulk(32, 0xFFFF0000);
array.setBulk(32, 0b11111111111111110000000000000000);
for i in 0..48 {
// for (int i = 0; i < 48; i++) {
assert!(!array.get(i));
@@ -150,7 +150,7 @@ fn test_set_bulk() {
#[test]
fn test_append_bit() {
let mut array = BitArray::new();
array.appendBits(0x000001E, 6).expect("must append)");
array.appendBits(0b11110, 6).expect("must append)");
let mut array_2 = BitArray::new();
array_2.appendBit(false);
array_2.appendBit(true);
@@ -159,7 +159,9 @@ fn test_append_bit() {
array_2.appendBit(true);
array_2.appendBit(false);
assert_eq!(array, array_2)
assert_eq!(array.get_size(), array_2.get_size());
assert_eq!(array.getBitArray(), array_2.getBitArray())
}
#[test]
@@ -234,18 +236,37 @@ fn test_is_range() {
#[test]
fn reverse_algorithm_test() {
let oldBits: Vec<u32> = vec![128, 256, 512, 6453324, 50934953];
let oldBits: Vec<super::BitFieldBaseType> = vec![128, 256, 512, 6453324, 50934953];
for size in 1..160 {
// for (int size = 1; size < 160; size++) {
let newBitsOriginal = reverse_original(&oldBits.clone(), size);
let mut newBitArray = BitArray::with_initial_values(oldBits.clone(), size);
newBitArray.reverse();
let newBitsNew = newBitArray.getBitArray();
assert!(arrays_are_equal(
&newBitsOriginal,
newBitsNew,
size / 32 + 1
));
assert!(
arrays_are_equal(&newBitsOriginal, newBitsNew, size / 32 + 1),
"size: ({}) : {:?}/{:?}",
size,
newBitsOriginal,
newBitsNew
);
}
}
#[test]
fn reverse_test_2() {
let initial_data: super::BitFieldBaseType = 0b00_00_11_00_00_00_00_00_00_00_00_00_00_00_00_00;
// let expected_data = vec![0b00_00_00_00_00_00_00_00_00_00_00_00_00_11_00_00_u32];
// let mut array = BitArray::with_initial_values(initial_data.clone(), 4);
for x in 1..=32 {
let expected_data = reverse_original(&[initial_data], x);
let mut array = BitArray::with_size(x);
array.setBulk(0, initial_data);
// dbg!(&array);
assert_eq!(&[initial_data], array.getBitArray());
array.reverse();
// dbg!(&array);
assert_eq!(expected_data, array.getBitArray(), "for x = {x}");
}
}
@@ -271,7 +292,48 @@ fn test_equals() {
// assert_eq!(a.hash(), b.hash());
}
fn reverse_original(oldBits: &[u32], size: usize) -> Vec<u32> {
#[test]
fn test_xor() {
let val_1: super::BitFieldBaseType = 0b01_00_11;
let val_2: super::BitFieldBaseType = 0b10_11_10;
let mut array_1 = BitArray::with_initial_values(vec![val_1], 32);
let array_2 = BitArray::with_initial_values(vec![val_2], 32);
array_1.xor(&array_2).expect("xor complete");
assert_eq!(array_1.getBitArray(), &[0b11_11_01]);
}
#[test]
fn test_xor_2() {
for i in 1..33 {
let val_1: super::BitFieldBaseType = 0b01_00_11;
let val_2: super::BitFieldBaseType = 0b10_01_10;
let mut array_1 = BitArray::new(); //BitArray::with_initial_values(vec![val_1], i);
let mut array_2 = BitArray::new(); //BitArray::with_initial_values(vec![val_2], i);
array_1.appendBits(val_1, i).expect("append");
array_2.appendBits(val_2, i).expect("append");
array_1.xor(&array_2).expect("xor complete");
match i {
1 => assert_eq!(array_1.getBitArray(), &[0b1]),
2 => assert_eq!(array_1.getBitArray(), &[0b10]),
3 => assert_eq!(array_1.getBitArray(), &[0b10_1]),
4 => assert_eq!(array_1.getBitArray(), &[0b10_10]),
5 => assert_eq!(array_1.getBitArray(), &[0b10_10_1]),
6 => assert_eq!(array_1.getBitArray(), &[0b10_10_11]),
7..=24 => assert_eq!(array_1.getBitArray(), &[0b10_10_11 << (i - 6)], "{i}"),
_ => assert_eq!(array_1.getBitArray(), &[0b10_10_11 << i - 6, 0], "{i}"),
}
}
}
fn reverse_original(
oldBits: &[super::BitFieldBaseType],
size: usize,
) -> Vec<super::BitFieldBaseType> {
let mut newBits = vec![0; oldBits.len()];
for i in 0..size {
// for (int i = 0; i < size; i++) {
@@ -282,13 +344,12 @@ fn reverse_original(oldBits: &[u32], size: usize) -> Vec<u32> {
newBits
}
fn bit_set(bits: &[u32], i: usize) -> bool {
fn bit_set(bits: &[super::BitFieldBaseType], i: usize) -> bool {
(bits[i / 32] & (1 << (i & 0x1F))) != 0
}
fn arrays_are_equal(left: &[u32], right: &[u32], size: usize) -> bool {
fn arrays_are_equal<T: Eq + Default>(left: &[T], right: &[T], size: usize) -> bool {
for i in 0..size {
// for (int i = 0; i < size; i++) {
if left[i] != right[i] {
return false;
}

View File

@@ -0,0 +1,95 @@
use std::borrow::Cow;
use image::{DynamicImage, ImageBuffer, Luma};
use once_cell::sync::OnceCell;
use crate::{Binarizer, Exceptions, LuminanceSource};
use super::{BitArray, BitMatrix, Result};
/// The `AdaptiveThresholdBinarizer` works using the `imageproc::contrast::adaptive_threshold`
/// function. This is an alternative to the other Binarizers available. It is largely
/// untested.
pub struct AdaptiveThresholdBinarizer<LS: LuminanceSource> {
source: LS,
matrix: OnceCell<BitMatrix>,
radius: u32,
}
impl<LS: LuminanceSource> AdaptiveThresholdBinarizer<LS> {
pub fn new(source: LS, radius: u32) -> Self {
Self {
source,
radius,
matrix: OnceCell::new(),
}
}
}
impl<LS: LuminanceSource> AdaptiveThresholdBinarizer<LS> {
fn buildMatrix(&self) -> Result<BitMatrix> {
let image_buffer = {
let Some(buff): Option<ImageBuffer<Luma<u8>, Vec<u8>>> = ImageBuffer::from_vec(
self.source.get_width() as u32,
self.source.get_height() as u32,
self.source.get_matrix(),
) else {
return Err(Exceptions::ILLEGAL_ARGUMENT);
};
buff
};
let filtered_iamge =
imageproc::contrast::adaptive_threshold(&image_buffer, self.radius.into());
let dynamic_filtered = DynamicImage::from(filtered_iamge);
dynamic_filtered.try_into()
}
}
impl<LS: LuminanceSource> Binarizer for AdaptiveThresholdBinarizer<LS> {
type Source = LS;
fn get_luminance_source(&self) -> &Self::Source {
&self.source
}
fn get_black_row(&self, y: usize) -> Result<Cow<BitArray>> {
let matrix = self.matrix.get_or_try_init(|| self.buildMatrix())?;
Ok(Cow::Owned(matrix.getRow(y as u32)))
}
fn get_black_matrix(&self) -> super::Result<&BitMatrix> {
self.matrix.get_or_try_init(|| self.buildMatrix())
}
fn get_black_line(&self, l: usize, lt: super::LineOrientation) -> Result<Cow<BitArray>> {
match lt {
super::LineOrientation::Row => self.get_black_row(l),
super::LineOrientation::Column => {
let matrix = self.matrix.get_or_try_init(|| self.buildMatrix())?;
Ok(Cow::Owned(matrix.getCol(l as u32)))
}
}
}
fn create_binarizer(&self, source: Self::Source) -> Self
where
Self: Sized,
{
Self {
source: source,
matrix: OnceCell::new(),
radius: self.radius,
}
}
fn get_width(&self) -> usize {
self.source.get_width()
}
fn get_height(&self) -> usize {
self.source.get_height()
}
}

View File

@@ -18,13 +18,15 @@
// import java.util.Arrays;
use std::ops::Index;
use std::{cmp, fmt};
use crate::common::Result;
use crate::Exceptions;
static LOAD_FACTOR: f32 = 0.75;
const LOAD_FACTOR: f32 = 0.75;
type BaseType = super::BitFieldBaseType;
const BASE_BITS: usize = super::BIT_FIELD_BASE_BITS;
/**
* <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>
@@ -33,7 +35,7 @@ static LOAD_FACTOR: f32 = 0.75;
*/
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct BitArray {
bits: Vec<u32>,
bits: Vec<BaseType>,
size: usize,
}
@@ -47,14 +49,14 @@ impl BitArray {
pub fn with_size(size: usize) -> Self {
Self {
bits: BitArray::makeArray(size),
bits: makeArray(size),
size,
}
}
/// For testing only
#[cfg(test)]
pub fn with_initial_values(bits: Vec<u32>, size: usize) -> Self {
pub fn with_initial_values(bits: Vec<BaseType>, size: usize) -> Self {
Self { bits, size }
}
@@ -66,12 +68,14 @@ impl BitArray {
(self.size + 7) / 8
}
#[inline]
fn ensure_capacity(&mut self, newSize: usize) {
if newSize > self.bits.len() * 32 {
let mut newBits = BitArray::makeArray((newSize as f32 / LOAD_FACTOR).ceil() as usize);
//System.arraycopy(bits, 0, newBits, 0, bits.length);
newBits[0..self.bits.len()].clone_from_slice(&self.bits[0..self.bits.len()]);
self.bits = newBits;
let target_size = (newSize as f32 / LOAD_FACTOR).ceil() as usize;
let array_desired_length = (target_size + BASE_BITS - 1) / BASE_BITS;
if self.bits.len() < array_desired_length {
let additional_capacity = array_desired_length - self.bits.len();
self.bits.extend(vec![0; additional_capacity]);
}
}
@@ -80,11 +84,11 @@ impl BitArray {
* @return true iff bit i is set
*/
pub fn get(&self, i: usize) -> bool {
(self.bits[i / 32] & (1 << (i & 0x1F))) != 0
(self.bits[i / BASE_BITS] & (1 << (i & 0x1F))) != 0
}
pub fn try_get(&self, i: usize) -> Option<bool> {
if (i / 32) >= self.bits.len() {
if (i / BASE_BITS) >= self.bits.len() {
None
} else {
Some(self.get(i))
@@ -97,7 +101,7 @@ impl BitArray {
* @param i bit to set
*/
pub fn set(&mut self, i: usize) {
self.bits[i / 32] |= 1 << (i & 0x1F);
self.bits[i / BASE_BITS] |= 1 << (i & 0x1F);
}
/**
@@ -106,7 +110,7 @@ impl BitArray {
* @param i bit to set
*/
pub fn flip(&mut self, i: usize) {
self.bits[i / 32] ^= 1 << (i & 0x1F);
self.bits[i / BASE_BITS] ^= 1 << (i & 0x1F);
}
/**
@@ -119,7 +123,7 @@ impl BitArray {
if from >= self.size {
return self.size;
}
let mut bitsOffset = from / 32;
let mut bitsOffset = from / BASE_BITS;
let mut currentBits = self.bits[bitsOffset] as i64;
// mask off lesser bits first
currentBits &= -(1 << (from & 0x1F));
@@ -130,7 +134,7 @@ impl BitArray {
}
currentBits = self.bits[bitsOffset] as i64;
}
let result = (bitsOffset * 32) + currentBits.trailing_zeros() as usize;
let result = (bitsOffset * BASE_BITS) + currentBits.trailing_zeros() as usize;
cmp::min(result, self.size)
}
@@ -143,7 +147,7 @@ impl BitArray {
if from >= self.size {
return self.size;
}
let mut bitsOffset = from / 32;
let mut bitsOffset = from / BASE_BITS;
let mut currentBits = !self.bits[bitsOffset] as i64;
// mask off lesser bits first
currentBits &= -(1 << (from & 0x1F));
@@ -154,7 +158,7 @@ impl BitArray {
}
currentBits = !self.bits[bitsOffset] as i64;
}
let result = (bitsOffset * 32) + currentBits.trailing_zeros() as usize;
let result = (bitsOffset * BASE_BITS) + currentBits.trailing_zeros() as usize;
cmp::min(result, self.size)
}
@@ -165,8 +169,8 @@ impl BitArray {
* @param newBits the new value of the next 32 bits. Note again that the least-significant bit
* corresponds to bit i, the next-least-significant to i+1, and so on.
*/
pub fn setBulk(&mut self, i: usize, newBits: u32) {
self.bits[i / 32] = newBits;
pub fn setBulk(&mut self, i: usize, newBits: BaseType) {
self.bits[i / BASE_BITS] = newBits;
}
/**
@@ -184,15 +188,15 @@ impl BitArray {
return Ok(());
}
end -= 1; // will be easier to treat this as the last actually set bit -- inclusive
let firstInt = start / 32;
let lastInt = end / 32;
let firstInt = start / BASE_BITS;
let lastInt = end / BASE_BITS;
for i in firstInt..=lastInt {
//for (int i = firstInt; i <= lastInt; i++) {
let firstBit = if i > firstInt { 0 } else { start & 0x1F };
let lastBit = if i < lastInt { 31 } else { end & 0x1F };
// Ones from firstBit to lastBit, inclusive
let mask: u64 = (2 << lastBit) - (1 << firstBit);
self.bits[i] |= mask as u32;
self.bits[i] |= mask as BaseType;
}
Ok(())
}
@@ -201,11 +205,6 @@ impl BitArray {
* Clears all bits (sets to false).
*/
pub fn clear(&mut self) {
// let max = self.bits.len();
// for i in 0..max {
// //for (int i = 0; i < max; i++) {
// self.bits[i] = 0;
// }
self.bits.fill(0);
}
@@ -227,8 +226,8 @@ impl BitArray {
return Ok(true); // empty range matches
}
end -= 1; // will be easier to treat this as the last actually set bit -- inclusive
let firstInt = start / 32;
let lastInt = end / 32;
let firstInt = start / BASE_BITS;
let lastInt = end / BASE_BITS;
for i in firstInt..=lastInt {
//for (int i = firstInt; i <= lastInt; i++) {
let firstBit = if i > firstInt { 0 } else { start & 0x1F };
@@ -238,7 +237,7 @@ impl BitArray {
// Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is,
// equals the mask, or we're looking for 0s and the masked portion is not all 0s
if (self.bits[i] & mask as u32) != (if value { mask as u32 } else { 0 }) {
if (self.bits[i] & mask as BaseType) != (if value { mask as BaseType } else { 0 }) {
return Ok(false);
}
}
@@ -248,7 +247,7 @@ impl BitArray {
pub fn appendBit(&mut self, bit: bool) {
self.ensure_capacity(self.size + 1);
if bit {
self.bits[self.size / 32] |= 1 << (self.size & 0x1F);
self.bits[self.size / BASE_BITS] |= 1 << (self.size & 0x1F);
}
self.size += 1;
}
@@ -261,11 +260,12 @@ impl BitArray {
* @param value {@code int} containing bits to append
* @param numBits bits from value to append
*/
pub fn appendBits(&mut self, value: u32, num_bits: usize) -> Result<()> {
if num_bits > 32 {
return Err(Exceptions::illegal_argument_with(
"num bits must be between 0 and 32",
));
pub fn appendBits(&mut self, value: BaseType, num_bits: usize) -> Result<()> {
if num_bits > BASE_BITS {
return Err(Exceptions::illegal_argument_with(format!(
"num bits must be between 0 and {}",
BaseType::BITS
)));
}
if num_bits == 0 {
@@ -277,7 +277,7 @@ impl BitArray {
for numBitsLeft in (0..num_bits).rev() {
//for (int numBitsLeft = numBits - 1; numBitsLeft >= 0; numBitsLeft--) {
if (value & (1 << numBitsLeft)) != 0 {
self.bits[next_size / 32] |= 1 << (next_size & 0x1F);
self.bits[next_size / BASE_BITS] |= 1 << (next_size & 0x1F);
}
next_size += 1;
}
@@ -298,11 +298,11 @@ impl BitArray {
if self.size != other.size {
return Err(Exceptions::illegal_argument_with("Sizes don't match"));
}
for i in 0..self.bits.len() {
for (lhs, rhs) in self.bits.iter_mut().zip(other.bits.iter()) {
//for (int i = 0; i < bits.length; i++) {
// The last int could be incomplete (i.e. not have 32 bits in
// it) but there is no problem since 0 XOR 0 == 0.
self.bits[i] ^= other.bits[i];
*lhs ^= rhs;
}
Ok(())
}
@@ -335,7 +335,7 @@ impl BitArray {
* @return underlying array of ints. The first element holds the first 32 bits, and the least
* significant bit is bit 0.
*/
pub fn getBitArray(&self) -> &[u32] {
pub fn getBitArray(&self) -> &[BaseType] {
&self.bits
}
@@ -343,52 +343,35 @@ impl BitArray {
* Reverses all bits in the array.
*/
pub fn reverse(&mut self) {
let mut newBits = vec![0; self.bits.len()];
// let mut newBits = vec![0; self.bits.len()];
// reverse all int's first
let len = (self.size - 1) / 32;
let oldBitsLen = len + 1;
for i in 0..oldBitsLen {
//for (int i = 0; i < oldBitsLen; i++) {
newBits[len - i] = self.bits[i].reverse_bits();
}
// let array_size = self.size.div_ceil(BASE_TYPE::BITS as usize);
// for (new_bits, old_bits) in newBits.iter_mut().take(oldBitsLen).zip(self.bits.iter().take(oldBitsLen).rev()) {
// *new_bits = old_bits.reverse_bits();
// }
self.bits[..oldBitsLen].reverse();
self.bits[..oldBitsLen]
.iter_mut()
.for_each(|bit_store| *bit_store = bit_store.reverse_bits());
self.bits[oldBitsLen..].fill(0);
// now correct the int's if the bit size isn't a multiple of 32
if self.size != oldBitsLen * 32 {
let leftOffset = oldBitsLen * 32 - self.size;
let mut currentInt = newBits[0] >> leftOffset;
if self.size != oldBitsLen * BASE_BITS {
let leftOffset = oldBitsLen * BASE_BITS - self.size;
let mut currentInt = self.bits[0] >> leftOffset;
for i in 1..oldBitsLen {
//for (int i = 1; i < oldBitsLen; i++) {
let nextInt = newBits[i];
currentInt |= nextInt << (32 - leftOffset);
newBits[i - 1] = currentInt;
let nextInt = self.bits[i];
currentInt |= nextInt << (BASE_BITS - leftOffset);
self.bits[i - 1] = currentInt;
currentInt = nextInt >> leftOffset;
}
newBits[oldBitsLen - 1] = currentInt;
self.bits[oldBitsLen - 1] = currentInt;
}
self.bits = newBits;
}
fn makeArray(size: usize) -> Vec<u32> {
vec![0; (size + 31) / 32]
}
// @Override
// public boolean equals(Object o) {
// if (!(o instanceof BitArray)) {
// return false;
// }
// BitArray other = (BitArray) o;
// return size == other.size && Arrays.equals(bits, other.bits);
// }
// @Override
// public int hashCode() {
// return 31 * size + Arrays.hashCode(bits);
// }
// @Override
// public BitArray clone() {
// return new BitArray(bits.clone(), size);
// }
}
impl fmt::Display for BitArray {
@@ -427,13 +410,6 @@ impl From<&BitArray> for Vec<u8> {
impl From<BitArray> for Vec<bool> {
fn from(value: BitArray) -> Self {
// let mut array = vec![false; value.size];
// for (pixel, element) in array.iter_mut().enumerate().take(value.size) {
// *element = value.get(pixel);
// }
// array
Self::from(&value)
}
}
@@ -449,3 +425,7 @@ impl From<&BitArray> for Vec<bool> {
array
}
}
fn makeArray(size: usize) -> Vec<BaseType> {
vec![0; (size + BASE_BITS - 1) / BASE_BITS]
}

View File

@@ -25,6 +25,9 @@ use crate::{point_f, point_i, Exceptions, Point};
use super::BitArray;
type BaseType = super::BitFieldBaseType;
const BASE_BITS: usize = super::BIT_FIELD_BASE_BITS;
/**
* <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common
* module, x is the column position, and y is the row position. The ordering is always x, y.
@@ -45,7 +48,7 @@ pub struct BitMatrix {
width: u32,
height: u32,
row_size: usize,
bits: Vec<u32>,
bits: Vec<BaseType>,
}
impl BitMatrix {
@@ -73,8 +76,11 @@ impl BitMatrix {
Ok(Self {
width,
height,
row_size: ((width + 31) / 32) as usize,
bits: vec![0; (((width + 31) / 32) * height) as usize],
row_size: ((width as usize + BASE_BITS - 1) / BASE_BITS) as usize,
bits: vec![
0;
(((width as usize + BASE_BITS - 1) / BASE_BITS) * height as usize) as usize
],
})
// this.width = width;
// this.height = height;
@@ -83,7 +89,7 @@ impl BitMatrix {
}
#[allow(dead_code)]
fn with_all_data(&self, width: u32, height: u32, rowSize: usize, bits: Vec<u32>) -> Self {
fn with_all_data(&self, width: u32, height: u32, rowSize: usize, bits: Vec<BaseType>) -> Self {
Self {
width,
height,
@@ -235,7 +241,7 @@ impl BitMatrix {
#[inline(always)]
fn get_offset(&self, y: u32, x: u32) -> usize {
y as usize * self.row_size + (x as usize / 32)
y as usize * self.row_size + (x as usize / BASE_BITS)
}
pub fn try_get(&self, x: u32, y: u32) -> Option<bool> {
@@ -387,7 +393,7 @@ impl BitMatrix {
let offset = y as usize * self.row_size;
for x in left..right {
//for (int x = left; x < right; x++) {
self.bits[offset + (x as usize / 32)] |= 1 << (x & 0x1f);
self.bits[offset + (x as usize / BASE_BITS)] |= 1 << (x & 0x1f);
}
}
Ok(())
@@ -407,7 +413,7 @@ impl BitMatrix {
let offset = y as usize * self.row_size;
for x in 0..self.row_size {
//for (int x = 0; x < rowSize; x++) {
rw.setBulk(x * 32, self.bits[offset + x]);
rw.setBulk(x * BASE_BITS, self.bits[offset + x]);
}
rw
}
@@ -489,7 +495,7 @@ impl BitMatrix {
pub fn rotate90(&mut self) {
let newWidth = self.height;
let newHeight = self.width;
let newRowSize = (newWidth + 31) / 32;
let newRowSize = (newWidth + BASE_BITS as u32 - 1) / BASE_BITS as u32;
let mut newBits = vec![0; (newRowSize * newHeight) as usize];
for y in 0..self.height {
@@ -498,7 +504,8 @@ impl BitMatrix {
//for (int x = 0; x < width; x++) {
let offset = self.get_offset(y, x);
if ((self.bits[offset] >> (x & 0x1f)) & 1) != 0 {
let newOffset: usize = ((newHeight - 1 - x) * newRowSize + (y / 32)) as usize;
let newOffset: usize =
((newHeight - 1 - x) * newRowSize + (y / BASE_BITS as u32)) as usize;
newBits[newOffset] |= 1 << (y & 0x1f);
}
}
@@ -531,22 +538,22 @@ impl BitMatrix {
top = top.min(y);
bottom = bottom.max(y);
if x32 * 32 < left as usize {
if x32 * BASE_BITS < left as usize {
let mut bit = 0;
while (theBits << (31 - bit)) == 0 {
while (theBits << (BASE_BITS - 1 - bit)) == 0 {
bit += 1;
}
if (x32 * 32 + bit) < left as usize {
left = (x32 * 32 + bit) as u32;
if (x32 * BASE_BITS + bit) < left as usize {
left = (x32 * BASE_BITS + bit) as u32;
}
}
if x32 * 32 + 31 > right as usize {
let mut bit = 31;
if x32 * BASE_BITS + BASE_BITS - 1 > right as usize {
let mut bit = BASE_BITS - 1;
while (theBits >> bit) == 0 {
bit -= 1;
}
if (x32 * 32 + bit) > right as usize {
right = (x32 * 32 + bit) as u32;
if (x32 * BASE_BITS + bit) > right as usize {
right = (x32 * BASE_BITS + bit) as u32;
}
}
}
@@ -574,7 +581,7 @@ impl BitMatrix {
return None;
}
let y = bitsOffset / self.row_size;
let mut x = (bitsOffset % self.row_size) * 32;
let mut x = (bitsOffset % self.row_size) * BASE_BITS;
let theBits = self.bits[bitsOffset];
let mut bit = 0;
@@ -595,10 +602,10 @@ impl BitMatrix {
}
let y = bitsOffset as usize / self.row_size;
let mut x = (bitsOffset as usize % self.row_size) * 32;
let mut x = (bitsOffset as usize % self.row_size) * BASE_BITS;
let theBits = self.bits[bitsOffset as usize];
let mut bit = 31;
let mut bit = BASE_BITS - 1;
while (theBits >> bit) == 0 {
bit -= 1;
}

View File

@@ -31,7 +31,7 @@ use crate::point_f;
use super::BitMatrix;
static BIT_MATRIX_POINTS: [u32; 6] = [1, 2, 2, 0, 3, 1];
const BIT_MATRIX_POINTS: [u32; 6] = [1, 2, 2, 0, 3, 1];
#[test]
fn test_get_set() {

View File

@@ -17,6 +17,7 @@
//package com.google.zxing.common;
use std::cmp;
use std::io::{ErrorKind, Read};
use crate::common::Result;
use crate::Exceptions;
@@ -173,3 +174,28 @@ impl BitSource {
8 * (self.bytes.len() - self.byte_offset) - self.bit_offset
}
}
impl Read for BitSource {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let requested_bytes = buf.len();
let available = self.available();
let to_read = if requested_bytes <= available {
requested_bytes
} else {
available
};
for byte in buf.iter_mut().take(to_read) {
let Ok(bits) = self.readBits(8) else {
return Err(std::io::Error::new(
ErrorKind::Unsupported,
"unable to read bits",
));
};
*byte = bits as u8;
}
Ok(to_read)
}
}

View File

@@ -18,6 +18,8 @@
// import java.io.ByteArrayOutputStream;
use std::io::Write;
/**
* Class that lets one easily build an array of bytes by appending bits at a time.
*
@@ -71,3 +73,19 @@ impl Default for BitSourceBuilder {
Self::new()
}
}
impl Write for BitSourceBuilder {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut written = 0;
for byte in buf.iter() {
self.write(*byte as u32, 8);
written += 1;
}
Ok(written)
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}

View File

@@ -349,3 +349,18 @@ impl Default for SymbologyIdentifier {
}
}
}
impl std::io::Write for ECIStringBuilder {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
if buf.len() == 1 {
self.append_byte(buf[0]);
} else {
self.append_bytes(buf);
}
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}

View File

@@ -175,12 +175,12 @@ impl<LS: LuminanceSource> HybridBinarizer<LS> {
// for (int y = 0; y < subHeight; y++) {
let yoffset = u32::min(y << BLOCK_SIZE_POWER, maxYOffset);
let top = Self::cap(y, sub_height - 3);
let top = u32::clamp(y, 2, sub_height - 3); // Self::cap(y, sub_height - 3);
for x in 0..sub_width {
// for (int x = 0; x < subWidth; x++) {
let xoffset = u32::min(x << BLOCK_SIZE_POWER, maxXOffset);
let left = Self::cap(x, sub_width - 3);
let left = u32::clamp(x, 2, sub_width - 3); //Self::cap(x, sub_width - 3);
let mut sum = 0;
for z in -2..=2 {
// for (int z = -2; z <= 2; z++) {
@@ -197,11 +197,6 @@ impl<LS: LuminanceSource> HybridBinarizer<LS> {
}
}
#[inline(always)]
fn cap(value: u32, max: u32) -> u32 {
u32::clamp(value, 2, max)
}
/**
* Applies a single threshold to a block of pixels.
*/

View File

@@ -121,3 +121,11 @@ pub use line_orientation::LineOrientation;
mod otsu_level_binarizer;
#[cfg(feature = "otsu_level")]
pub use otsu_level_binarizer::*;
#[cfg(feature = "image")]
mod adaptive_threshold_binarizer;
#[cfg(feature = "image")]
pub use adaptive_threshold_binarizer::*;
pub type BitFieldBaseType = u32;
pub const BIT_FIELD_BASE_BITS: usize = BitFieldBaseType::BITS as usize;

View File

@@ -20,7 +20,7 @@ use once_cell::sync::Lazy;
use crate::common::Result;
use crate::Exceptions;
static VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::buildVersions);
static VERSIONS: Lazy<Box<[Version]>> = Lazy::new(Version::buildVersions);
pub type VersionRef = &'static Version;
@@ -118,8 +118,8 @@ impl Version {
/**
* See ISO 16022:2006 5.5.1 Table 7
*/
fn buildVersions() -> Vec<Version> {
vec![
fn buildVersions() -> Box<[Version]> {
Box::new([
Version::new(1, 10, 10, 8, 8, ECBlocks::new(5, ECB::new(1, 3))),
Version::new(2, 12, 12, 10, 10, ECBlocks::new(7, ECB::new(1, 5))),
Version::new(3, 14, 14, 12, 12, ECBlocks::new(10, ECB::new(1, 8))),
@@ -177,7 +177,7 @@ impl Version {
Version::new(46, 26, 40, 24, 18, ECBlocks::new(38, ECB::new(1, 70))),
Version::new(47, 26, 48, 24, 22, ECBlocks::new(42, ECB::new(1, 90))),
Version::new(48, 26, 64, 24, 14, ECBlocks::new(50, ECB::new(1, 118))),
]
])
}
}
@@ -195,20 +195,20 @@ impl fmt::Display for Version {
*/
pub struct ECBlocks {
ecCodewords: u32,
ecBlocks: Vec<ECB>,
ecBlocks: Box<[ECB]>,
}
impl ECBlocks {
pub fn new(ecCodewords: u32, ecBlocks: ECB) -> Self {
Self {
ecCodewords,
ecBlocks: vec![ecBlocks],
ecBlocks: Box::new([ecBlocks]),
}
}
pub fn new2(ecCodewords: u32, ecBlocks1: ECB, ecBlocks2: ECB) -> Self {
Self {
ecCodewords,
ecBlocks: vec![ecBlocks1, ecBlocks2],
ecBlocks: Box::new([ecBlocks1, ecBlocks2]),
}
}
@@ -231,18 +231,18 @@ pub struct ECB {
dataCodewords: u32,
}
impl ECB {
pub fn new(count: u32, dataCodewords: u32) -> Self {
pub const fn new(count: u32, dataCodewords: u32) -> Self {
Self {
count,
dataCodewords,
}
}
pub fn getCount(&self) -> u32 {
pub const fn getCount(&self) -> u32 {
self.count
}
pub fn getDataCodewords(&self) -> u32 {
pub const fn getDataCodewords(&self) -> u32 {
self.dataCodewords
}
}

View File

@@ -104,7 +104,9 @@ pub mod helpers;
mod luma_luma_source;
pub use luma_luma_source::*;
#[cfg(feature = "experimental_features")]
mod filtered_image_reader;
#[cfg(feature = "experimental_features")]
pub use filtered_image_reader::*;
#[cfg(feature = "svg_read")]

View File

@@ -9,13 +9,16 @@ pub struct Luma8LuminanceSource {
/// image origin in the form (x,y)
origin: (u32, u32),
/// raw data for luma 8
data: Vec<u8>,
data: Box<[u8]>,
/// flag indicating if the underlying data needs to be inverted for use
inverted: bool,
/// original dimensions of the data, used to manage crop
original_dimension: (u32, u32),
}
impl LuminanceSource for Luma8LuminanceSource {
const SUPPORTS_CROP: bool = true;
const SUPPORTS_ROTATION: bool = true;
fn get_row(&self, y: usize) -> Vec<u8> {
let chunk_size = self.original_dimension.0 as usize;
let row_skip = y + self.origin.1 as usize;
@@ -30,16 +33,6 @@ impl LuminanceSource for Luma8LuminanceSource {
} else {
Vec::from(&self.data[data_start..data_end])
}
// self.data
// .chunks_exact(chunk_size)
// .skip(row_skip)
// .take(1)
// .flatten()
// .skip(column_skip)
// .take(column_take)
// .map(|byte| Self::invert_if_should(*byte, self.inverted))
// .collect()
}
fn get_column(&self, x: usize) -> Vec<u8> {
@@ -85,10 +78,6 @@ impl LuminanceSource for Luma8LuminanceSource {
self.inverted = !self.inverted;
}
fn is_crop_supported(&self) -> bool {
true
}
fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> Result<Self> {
Ok(Self {
dimensions: (width as u32, height as u32),
@@ -99,10 +88,6 @@ impl LuminanceSource for Luma8LuminanceSource {
})
}
fn is_rotate_supported(&self) -> bool {
true
}
fn rotate_counter_clockwise(&self) -> Result<Self> {
let mut new_matrix = Self {
dimensions: self.dimensions,
@@ -123,7 +108,14 @@ impl LuminanceSource for Luma8LuminanceSource {
}
fn get_luma8_point(&self, column: usize, row: usize) -> u8 {
self.get_row(row)[column]
let chunk_size = self.original_dimension.0 as usize;
let row_skip = row + self.origin.1 as usize;
let column_skip = self.origin.0 as usize;
let data_start = (chunk_size * row_skip) + column_skip;
let data_point = data_start + column;
Self::invert_if_should(self.data[data_point], self.inverted)
}
}
@@ -163,7 +155,7 @@ impl Luma8LuminanceSource {
new_data[offset_b] = self.data[offset_a];
}
}
self.data = new_data;
self.data = new_data.into_boxed_slice();
self.dimensions = new_dim;
self.original_dimension = (self.original_dimension.1, self.original_dimension.0);
self.origin = (self.origin.1, self.origin.0);
@@ -184,7 +176,7 @@ impl Luma8LuminanceSource {
Self {
dimensions: (width, height),
origin: (0, 0),
data: source,
data: source.into_boxed_slice(),
inverted: false,
original_dimension: (width, height),
}
@@ -194,13 +186,13 @@ impl Luma8LuminanceSource {
Self {
dimensions: (width as u32, height as u32),
origin: (0, 0),
data: vec![0u8; width * height],
data: vec![0u8; width * height].into_boxed_slice(),
inverted: false,
original_dimension: (width as u32, height as u32),
}
}
pub fn get_matrix_mut(&mut self) -> &mut Vec<u8> {
pub fn get_matrix_mut(&mut self) -> &mut Box<[u8]> {
&mut self.data
}
@@ -244,16 +236,19 @@ mod tests {
(rect_wide.dimensions.1, rect_wide.dimensions.0)
);
assert_eq!(rotated_square.data, vec![3, 6, 9, 2, 5, 8, 1, 4, 7]);
assert_eq!(
rotated_square.data,
vec![3, 6, 9, 2, 5, 8, 1, 4, 7].into_boxed_slice()
);
assert_eq!(
rotated_wide_rect.data,
vec![1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1]
vec![1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1].into_boxed_slice()
);
assert_eq!(
rotated_tall_rect.data,
vec![0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0]
vec![0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0].into_boxed_slice()
);
}
}

View File

@@ -29,8 +29,8 @@ use crate::Exceptions;
* @author dswitkin@google.com (Daniel Switkin)
*/
pub trait LuminanceSource {
//private final int width;
//private final int height;
const SUPPORTS_ROTATION: bool = false;
const SUPPORTS_CROP: bool = false;
//fn new( width:usize, height:usize) -> Self;
@@ -75,7 +75,14 @@ pub trait LuminanceSource {
* @return Whether this subclass supports cropping.
*/
fn is_crop_supported(&self) -> bool {
false
Self::SUPPORTS_CROP
}
/**
* @return Whether this subclass supports counter-clockwise rotation.
*/
fn is_rotate_supported(&self) -> bool {
Self::SUPPORTS_ROTATION
}
/**
@@ -97,13 +104,6 @@ pub trait LuminanceSource {
))
}
/**
* @return Whether this subclass supports counter-clockwise rotation.
*/
fn is_rotate_supported(&self) -> bool {
false
}
/**
* @return a wrapper of this {@code LuminanceSource} which inverts the luminances it returns -- black becomes
* white and vice versa, and each value becomes (255-value).

View File

@@ -1143,7 +1143,7 @@ mod detector_test {
.read_to_string(&mut expected_result)
.unwrap();
let detection = super::detect(bitmatrix, true).unwrap();
let detection = super::detect(&bitmatrix, true).unwrap();
// let i: image::DynamicImage = detection.getBits().into();
// i.save("dbgfle-transformed.png")

View File

@@ -433,115 +433,115 @@ impl Code128Reader {
use once_cell::sync::Lazy;
pub static CODE_PATTERNS: Lazy<[Vec<u32>; 107]> = Lazy::new(|| {
pub static CODE_PATTERNS: Lazy<[Box<[u32]>; 107]> = Lazy::new(|| {
[
vec![2, 1, 2, 2, 2, 2], // 0
vec![2, 2, 2, 1, 2, 2],
vec![2, 2, 2, 2, 2, 1],
vec![1, 2, 1, 2, 2, 3],
vec![1, 2, 1, 3, 2, 2],
vec![1, 3, 1, 2, 2, 2], // 5
vec![1, 2, 2, 2, 1, 3],
vec![1, 2, 2, 3, 1, 2],
vec![1, 3, 2, 2, 1, 2],
vec![2, 2, 1, 2, 1, 3],
vec![2, 2, 1, 3, 1, 2], // 10
vec![2, 3, 1, 2, 1, 2],
vec![1, 1, 2, 2, 3, 2],
vec![1, 2, 2, 1, 3, 2],
vec![1, 2, 2, 2, 3, 1],
vec![1, 1, 3, 2, 2, 2], // 15
vec![1, 2, 3, 1, 2, 2],
vec![1, 2, 3, 2, 2, 1],
vec![2, 2, 3, 2, 1, 1],
vec![2, 2, 1, 1, 3, 2],
vec![2, 2, 1, 2, 3, 1], // 20
vec![2, 1, 3, 2, 1, 2],
vec![2, 2, 3, 1, 1, 2],
vec![3, 1, 2, 1, 3, 1],
vec![3, 1, 1, 2, 2, 2],
vec![3, 2, 1, 1, 2, 2], // 25
vec![3, 2, 1, 2, 2, 1],
vec![3, 1, 2, 2, 1, 2],
vec![3, 2, 2, 1, 1, 2],
vec![3, 2, 2, 2, 1, 1],
vec![2, 1, 2, 1, 2, 3], // 30
vec![2, 1, 2, 3, 2, 1],
vec![2, 3, 2, 1, 2, 1],
vec![1, 1, 1, 3, 2, 3],
vec![1, 3, 1, 1, 2, 3],
vec![1, 3, 1, 3, 2, 1], // 35
vec![1, 1, 2, 3, 1, 3],
vec![1, 3, 2, 1, 1, 3],
vec![1, 3, 2, 3, 1, 1],
vec![2, 1, 1, 3, 1, 3],
vec![2, 3, 1, 1, 1, 3], // 40
vec![2, 3, 1, 3, 1, 1],
vec![1, 1, 2, 1, 3, 3],
vec![1, 1, 2, 3, 3, 1],
vec![1, 3, 2, 1, 3, 1],
vec![1, 1, 3, 1, 2, 3], // 45
vec![1, 1, 3, 3, 2, 1],
vec![1, 3, 3, 1, 2, 1],
vec![3, 1, 3, 1, 2, 1],
vec![2, 1, 1, 3, 3, 1],
vec![2, 3, 1, 1, 3, 1], // 50
vec![2, 1, 3, 1, 1, 3],
vec![2, 1, 3, 3, 1, 1],
vec![2, 1, 3, 1, 3, 1],
vec![3, 1, 1, 1, 2, 3],
vec![3, 1, 1, 3, 2, 1], // 55
vec![3, 3, 1, 1, 2, 1],
vec![3, 1, 2, 1, 1, 3],
vec![3, 1, 2, 3, 1, 1],
vec![3, 3, 2, 1, 1, 1],
vec![3, 1, 4, 1, 1, 1], // 60
vec![2, 2, 1, 4, 1, 1],
vec![4, 3, 1, 1, 1, 1],
vec![1, 1, 1, 2, 2, 4],
vec![1, 1, 1, 4, 2, 2],
vec![1, 2, 1, 1, 2, 4], // 65
vec![1, 2, 1, 4, 2, 1],
vec![1, 4, 1, 1, 2, 2],
vec![1, 4, 1, 2, 2, 1],
vec![1, 1, 2, 2, 1, 4],
vec![1, 1, 2, 4, 1, 2], // 70
vec![1, 2, 2, 1, 1, 4],
vec![1, 2, 2, 4, 1, 1],
vec![1, 4, 2, 1, 1, 2],
vec![1, 4, 2, 2, 1, 1],
vec![2, 4, 1, 2, 1, 1], // 75
vec![2, 2, 1, 1, 1, 4],
vec![4, 1, 3, 1, 1, 1],
vec![2, 4, 1, 1, 1, 2],
vec![1, 3, 4, 1, 1, 1],
vec![1, 1, 1, 2, 4, 2], // 80
vec![1, 2, 1, 1, 4, 2],
vec![1, 2, 1, 2, 4, 1],
vec![1, 1, 4, 2, 1, 2],
vec![1, 2, 4, 1, 1, 2],
vec![1, 2, 4, 2, 1, 1], // 85
vec![4, 1, 1, 2, 1, 2],
vec![4, 2, 1, 1, 1, 2],
vec![4, 2, 1, 2, 1, 1],
vec![2, 1, 2, 1, 4, 1],
vec![2, 1, 4, 1, 2, 1], // 90
vec![4, 1, 2, 1, 2, 1],
vec![1, 1, 1, 1, 4, 3],
vec![1, 1, 1, 3, 4, 1],
vec![1, 3, 1, 1, 4, 1],
vec![1, 1, 4, 1, 1, 3], // 95
vec![1, 1, 4, 3, 1, 1],
vec![4, 1, 1, 1, 1, 3],
vec![4, 1, 1, 3, 1, 1],
vec![1, 1, 3, 1, 4, 1],
vec![1, 1, 4, 1, 3, 1], // 100
vec![3, 1, 1, 1, 4, 1],
vec![4, 1, 1, 1, 3, 1],
vec![2, 1, 1, 4, 1, 2],
vec![2, 1, 1, 2, 1, 4],
vec![2, 1, 1, 2, 3, 2], // 105
vec![2, 3, 3, 1, 1, 1, 2],
Box::new([2, 1, 2, 2, 2, 2]), // 0
Box::new([2, 2, 2, 1, 2, 2]),
Box::new([2, 2, 2, 2, 2, 1]),
Box::new([1, 2, 1, 2, 2, 3]),
Box::new([1, 2, 1, 3, 2, 2]),
Box::new([1, 3, 1, 2, 2, 2]), // 5
Box::new([1, 2, 2, 2, 1, 3]),
Box::new([1, 2, 2, 3, 1, 2]),
Box::new([1, 3, 2, 2, 1, 2]),
Box::new([2, 2, 1, 2, 1, 3]),
Box::new([2, 2, 1, 3, 1, 2]), // 10
Box::new([2, 3, 1, 2, 1, 2]),
Box::new([1, 1, 2, 2, 3, 2]),
Box::new([1, 2, 2, 1, 3, 2]),
Box::new([1, 2, 2, 2, 3, 1]),
Box::new([1, 1, 3, 2, 2, 2]), // 15
Box::new([1, 2, 3, 1, 2, 2]),
Box::new([1, 2, 3, 2, 2, 1]),
Box::new([2, 2, 3, 2, 1, 1]),
Box::new([2, 2, 1, 1, 3, 2]),
Box::new([2, 2, 1, 2, 3, 1]), // 20
Box::new([2, 1, 3, 2, 1, 2]),
Box::new([2, 2, 3, 1, 1, 2]),
Box::new([3, 1, 2, 1, 3, 1]),
Box::new([3, 1, 1, 2, 2, 2]),
Box::new([3, 2, 1, 1, 2, 2]), // 25
Box::new([3, 2, 1, 2, 2, 1]),
Box::new([3, 1, 2, 2, 1, 2]),
Box::new([3, 2, 2, 1, 1, 2]),
Box::new([3, 2, 2, 2, 1, 1]),
Box::new([2, 1, 2, 1, 2, 3]), // 30
Box::new([2, 1, 2, 3, 2, 1]),
Box::new([2, 3, 2, 1, 2, 1]),
Box::new([1, 1, 1, 3, 2, 3]),
Box::new([1, 3, 1, 1, 2, 3]),
Box::new([1, 3, 1, 3, 2, 1]), // 35
Box::new([1, 1, 2, 3, 1, 3]),
Box::new([1, 3, 2, 1, 1, 3]),
Box::new([1, 3, 2, 3, 1, 1]),
Box::new([2, 1, 1, 3, 1, 3]),
Box::new([2, 3, 1, 1, 1, 3]), // 40
Box::new([2, 3, 1, 3, 1, 1]),
Box::new([1, 1, 2, 1, 3, 3]),
Box::new([1, 1, 2, 3, 3, 1]),
Box::new([1, 3, 2, 1, 3, 1]),
Box::new([1, 1, 3, 1, 2, 3]), // 45
Box::new([1, 1, 3, 3, 2, 1]),
Box::new([1, 3, 3, 1, 2, 1]),
Box::new([3, 1, 3, 1, 2, 1]),
Box::new([2, 1, 1, 3, 3, 1]),
Box::new([2, 3, 1, 1, 3, 1]), // 50
Box::new([2, 1, 3, 1, 1, 3]),
Box::new([2, 1, 3, 3, 1, 1]),
Box::new([2, 1, 3, 1, 3, 1]),
Box::new([3, 1, 1, 1, 2, 3]),
Box::new([3, 1, 1, 3, 2, 1]), // 55
Box::new([3, 3, 1, 1, 2, 1]),
Box::new([3, 1, 2, 1, 1, 3]),
Box::new([3, 1, 2, 3, 1, 1]),
Box::new([3, 3, 2, 1, 1, 1]),
Box::new([3, 1, 4, 1, 1, 1]), // 60
Box::new([2, 2, 1, 4, 1, 1]),
Box::new([4, 3, 1, 1, 1, 1]),
Box::new([1, 1, 1, 2, 2, 4]),
Box::new([1, 1, 1, 4, 2, 2]),
Box::new([1, 2, 1, 1, 2, 4]), // 65
Box::new([1, 2, 1, 4, 2, 1]),
Box::new([1, 4, 1, 1, 2, 2]),
Box::new([1, 4, 1, 2, 2, 1]),
Box::new([1, 1, 2, 2, 1, 4]),
Box::new([1, 1, 2, 4, 1, 2]), // 70
Box::new([1, 2, 2, 1, 1, 4]),
Box::new([1, 2, 2, 4, 1, 1]),
Box::new([1, 4, 2, 1, 1, 2]),
Box::new([1, 4, 2, 2, 1, 1]),
Box::new([2, 4, 1, 2, 1, 1]), // 75
Box::new([2, 2, 1, 1, 1, 4]),
Box::new([4, 1, 3, 1, 1, 1]),
Box::new([2, 4, 1, 1, 1, 2]),
Box::new([1, 3, 4, 1, 1, 1]),
Box::new([1, 1, 1, 2, 4, 2]), // 80
Box::new([1, 2, 1, 1, 4, 2]),
Box::new([1, 2, 1, 2, 4, 1]),
Box::new([1, 1, 4, 2, 1, 2]),
Box::new([1, 2, 4, 1, 1, 2]),
Box::new([1, 2, 4, 2, 1, 1]), // 85
Box::new([4, 1, 1, 2, 1, 2]),
Box::new([4, 2, 1, 1, 1, 2]),
Box::new([4, 2, 1, 2, 1, 1]),
Box::new([2, 1, 2, 1, 4, 1]),
Box::new([2, 1, 4, 1, 2, 1]), // 90
Box::new([4, 1, 2, 1, 2, 1]),
Box::new([1, 1, 1, 1, 4, 3]),
Box::new([1, 1, 1, 3, 4, 1]),
Box::new([1, 3, 1, 1, 4, 1]),
Box::new([1, 1, 4, 1, 1, 3]), // 95
Box::new([1, 1, 4, 3, 1, 1]),
Box::new([4, 1, 1, 1, 1, 3]),
Box::new([4, 1, 1, 3, 1, 1]),
Box::new([1, 1, 3, 1, 4, 1]),
Box::new([1, 1, 4, 1, 3, 1]), // 100
Box::new([3, 1, 1, 1, 4, 1]),
Box::new([4, 1, 1, 1, 3, 1]),
Box::new([2, 1, 1, 4, 1, 2]),
Box::new([2, 1, 1, 2, 1, 4]),
Box::new([2, 1, 1, 2, 3, 2]), // 105
Box::new([2, 3, 3, 1, 1, 1, 2]),
]
});

View File

@@ -265,7 +265,7 @@ impl<'a> RowReader for DXFilmEdgeReader<'_> {
for _i in 0..modules {
dataBits.appendBits(
if next.index() % 2 == 0 {
0xFFFFFFFF
0xFFFFFFFF_u32
} else {
0x0
},

View File

@@ -25,15 +25,15 @@
*/
pub struct EANManufacturerOrgSupport {
ranges: Vec<Vec<u32>>, //= new ArrayList<>();
countryIdentifiers: Vec<String>, // = new ArrayList<>();
ranges: Vec<[u32; 2]>, //= new ArrayList<>();
countryIdentifiers: Vec<&'static str>, // = new ArrayList<>();
}
impl Default for EANManufacturerOrgSupport {
fn default() -> Self {
let mut slf = Self {
ranges: Default::default(),
countryIdentifiers: Default::default(),
ranges: Vec::with_capacity(150),
countryIdentifiers: Vec::with_capacity(150),
};
slf.initIfNeeded();
slf
@@ -42,14 +42,14 @@ impl Default for EANManufacturerOrgSupport {
impl EANManufacturerOrgSupport {
pub fn lookupCountryIdentifier(&self, productCode: &str) -> Option<&str> {
let prefix = productCode[0..3].parse::<u32>().expect("must parse prefix");
let prefix = productCode[0..3].parse::<u32>().ok()?;
let max = self.ranges.len();
for (i, range) in self.ranges.iter().enumerate().take(max) {
let start = range[0];
if prefix < start {
return None;
}
let end = if range.len() == 1 { start } else { range[1] };
let end = if range[1] == 0 { start } else { range[1] };
if prefix <= end {
return Some(self.countryIdentifiers.get(i)?);
}
@@ -58,7 +58,7 @@ impl EANManufacturerOrgSupport {
None
}
fn add(&mut self, range: Vec<u32>, id: String) {
fn add(&mut self, range: [u32; 2], id: &'static str) {
self.ranges.push(range);
self.countryIdentifiers.push(id);
}
@@ -67,112 +67,112 @@ impl EANManufacturerOrgSupport {
if !self.ranges.is_empty() {
return;
}
self.add(vec![0, 19], "US/CA".to_owned());
self.add(vec![30, 39], "US".to_owned());
self.add(vec![60, 139], "US/CA".to_owned());
self.add(vec![300, 379], "FR".to_owned());
self.add(vec![380], "BG".to_owned());
self.add(vec![383], "SI".to_owned());
self.add(vec![385], "HR".to_owned());
self.add(vec![387], "BA".to_owned());
self.add(vec![400, 440], "DE".to_owned());
self.add(vec![450, 459], "JP".to_owned());
self.add(vec![460, 469], "RU".to_owned());
self.add(vec![471], "TW".to_owned());
self.add(vec![474], "EE".to_owned());
self.add(vec![475], "LV".to_owned());
self.add(vec![476], "AZ".to_owned());
self.add(vec![477], "LT".to_owned());
self.add(vec![478], "UZ".to_owned());
self.add(vec![479], "LK".to_owned());
self.add(vec![480], "PH".to_owned());
self.add(vec![481], "BY".to_owned());
self.add(vec![482], "UA".to_owned());
self.add(vec![484], "MD".to_owned());
self.add(vec![485], "AM".to_owned());
self.add(vec![486], "GE".to_owned());
self.add(vec![487], "KZ".to_owned());
self.add(vec![489], "HK".to_owned());
self.add(vec![490, 499], "JP".to_owned());
self.add(vec![500, 509], "GB".to_owned());
self.add(vec![520], "GR".to_owned());
self.add(vec![528], "LB".to_owned());
self.add(vec![529], "CY".to_owned());
self.add(vec![531], "MK".to_owned());
self.add(vec![535], "MT".to_owned());
self.add(vec![539], "IE".to_owned());
self.add(vec![540, 549], "BE/LU".to_owned());
self.add(vec![560], "PT".to_owned());
self.add(vec![569], "IS".to_owned());
self.add(vec![570, 579], "DK".to_owned());
self.add(vec![590], "PL".to_owned());
self.add(vec![594], "RO".to_owned());
self.add(vec![599], "HU".to_owned());
self.add(vec![600, 601], "ZA".to_owned());
self.add(vec![603], "GH".to_owned());
self.add(vec![608], "BH".to_owned());
self.add(vec![609], "MU".to_owned());
self.add(vec![611], "MA".to_owned());
self.add(vec![613], "DZ".to_owned());
self.add(vec![616], "KE".to_owned());
self.add(vec![618], "CI".to_owned());
self.add(vec![619], "TN".to_owned());
self.add(vec![621], "SY".to_owned());
self.add(vec![622], "EG".to_owned());
self.add(vec![624], "LY".to_owned());
self.add(vec![625], "JO".to_owned());
self.add(vec![626], "IR".to_owned());
self.add(vec![627], "KW".to_owned());
self.add(vec![628], "SA".to_owned());
self.add(vec![629], "AE".to_owned());
self.add(vec![640, 649], "FI".to_owned());
self.add(vec![690, 695], "CN".to_owned());
self.add(vec![700, 709], "NO".to_owned());
self.add(vec![729], "IL".to_owned());
self.add(vec![730, 739], "SE".to_owned());
self.add(vec![740], "GT".to_owned());
self.add(vec![741], "SV".to_owned());
self.add(vec![742], "HN".to_owned());
self.add(vec![743], "NI".to_owned());
self.add(vec![744], "CR".to_owned());
self.add(vec![745], "PA".to_owned());
self.add(vec![746], "DO".to_owned());
self.add(vec![750], "MX".to_owned());
self.add(vec![754, 755], "CA".to_owned());
self.add(vec![759], "VE".to_owned());
self.add(vec![760, 769], "CH".to_owned());
self.add(vec![770], "CO".to_owned());
self.add(vec![773], "UY".to_owned());
self.add(vec![775], "PE".to_owned());
self.add(vec![777], "BO".to_owned());
self.add(vec![779], "AR".to_owned());
self.add(vec![780], "CL".to_owned());
self.add(vec![784], "PY".to_owned());
self.add(vec![785], "PE".to_owned());
self.add(vec![786], "EC".to_owned());
self.add(vec![789, 790], "BR".to_owned());
self.add(vec![800, 839], "IT".to_owned());
self.add(vec![840, 849], "ES".to_owned());
self.add(vec![850], "CU".to_owned());
self.add(vec![858], "SK".to_owned());
self.add(vec![859], "CZ".to_owned());
self.add(vec![860], "YU".to_owned());
self.add(vec![865], "MN".to_owned());
self.add(vec![867], "KP".to_owned());
self.add(vec![868, 869], "TR".to_owned());
self.add(vec![870, 879], "NL".to_owned());
self.add(vec![880], "KR".to_owned());
self.add(vec![885], "TH".to_owned());
self.add(vec![888], "SG".to_owned());
self.add(vec![890], "IN".to_owned());
self.add(vec![893], "VN".to_owned());
self.add(vec![896], "PK".to_owned());
self.add(vec![899], "ID".to_owned());
self.add(vec![900, 919], "AT".to_owned());
self.add(vec![930, 939], "AU".to_owned());
self.add(vec![940, 949], "AZ".to_owned());
self.add(vec![955], "MY".to_owned());
self.add(vec![958], "MO".to_owned());
self.add([0, 19], "US/CA");
self.add([30, 39], "US");
self.add([60, 139], "US/CA");
self.add([300, 379], "FR");
self.add([380, 0], "BG");
self.add([383, 0], "SI");
self.add([385, 0], "HR");
self.add([387, 0], "BA");
self.add([400, 440], "DE");
self.add([450, 459], "JP");
self.add([460, 469], "RU");
self.add([471, 0], "TW");
self.add([474, 0], "EE");
self.add([475, 0], "LV");
self.add([476, 0], "AZ");
self.add([477, 0], "LT");
self.add([478, 0], "UZ");
self.add([479, 0], "LK");
self.add([480, 0], "PH");
self.add([481, 0], "BY");
self.add([482, 0], "UA");
self.add([484, 0], "MD");
self.add([485, 0], "AM");
self.add([486, 0], "GE");
self.add([487, 0], "KZ");
self.add([489, 0], "HK");
self.add([490, 499], "JP");
self.add([500, 509], "GB");
self.add([520, 0], "GR");
self.add([528, 0], "LB");
self.add([529, 0], "CY");
self.add([531, 0], "MK");
self.add([535, 0], "MT");
self.add([539, 0], "IE");
self.add([540, 549], "BE/LU");
self.add([560, 0], "PT");
self.add([569, 0], "IS");
self.add([570, 579], "DK");
self.add([590, 0], "PL");
self.add([594, 0], "RO");
self.add([599, 0], "HU");
self.add([600, 601], "ZA");
self.add([603, 0], "GH");
self.add([608, 0], "BH");
self.add([609, 0], "MU");
self.add([611, 0], "MA");
self.add([613, 0], "DZ");
self.add([616, 0], "KE");
self.add([618, 0], "CI");
self.add([619, 0], "TN");
self.add([621, 0], "SY");
self.add([622, 0], "EG");
self.add([624, 0], "LY");
self.add([625, 0], "JO");
self.add([626, 0], "IR");
self.add([627, 0], "KW");
self.add([628, 0], "SA");
self.add([629, 0], "AE");
self.add([640, 649], "FI");
self.add([690, 695], "CN");
self.add([700, 709], "NO");
self.add([729, 0], "IL");
self.add([730, 739], "SE");
self.add([740, 0], "GT");
self.add([741, 0], "SV");
self.add([742, 0], "HN");
self.add([743, 0], "NI");
self.add([744, 0], "CR");
self.add([745, 0], "PA");
self.add([746, 0], "DO");
self.add([750, 0], "MX");
self.add([754, 755], "CA");
self.add([759, 0], "VE");
self.add([760, 769], "CH");
self.add([770, 0], "CO");
self.add([773, 0], "UY");
self.add([775, 0], "PE");
self.add([777, 0], "BO");
self.add([779, 0], "AR");
self.add([780, 0], "CL");
self.add([784, 0], "PY");
self.add([785, 0], "PE");
self.add([786, 0], "EC");
self.add([789, 790], "BR");
self.add([800, 839], "IT");
self.add([840, 849], "ES");
self.add([850, 0], "CU");
self.add([858, 0], "SK");
self.add([859, 0], "CZ");
self.add([860, 0], "YU");
self.add([865, 0], "MN");
self.add([867, 0], "KP");
self.add([868, 869], "TR");
self.add([870, 879], "NL");
self.add([880, 0], "KR");
self.add([885, 0], "TH");
self.add([888, 0], "SG");
self.add([890, 0], "IN");
self.add([893, 0], "VN");
self.add([896, 0], "PK");
self.add([899, 0], "ID");
self.add([900, 919], "AT");
self.add([930, 939], "AU");
self.add([940, 949], "AZ");
self.add([955, 0], "MY");
self.add([958, 0], "MO");
}
}

View File

@@ -85,19 +85,12 @@ pub trait AbstractRSSReaderTrait: OneDReader {
let ratio: f32 = (firstTwoSum as f32) / (sum as f32);
if ratio >= Self::MIN_FINDER_PATTERN_RATIO && ratio <= Self::MAX_FINDER_PATTERN_RATIO {
// passes ratio test in spec, but see if the counts are unreasonable
// let minCounter = counters.iter().min();
// let maxCounter = counters.iter().max();
let mut minCounter = u32::MAX;
let mut maxCounter = u32::MIN;
for counter in counters {
maxCounter = std::cmp::max(*counter, maxCounter);
minCounter = std::cmp::min(*counter, minCounter);
// if *counter > maxCounter {
// maxCounter = *counter;
// }
// if *counter < minCounter {
// minCounter = *counter;
// }
}
return maxCounter < 10 * minCounter;
}

View File

@@ -93,62 +93,14 @@ pub fn createDecoder<'a>(
let sevenBitEncodationMethod =
GeneralAppIdDecoder::extractNumericValueFromBitArrayWithInformation(information, 1, 7);
match sevenBitEncodationMethod {
56 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"310".to_owned(),
"11".to_owned(),
)))
}
57 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"320".to_owned(),
"11".to_owned(),
)))
}
58 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"310".to_owned(),
"13".to_owned(),
)))
}
59 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"320".to_owned(),
"13".to_owned(),
)))
}
60 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"310".to_owned(),
"15".to_owned(),
)))
}
61 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"320".to_owned(),
"15".to_owned(),
)))
}
62 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"310".to_owned(),
"17".to_owned(),
)))
}
63 => {
return Ok(Box::new(AI013x0x1xDecoder::new(
information,
"320".to_owned(),
"17".to_owned(),
)))
}
56 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "310", "11"))),
57 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "320", "11"))),
58 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "310", "13"))),
59 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "320", "13"))),
60 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "310", "15"))),
61 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "320", "15"))),
62 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "310", "17"))),
63 => return Ok(Box::new(AI013x0x1xDecoder::new(information, "320", "17"))),
_ => {}
}

View File

@@ -35,8 +35,8 @@ use super::{AI01decoder, AI01weightDecoder, AbstractExpandedDecoder, GeneralAppI
pub struct AI013x0x1xDecoder<'a> {
information: &'a BitArray,
decoder: GeneralAppIdDecoder<'a>,
dateCode: String,
firstAIdigits: String,
dateCode: &'static str,
firstAIdigits: &'static str,
}
impl AI01weightDecoder for AI013x0x1xDecoder<'_> {
@@ -88,8 +88,8 @@ impl<'a> AI013x0x1xDecoder<'_> {
pub fn new(
information: &'a BitArray,
firstAIdigits: String,
dateCode: String,
firstAIdigits: &'static str,
dateCode: &'static str,
) -> AI013x0x1xDecoder<'a> {
AI013x0x1xDecoder {
information,

View File

@@ -57,7 +57,6 @@ impl OneDReader for RSS14Reader {
row.reverse();
let rightPair = self.decodePair(&row, true, rowNumber, hints);
Self::addOrTally(&mut self.possibleRightPairs, rightPair);
row.reverse();
for left in &self.possibleLeftPairs {
if left.getCount() > 1 {
for right in &self.possibleRightPairs {
@@ -246,35 +245,33 @@ impl RSS14Reader {
rowNumber: u32,
hints: &DecodingHintDictionary,
) -> Option<Pair> {
let pos_pair = || -> Result<Pair> {
let startEnd = self.findFinderPattern(row, right)?;
let pattern = self.parseFoundFinderPattern(row, rowNumber, right, &startEnd)?;
let startEnd = self.findFinderPattern(row, right).ok()?;
let pattern = self
.parseFoundFinderPattern(row, rowNumber, right, &startEnd)
.ok()?;
if let Some(DecodeHintValue::NeedResultPointCallback(cb)) =
hints.get(&DecodeHintType::NEED_RESULT_POINT_CALLBACK)
{
let startEnd = pattern.getStartEnd();
let mut center: f32 = (startEnd[0] + startEnd[1] - 1) as f32 / 2.0;
if right {
// row is actually reversed
center = row.get_size() as f32 - 1.0 - center;
}
cb(point_f(center, rowNumber as f32));
if let Some(DecodeHintValue::NeedResultPointCallback(cb)) =
hints.get(&DecodeHintType::NEED_RESULT_POINT_CALLBACK)
{
let startEnd = pattern.getStartEnd();
let mut center: f32 = (startEnd[0] + startEnd[1] - 1) as f32 / 2.0;
if right {
// row is actually reversed
center = row.get_size() as f32 - 1.0 - center;
}
cb(point_f(center, rowNumber as f32));
}
let outside = self.decodeDataCharacter(row, &pattern, true)?;
let inside = self.decodeDataCharacter(row, &pattern, false)?;
let outside = self.decodeDataCharacter(row, &pattern, true).ok()?;
let inside = self.decodeDataCharacter(row, &pattern, false).ok()?;
// todo!("must add callback");
// todo!("must add callback");
Ok(Pair::new(
1597 * outside.getValue() + inside.getValue(),
outside.getChecksumPortion() + 4 * inside.getChecksumPortion(),
pattern,
))
}();
pos_pair.ok()
Some(Pair::new(
1597 * outside.getValue() + inside.getValue(),
outside.getChecksumPortion() + 4 * inside.getChecksumPortion(),
pattern,
))
}
fn decodeDataCharacter(

View File

@@ -66,7 +66,7 @@ impl OneDimensionalCodeWriter for TelepenWriter {
for c in decodedContents.chars() {
if c as u32 > 127 {
return Err(Exceptions::illegal_argument_with(
"Telepen only supports ASCII characters.".to_string(),
"Telepen only supports ASCII characters.",
));
}
@@ -133,7 +133,7 @@ impl OneDimensionalCodeWriter for TelepenWriter {
}
"0" => {
return Err(Exceptions::illegal_argument_with(
"Invalid bit combination!".to_string(),
"Invalid bit combination!",
));
}
_ => {

View File

@@ -188,7 +188,7 @@ impl UPCEANExtension5Support {
"99991" =>
// Complementary
{
return Some("0.00".to_string())
return Some("0.00".to_owned())
}
"99990" => return Some("Used".to_owned()),
_ => {}

View File

@@ -237,6 +237,9 @@ impl PlanarYUVLuminanceSource {
}
impl LuminanceSource for PlanarYUVLuminanceSource {
const SUPPORTS_CROP: bool = true;
const SUPPORTS_ROTATION: bool = false;
fn get_row(&self, y: usize) -> Vec<u8> {
if y >= self.get_height() {
// //throw new IllegalArgumentException("Requested row is outside the image: " + y);
@@ -310,10 +313,6 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
self.height
}
fn is_crop_supported(&self) -> bool {
true
}
fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> Result<Self> {
PlanarYUVLuminanceSource::new_with_all(
self.yuv_data.clone(),
@@ -329,10 +328,6 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
.map_err(|_| Exceptions::UNSUPPORTED_OPERATION)
}
fn is_rotate_supported(&self) -> bool {
false
}
fn invert(&mut self) {
self.invert = !self.invert;
}

View File

@@ -56,7 +56,7 @@ impl ErrorCorrectionLevel {
}
}
pub fn get_value(&self) -> u8 {
pub const fn get_value(&self) -> u8 {
match self {
ErrorCorrectionLevel::L => 0x01,
ErrorCorrectionLevel::M => 0x00,
@@ -66,7 +66,7 @@ impl ErrorCorrectionLevel {
}
}
pub fn get_ordinal(&self) -> u8 {
pub const fn get_ordinal(&self) -> u8 {
match self {
ErrorCorrectionLevel::L => 0,
ErrorCorrectionLevel::M => 1,

View File

@@ -28,10 +28,10 @@ use once_cell::sync::Lazy;
pub type VersionRef = &'static Version;
pub static VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::buildVersions);
pub static MICRO_VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::build_micro_versions);
pub static MODEL1_VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::build_model1_versions);
pub static RMQR_VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::build_rmqr_versions);
pub static VERSIONS: Lazy<Box<[Version]>> = Lazy::new(Version::buildVersions);
pub static MICRO_VERSIONS: Lazy<Box<[Version]>> = Lazy::new(Version::build_micro_versions);
pub static MODEL1_VERSIONS: Lazy<Box<[Version]>> = Lazy::new(Version::build_model1_versions);
pub static RMQR_VERSIONS: Lazy<Box<[Version]>> = Lazy::new(Version::build_rmqr_versions);
/**
* See ISO 18004:2006 Annex D.
@@ -54,15 +54,15 @@ pub const VERSION_DECODE_INFO: [u32; 34] = [
pub struct Version {
// private static final Version[] VERSIONS = buildVersions();
versionNumber: u32,
alignmentPatternCenters: Vec<u32>,
ecBlocks: Vec<ECBlocks>,
alignmentPatternCenters: Box<[u32]>,
ecBlocks: Box<[ECBlocks]>,
totalCodewords: u32,
pub(crate) qr_type: Type,
}
impl Version {
pub(super) fn new(
versionNumber: u32,
alignmentPatternCenters: Vec<u32>,
alignmentPatternCenters: Box<[u32]>,
ecBlocks: [ECBlocks; 4],
) -> Self {
let mut total = 0;
@@ -78,17 +78,20 @@ impl Version {
Self {
versionNumber,
alignmentPatternCenters,
ecBlocks: ecBlocks.to_vec(),
totalCodewords: total,
qr_type: if ecBlocks[0].getECCodewordsPerBlock() != 0 {
Type::Model2
} else {
Type::RectMicro
},
ecBlocks: Box::new(ecBlocks),
totalCodewords: total,
}
}
pub(super) fn without_alignment_patterns(versionNumber: u32, ecBlocks: Vec<ECBlocks>) -> Self {
pub(super) fn without_alignment_patterns(
versionNumber: u32,
ecBlocks: Box<[ECBlocks]>,
) -> Self {
let mut total = 0;
let ecCodewords = ecBlocks[0].getECCodewordsPerBlock();
let ecbArray = ecBlocks[0].getECBlocks();
@@ -107,7 +110,7 @@ impl Version {
Self {
versionNumber,
alignmentPatternCenters: Vec::default(),
alignmentPatternCenters: Box::default(),
ecBlocks,
totalCodewords: total,
qr_type: symbol_type,
@@ -118,11 +121,11 @@ impl Version {
self.versionNumber
}
pub fn getAlignmentPatternCenters(&self) -> &[u32] {
pub const fn getAlignmentPatternCenters(&self) -> &[u32] {
&self.alignmentPatternCenters
}
pub fn getTotalCodewords(&self) -> u32 {
pub const fn getTotalCodewords(&self) -> u32 {
self.totalCodewords
}
@@ -131,7 +134,7 @@ impl Version {
// 17 + 4 * self.versionNumber
}
pub fn getECBlocksForLevel(&self, ecLevel: ErrorCorrectionLevel) -> &ECBlocks {
pub const fn getECBlocksForLevel(&self, ecLevel: ErrorCorrectionLevel) -> &ECBlocks {
if ecLevel.get_ordinal() as usize >= self.ecBlocks.len() {
return &self.ecBlocks[ecLevel.get_ordinal() as usize % self.ecBlocks.len()];
}
@@ -293,11 +296,11 @@ impl fmt::Display for Version {
#[derive(Debug, Clone)]
pub struct ECBlocks {
ecCodewordsPerBlock: u32,
ecBlocks: Vec<ECB>,
ecBlocks: Box<[ECB]>,
}
impl ECBlocks {
pub const fn new(ecCodewordsPerBlock: u32, ecBlocks: Vec<ECB>) -> Self {
pub const fn new(ecCodewordsPerBlock: u32, ecBlocks: Box<[ECB]>) -> Self {
Self {
ecCodewordsPerBlock,
ecBlocks,
@@ -310,7 +313,7 @@ impl ECBlocks {
pub fn getNumBlocks(&self) -> u32 {
let mut total = 0;
for ecBlock in &self.ecBlocks {
for ecBlock in self.ecBlocks.iter() {
total += ecBlock.getCount();
}
total

View File

@@ -13,18 +13,18 @@ macro_rules! qr_version {
),+
}
) => {
vec![
Box::new([
$(
Version::without_alignment_patterns(
$version,
vec![
Box::new([
$(
ECBlocks::new($ec_codewords_per_block, vec![ECB::new($count_1,$data_codewords_1),ECB::new($count_2,$data_codewords_2)])
ECBlocks::new($ec_codewords_per_block, Box::new([ECB::new($count_1,$data_codewords_1),ECB::new($count_2,$data_codewords_2)]))
),*
]
])
)
),*
]
])
};
// Model 2 & rMQR
(
@@ -38,27 +38,27 @@ macro_rules! qr_version {
),+
}
) => {
vec![
Box::new([
$(
Version::new($version,
vec![
Box::new([
$(
$alignment_pattern
),*
],
]),
[
$(
ECBlocks::new($ec_codewords_per_block, vec![ECB::new($count_1,$data_codewords_1),ECB::new($count_2,$data_codewords_2)])
ECBlocks::new($ec_codewords_per_block, Box::new([ECB::new($count_1,$data_codewords_1),ECB::new($count_2,$data_codewords_2)]))
),*
]
)
),*
]
])
};
}
impl Version {
pub fn build_micro_versions() -> Vec<Version> {
pub fn build_micro_versions() -> Box<[Version]> {
qr_version!(
{
{1, {2, 1, 3, 0, 0}},
@@ -71,7 +71,7 @@ impl Version {
/**
* See ISO 18004:2006 6.5.1 Table 9
*/
pub fn buildVersions() -> Vec<Version> {
pub fn buildVersions() -> Box<[Version]> {
qr_version!({
{1, {}, {
7, 1, 19, 0, 0,
@@ -316,7 +316,7 @@ impl Version {
})
}
pub fn build_model1_versions() -> Vec<Version> {
pub fn build_model1_versions() -> Box<[Version]> {
qr_version!(
{
{1, {
@@ -407,7 +407,7 @@ impl Version {
)
}
pub fn build_rmqr_versions() -> Vec<Version> {
pub fn build_rmqr_versions() -> Box<[Version]> {
qr_version!(
{
// Version number, alignment pattern centres, `ECBlocks`

View File

@@ -127,7 +127,7 @@ fn testXOR() {
let mut v1 = BitArray::new();
v1.appendBits(0x5555aaaa, 32).expect("append");
let mut v2 = BitArray::new();
v2.appendBits(0xaaaa5555, 32).expect("append");
v2.appendBits(0xaaaa5555_u32, 32).expect("append");
v1.xor(&v2).expect("xor");
assert_eq!(0xffffffff, getUnsignedInt(&v1));
}

View File

@@ -39,6 +39,8 @@ pub struct RGBLuminanceSource {
}
impl LuminanceSource for RGBLuminanceSource {
const SUPPORTS_CROP: bool = true;
/// gets a row, returns an empty row if we are out of bounds.
fn get_row(&self, y: usize) -> Vec<u8> {
if y >= self.get_height() {
@@ -111,10 +113,6 @@ impl LuminanceSource for RGBLuminanceSource {
self.height
}
fn is_crop_supported(&self) -> bool {
true
}
fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> Result<Self> {
RGBLuminanceSource::new_complex(
&self.luminances,

View File

@@ -1,6 +1,6 @@
// dxfilmedge-1
#![cfg(feature = "image")]
#![cfg(feature = "image, experimental_features")]
use rxing::{BarcodeFormat, FilteredImageReader, MultiFormatReader};