Skip to content

Commit

Permalink
Merge branch 'rxing-core:main' into 2d_margins
Browse files Browse the repository at this point in the history
  • Loading branch information
snail-with-tea authored Dec 24, 2024
2 parents 287e57b + 4ea071e commit 60f2a4e
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 91 deletions.
2 changes: 1 addition & 1 deletion src/common/BitSourceTestCase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use super::BitSource;
#[test]
fn test_source() {
let bytes: Vec<u8> = vec![1, 2, 3, 4, 5];
let mut source = BitSource::new(bytes);
let mut source = BitSource::new(&bytes);
assert_eq!(40, source.available());
assert_eq!(0, source.readBits(1).unwrap());
assert_eq!(39, source.available());
Expand Down
12 changes: 12 additions & 0 deletions src/common/bit_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,18 @@ impl From<&BitArray> for Vec<bool> {
}
}

impl From<Vec<u8>> for BitArray {
fn from(val: Vec<u8>) -> Self {
let mut new_array = BitArray::with_capacity(val.len());
for (pos, byte) in val.into_iter().enumerate() {
if byte == 0 {
new_array.set(pos)
}
}
new_array
}
}

fn makeArray(size: usize) -> Vec<BaseType> {
vec![0; size.div_ceil(BASE_BITS)]
}
Expand Down
12 changes: 6 additions & 6 deletions src/common/bit_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ use crate::Exceptions;
*
* @author Sean Owen
*/
pub struct BitSource {
bytes: Vec<u8>,
pub struct BitSource<'a> {
bytes: &'a [u8],
byte_offset: usize,
bit_offset: usize,
}

impl BitSource {
impl<'a> BitSource<'a> {
/**
* @param bytes bytes from which this will read bits. Bits will be read from the first byte first.
* Bits are read within a byte from most-significant to least-significant bit.
*/
pub fn new(bytes: Vec<u8>) -> Self {
Self {
pub fn new(bytes: &'a [u8]) -> Self {
BitSource {
bytes,
byte_offset: 0,
bit_offset: 0,
Expand Down Expand Up @@ -175,7 +175,7 @@ impl BitSource {
}
}

impl Read for BitSource {
impl Read for BitSource<'_> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let requested_bytes = buf.len();
let available = self.available();
Expand Down
116 changes: 116 additions & 0 deletions src/common/bitmatrix_sources.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::borrow::Cow;

use crate::{Binarizer, LuminanceSource};

use super::{BitArray, BitMatrix, LineOrientation};

pub struct BitMatrixSource {
base_bitmatrix: BitMatrix,
byte_array: Box<[u8]>,
}

impl BitMatrixSource {
pub fn new(base_bitmatrix: BitMatrix) -> Self {
let mut tmp =
Vec::with_capacity((base_bitmatrix.getWidth() * base_bitmatrix.getHeight()) as usize);
for y in 0..base_bitmatrix.getHeight() {
for x in 0..base_bitmatrix.getWidth() {
tmp.push(if base_bitmatrix.get(x, y) { 255 } else { 0 });
}
}
Self {
base_bitmatrix,
byte_array: tmp.into_boxed_slice(),
}
}
}

impl LuminanceSource for BitMatrixSource {
fn get_row(&self, y: usize) -> Vec<u8> {
self.base_bitmatrix.getRow(y as u32).into()
}

fn get_column(&self, x: usize) -> Vec<u8> {
self.base_bitmatrix.getCol(x as u32).into()
}

fn get_matrix(&self) -> Vec<u8> {
self.byte_array.to_vec()
}

fn get_width(&self) -> usize {
self.base_bitmatrix.getWidth() as usize
}

fn get_height(&self) -> usize {
self.base_bitmatrix.getHeight() as usize
}

fn invert(&mut self) {
for byte in self.byte_array.iter_mut() {
match byte {
0 => *byte = 255,
255 => *byte = 0,
_ => unreachable!(),
}
}
}

fn get_luma8_point(&self, x: usize, y: usize) -> u8 {
if !self.base_bitmatrix.get(x as u32, y as u32) {
0
} else {
255
}
}
}

pub struct BitMatrixBinarizer(BitMatrixSource);
impl Binarizer for BitMatrixBinarizer {
type Source = BitMatrixSource;

fn get_luminance_source(&self) -> &Self::Source {
&self.0
}

fn get_black_row(&self, y: usize) -> super::Result<std::borrow::Cow<BitArray>> {
Ok(Cow::Owned(self.0.get_row(y).into()))
}

fn get_black_row_from_matrix(
&self,
y: usize,
) -> super::Result<std::borrow::Cow<super::BitArray>> {
self.get_black_row(y)
}

fn get_black_matrix(&self) -> super::Result<&super::BitMatrix> {
Ok(&self.0.base_bitmatrix)
}

fn get_black_line(
&self,
l: usize,
lt: super::LineOrientation,
) -> super::Result<std::borrow::Cow<super::BitArray>> {
match lt {
LineOrientation::Row => self.get_black_row(l),
LineOrientation::Column => Ok(Cow::Owned(self.0.get_column(l).into())),
}
}

fn create_binarizer(&self, source: Self::Source) -> Self
where
Self: Sized,
{
Self(source)
}

fn get_width(&self) -> usize {
self.0.get_width()
}

fn get_height(&self) -> usize {
self.0.get_height()
}
}
3 changes: 3 additions & 0 deletions src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,6 @@ pub use adaptive_threshold_binarizer::*;
pub type BitFieldBaseType = usize;
pub const BIT_FIELD_BASE_BITS: usize = BitFieldBaseType::BITS as usize;
pub const BIT_FIELD_SHIFT_BITS: usize = BIT_FIELD_BASE_BITS - 1;

#[cfg(feature = "experimental_features")]
mod bitmatrix_sources;
4 changes: 2 additions & 2 deletions src/datamatrix/decoder/decoded_bit_stream_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ const VALUE_236: &str = "[)>\u{001E}05\u{001D}";
const VALUE_237: &str = "[)>\u{001E}06\u{001D}";

pub fn decode(bytes: &[u8], is_flipped: bool) -> Result<DecoderRXingResult> {
let mut bits = BitSource::new(bytes.to_vec());
let mut bits = BitSource::new(bytes);
let mut result = ECIStringBuilder::with_capacity(100);
let mut resultTrailer = String::new();
let mut byteSegments = Vec::new(); //new ArrayList<>(1);
let mut byteSegments = Vec::new();
let mut mode = Mode::ASCII_ENCODE;
// Could look directly at 'bytes', if we're sure of not having to account for multi byte values
let mut fnc1Positions = Vec::new();
Expand Down
107 changes: 30 additions & 77 deletions src/datamatrix/encoder/error_correction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,125 +151,78 @@ const ALOG: [u32; 255] = {
* @return the codewords with interleaved error correction.
*/
pub fn encodeECC200(codewords: &str, symbolInfo: &SymbolInfo) -> Result<String> {
if codewords.chars().count() != symbolInfo.getDataCapacity() as usize {
let codewords: Vec<u8> = codewords.chars().map(|c| c as u8).collect();

if codewords.len() != symbolInfo.getDataCapacity() as usize {
return Err(Exceptions::illegal_argument_with(
"The number of codewords does not match the selected symbol",
));
}
let mut sb = String::with_capacity(
(symbolInfo.getDataCapacity() + symbolInfo.getErrorCodewords()) as usize,
);
sb.push_str(codewords);

let mut sb = vec![0; (symbolInfo.getDataCapacity() + symbolInfo.getErrorCodewords()) as usize];
sb[..codewords.len()].copy_from_slice(&codewords);

let blockCount = symbolInfo.getInterleavedBlockCount() as usize;
if blockCount == 1 {
let ecc = createECCBlock(codewords, symbolInfo.getErrorCodewords() as usize)?;
sb.push_str(&ecc);
let ecc = createECCBlock(&codewords, symbolInfo.getErrorCodewords() as usize)?;
sb[codewords.len()..ecc.len() + codewords.len()].copy_from_slice(ecc.as_slice());
} else {
//sb.setLength(sb.capacity());
sb.push_str(
&vec![
char::default();
(symbolInfo.getDataCapacity() + symbolInfo.getErrorCodewords()) as usize
- sb.chars().count()
]
.into_iter()
.collect::<String>(),
);
let mut dataSizes = vec![0u32; blockCount];
let mut errorSizes = vec![0u32; blockCount];
for i in 0..blockCount {
dataSizes[i] = symbolInfo.getDataLengthForInterleavedBlock(i as u32 + 1) as u32;
errorSizes[i] = symbolInfo.getErrorLengthForInterleavedBlock(i as u32 + 1);
}
for block in 0..blockCount {
let mut temp = String::with_capacity(dataSizes[block] as usize);
let mut temp = Vec::with_capacity(dataSizes[block] as usize);
let mut d = block;
while d < symbolInfo.getDataCapacity() as usize {
temp.push(
codewords
.chars()
.nth(d)
.ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)?,
);
temp.push(codewords[d]);

d += blockCount;
}
let ecc = createECCBlock(&temp, errorSizes[block] as usize)?;
let mut pos = 0;
let mut e = block;
while e < errorSizes[block] as usize * blockCount {
let (char_index, _) = sb
.char_indices()
.nth(symbolInfo.getDataCapacity() as usize + e)
.ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)?;
sb.replace_range(
char_index..(char_index + 1),
&ecc.chars()
.nth(pos)
.ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)?
.to_string(),
);
sb[symbolInfo.getDataCapacity() as usize + e] = ecc[pos];
pos += 1;

e += blockCount;
}
}
}

Ok(sb)
Ok(sb.into_iter().map(|c| c as char).collect())
}

fn createECCBlock(codewords: &str, numECWords: usize) -> Result<String> {
let mut table = -1_isize;
for (i, set) in FACTOR_SETS.iter().enumerate() {
// for i in 0..FACTOR_SETS.len() {
// for (int i = 0; i < FACTOR_SETS.length; i++) {
if set == &(numECWords as u32) {
table = i as isize;
break;
}
}
if table < 0 {
return Err(Exceptions::illegal_argument_with(format!(
"Illegal number of error correction codewords specified: {numECWords}"
)));
}
let poly = FACTORS[table as usize];
let mut ecc = vec![0 as char; numECWords];
// for i in 0..numECWords {
// // for (int i = 0; i < numECWords; i++) {
// ecc[i] = 0;
// }
for i in 0..codewords.chars().count() {
// for (int i = 0; i < codewords.length(); i++) {
let m = ecc[numECWords - 1] as usize
^ codewords
.chars()
.nth(i)
.ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)? as usize;
fn createECCBlock(codewords: &[u8], numECWords: usize) -> Result<Vec<u8>> {
let table = FACTOR_SETS
.iter()
.position(|&set| set == numECWords as u32)
.ok_or_else(|| {
Exceptions::illegal_argument_with(format!(
"Illegal number of error correction codewords specified: {numECWords}"
))
})?;

let poly = FACTORS[table];
let mut ecc = vec![0u8; numECWords];
for codeword in codewords {
let m = ecc[numECWords - 1] as usize ^ *codeword as usize;
for k in (1..numECWords).rev() {
// for (int k = numECWords - 1; k > 0; k--) {
if m != 0 && poly[k] != 0 {
ecc[k] = char::from_u32(
ecc[k - 1] as u32 ^ ALOG[(LOG[m] + LOG[poly[k] as usize]) as usize % 255],
)
.ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)?;
ecc[k] = ecc[k - 1] ^ ALOG[(LOG[m] + LOG[poly[k] as usize]) as usize % 255] as u8;
} else {
ecc[k] = ecc[k - 1];
}
}
if m != 0 && poly[0] != 0 {
ecc[0] = char::from_u32(ALOG[(LOG[m] + LOG[poly[0] as usize]) as usize % 255])
.ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)?;
ecc[0] = ALOG[(LOG[m] + LOG[poly[0] as usize]) as usize % 255] as u8;
} else {
ecc[0] = 0 as char;
ecc[0] = 0;
}
}
// let eccReversed = new char[numECWords];
// for (int i = 0; i < numECWords; i++) {
// eccReversed[i] = ecc[numECWords - i - 1];
// }
// return String.valueOf(eccReversed);
Ok(ecc.into_iter().rev().collect())
}

Expand Down
2 changes: 1 addition & 1 deletion src/qrcode/cpp_port/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ pub fn DecodeBitStream(
version: &Version,
ecLevel: ErrorCorrectionLevel,
) -> Result<DecoderResult<bool>> {
let mut bits = BitSource::new(bytes.to_vec());
let mut bits = BitSource::new(bytes);
let mut result = ECIStringBuilder::default();
// Error error;
result.symbology = SymbologyIdentifier {
Expand Down
2 changes: 1 addition & 1 deletion src/qrcode/decoder/decoded_bit_stream_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub fn decode(
ecLevel: ErrorCorrectionLevel,
hints: &DecodingHintDictionary,
) -> Result<DecoderRXingResult> {
let mut bits = BitSource::new(bytes.to_owned());
let mut bits = BitSource::new(bytes);
let mut result = ECIStringBuilder::with_capacity(50); //String::with_capacity(50);
let mut byteSegments: std::vec::Vec<std::vec::Vec<u8>> = vec![];
let mut symbolSequence = -1;
Expand Down
9 changes: 6 additions & 3 deletions tests/github_issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,12 +591,12 @@ fn issue_59() {
use rand::prelude::*;
use rxing::BufferedImageLuminanceSource;

const TEST_SIZE: usize = 1556;
const TEST_SIZE: usize = 1400;
const TEST_2_SIZE: usize = 100;

let mut rnd_data = [0; TEST_SIZE];
rand::thread_rng().fill_bytes(&mut rnd_data);
let data = rnd_data.iter().map(|c| *c as char).collect::<String>();
let data = rnd_data.into_iter().map(|c| c as char).collect::<String>();

let writer = rxing::datamatrix::DataMatrixWriter;
let data_matrix = writer
Expand All @@ -605,7 +605,10 @@ fn issue_59() {

let mut rnd_data_2 = [0; TEST_2_SIZE];
rand::thread_rng().fill_bytes(&mut rnd_data_2);
let data2 = rnd_data_2.iter().map(|c| *c as char).collect::<String>();
let data2 = rnd_data_2
.into_iter()
.map(|c| c as char)
.collect::<String>();

let mut hints = EncodingHintDictionary::default();
hints.insert(
Expand Down

0 comments on commit 60f2a4e

Please sign in to comment.