mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
Many unwraps, expects, and panics removed or handled. More rustification of the codebase. Squashed commit of the following: commit 80c6483cf8c819496a7b781f9e3a149d1f18d5fe Author: Henry <henry@azule.info> Date: Fri Feb 10 20:36:57 2023 -0600 add other parsed result option commit 412d92ae585e7bf194697f5282dbc045e448bace Author: Henry <henry@azule.info> Date: Fri Feb 10 19:06:34 2023 -0600 fix some panics commit 9108d3e931aadec00fc0bf346ebc52d24e5d8146 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:56:30 2023 -0600 clippy --fix commit 8cd89d314323f54f342f15fc73297b62d418ac79 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:55:45 2023 -0600 some more cleanup in aztec commit fb7f9242e273b85a4bb212f22a185a0dcbfafc36 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:19:54 2023 -0600 cleanup root commit 4fb7c0639830869149332b29be789e891eade3e7 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:50:15 2023 -0600 format commit 3ac271af657b25fbe5ee39cbdf8859e5aa38ea41 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:43:14 2023 -0600 clippy --fix commit 0c5b4c1477159db93a9da9645039f51cd1a7c574 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:04:31 2023 -0600 qrcode cleanup complete commit 70c1d107cc672e45d46567c650c46fece7e7da9c Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 13:28:25 2023 -0600 clippy --fix commit e13263d0f1f2a13dbb59b6e60d8b871a32babc92 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 13:27:44 2023 -0600 qrcode detector cleanup commit f7f2855099e469fe1091868c6099196705d0ae83 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:48:13 2023 -0600 qrcode decoder commit bdbaaba597b3479639c2ed3726465a69e3004471 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:13:18 2023 -0600 clippy --fix commit fd6dbcaeb1f45dc91ae98f0e7c58aad48d67df78 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:12:28 2023 -0600 pdf417 cleanup complete commit 7bbd47604c2639a5eb61bdb5533e71be3bce95a1 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 10:39:28 2023 -0600 clippy --fix commit 8f4962b7bb5f133524fe4d3d4948e5672a88c545 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 10:39:00 2023 -0600 cleanup on pdf417 hie commit 254c8243953776d3c8704dd81529aadd05d5a94e Author: Henry <henry@azule.info> Date: Fri Feb 10 02:51:21 2023 +0000 partway through pdf417 hle commit d4a5b00fde8c0282b0c6e4175a21c1e111b11533 Author: Henry <henry@azule.info> Date: Wed Feb 8 21:35:25 2023 +0000 clippy --fix commit 2bd4a8e218aa963a88997b50bc5a198f9a88205e Author: Henry <henry@azule.info> Date: Wed Feb 8 21:31:55 2023 +0000 pdf417 decode and detect cleanup commit 05130ac54a72c2303045d64507bf6185aa74e531 Author: Henry Schimke <henry@azule.info> Date: Tue Feb 7 08:06:25 2023 -0600 at decodeTextCompaction in decoded_bit_straem_parser commit 924c023a7d2339dfffa6ef0c4a805fb192576796 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 18:22:02 2023 -0600 clippy --fix commit 5cfb81a885c22b4b5ec937a79be31d0815def211 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 18:20:22 2023 -0600 oned cleanup commit 0649b64854baf56a8e3314728d4f6cf4063db8b2 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 11:47:28 2023 -0600 rss cleanup commit 2d3127898fc11f7e65d590e983cda799b798b646 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 10:19:56 2023 -0600 multi cleanup commit 7e8b43a159083a2096123e6204d4d1d359c59981 Author: Henry <henry@azule.info> Date: Sun Feb 5 21:41:59 2023 -0600 cargo fmt commit df8285e8da07b4bffd48ca6e596de3f010eb8d9e Author: Henry <henry@azule.info> Date: Sun Feb 5 21:41:29 2023 -0600 maxicode cleanup commit a51f923a14016eb416ca202b2194258808dde3e7 Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:57 2023 -0600 cargo fmt commit 332d7eef4a25318611025a3fcb0b70c604d917be Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:48 2023 -0600 cleanup datamatrix commit eb2311c476a9c9993f271ab6cf9fd359aedca26f Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:26 2023 -0600 cargo clippy --fix commit 2abaa4c51d287f619d4c7a438f85ba2a30f159cf Author: Henry <henry@azule.info> Date: Sun Feb 5 19:13:02 2023 -0600 finish cleanup in parsers commit 716aa2fbf728716cff36657a5fd80e7bca5276b7 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 17:44:56 2023 -0600 cleanup continues commit 7d843788a49fa9cc82c4616d226c0f882e73612b Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 15:15:09 2023 -0600 common cleanup commit fd251866c68f22d450dd428c93d7a3620bf1be27 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 10:24:54 2023 -0600 cleanup reedsolomon commit 132e27ed1468f5c1ce998516ff5a00687217c3e6 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 09:52:04 2023 -0600 make MathUtils more generic commit d8352b7fff4cb4f9ecc8e8a969710d26ef410e8b Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 09:29:33 2023 -0600 cleanup some string handling in ResultParser There may still be some edge cases where multi-byte characters break the parser
710 lines
28 KiB
Rust
710 lines
28 KiB
Rust
/*
|
|
* Copyright 2013 ZXing authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
use std::{fmt::Display, rc::Rc};
|
|
|
|
use crate::pdf417::pdf_417_common;
|
|
|
|
use super::{
|
|
BarcodeMetadata, BoundingBox, Codeword, DetectionRXingResultColumnTrait,
|
|
DetectionRXingResultRowIndicatorColumn,
|
|
};
|
|
|
|
const ADJUST_ROW_NUMBER_SKIP: u32 = 2;
|
|
|
|
/**
|
|
* @author Guenther Grau
|
|
*/
|
|
pub struct DetectionRXingResult {
|
|
barcodeMetadata: BarcodeMetadata,
|
|
detectionRXingResultColumns: Vec<Option<Box<dyn DetectionRXingResultColumnTrait>>>,
|
|
boundingBox: Rc<BoundingBox>,
|
|
barcodeColumnCount: usize,
|
|
}
|
|
|
|
impl DetectionRXingResult {
|
|
pub fn new(
|
|
barcodeMetadata: BarcodeMetadata,
|
|
boundingBox: Rc<BoundingBox>,
|
|
) -> DetectionRXingResult {
|
|
let mut columns = Vec::with_capacity(barcodeMetadata.getColumnCount() as usize + 2);
|
|
for _i in 0..(barcodeMetadata.getColumnCount() as usize + 2) {
|
|
columns.push(None);
|
|
}
|
|
DetectionRXingResult {
|
|
barcodeColumnCount: barcodeMetadata.getColumnCount() as usize,
|
|
detectionRXingResultColumns: columns,
|
|
barcodeMetadata,
|
|
boundingBox,
|
|
}
|
|
}
|
|
|
|
pub fn getDetectionRXingResultColumns(
|
|
&mut self,
|
|
) -> &Vec<Option<Box<dyn DetectionRXingResultColumnTrait>>> {
|
|
self.adjustIndicatorColumnRowNumbers(0);
|
|
let pos = self.barcodeColumnCount + 1;
|
|
self.adjustIndicatorColumnRowNumbers(pos);
|
|
let mut unadjustedCodewordCount = pdf_417_common::MAX_CODEWORDS_IN_BARCODE;
|
|
let mut previousUnadjustedCount;
|
|
loop {
|
|
previousUnadjustedCount = unadjustedCodewordCount;
|
|
unadjustedCodewordCount = self.adjustRowNumbers();
|
|
if !(unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount) {
|
|
break;
|
|
}
|
|
}
|
|
&self.detectionRXingResultColumns
|
|
}
|
|
|
|
fn adjustIndicatorColumnRowNumbers(
|
|
&mut self,
|
|
pos: usize,
|
|
// detectionRXingResultColumn: &mut Option<DetectionRXingResultColumn>,
|
|
) {
|
|
if let Some(col) = self.detectionRXingResultColumns[pos].as_mut() {
|
|
// if self.detectionRXingResultColumns[pos].is_some() {
|
|
// if (detectionRXingResultColumn != null) {
|
|
// ((DetectionRXingResultRowIndicatorColumn) detectionRXingResultColumn)
|
|
// .adjustCompleteIndicatorColumnRowNumbers(barcodeMetadata);
|
|
// }
|
|
col.as_indicator_row()
|
|
.adjustCompleteIndicatorColumnRowNumbers(&self.barcodeMetadata);
|
|
}
|
|
}
|
|
|
|
// TODO ensure that no detected codewords with unknown row number are left
|
|
// we should be able to estimate the row height and use it as a hint for the row number
|
|
// we should also fill the rows top to bottom and bottom to top
|
|
/**
|
|
* @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords
|
|
* will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers
|
|
*/
|
|
fn adjustRowNumbers(&mut self) -> u32 {
|
|
let unadjustedCount = self.adjustRowNumbersByRow();
|
|
if unadjustedCount == 0 {
|
|
return 0;
|
|
}
|
|
for barcodeColumn in 1..(self.barcodeColumnCount + 1) {
|
|
// for (int barcodeColumn = 1; barcodeColumn < barcodeColumnCount + 1; barcodeColumn++) {
|
|
if self.detectionRXingResultColumns[barcodeColumn].is_some() {
|
|
let codewords_len = self.detectionRXingResultColumns[barcodeColumn]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()
|
|
.len();
|
|
for codewordsRow in 0..codewords_len {
|
|
// for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) {
|
|
if let Some(cw_row) = self.detectionRXingResultColumns[barcodeColumn]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
{
|
|
if !cw_row.hasValidRowNumber() {
|
|
self.adjustRowNumbersWithCodewords(
|
|
barcodeColumn,
|
|
codewordsRow,
|
|
barcodeColumn,
|
|
);
|
|
}
|
|
} else {
|
|
continue;
|
|
}
|
|
// if (codewords[codewordsRow] == null) {
|
|
// continue;
|
|
// }
|
|
// if (!codewords[codewordsRow].hasValidRowNumber()) {
|
|
// self.adjustRowNumbers(barcodeColumn, codewordsRow, codewords);
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
unadjustedCount
|
|
}
|
|
|
|
fn adjustRowNumbersByRow(&mut self) -> u32 {
|
|
self.adjustRowNumbersFromBothRI();
|
|
// TODO we should only do full row adjustments if row numbers of left and right row indicator column match.
|
|
// Maybe it's even better to calculated the height (in codeword rows) and divide it by the number of barcode
|
|
// rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row
|
|
// number starts and ends.
|
|
let unadjustedCount = self.adjustRowNumbersFromLRI();
|
|
unadjustedCount + self.adjustRowNumbersFromRRI()
|
|
}
|
|
|
|
fn adjustRowNumbersFromBothRI(&mut self) {
|
|
if self.detectionRXingResultColumns[0].is_none()
|
|
&& self.detectionRXingResultColumns[self.barcodeColumnCount + 1].is_none()
|
|
{
|
|
return;
|
|
}
|
|
|
|
// let LRIcodewords = self.detectionRXingResultColumns[0].as_ref().unwrap().getCodewords();
|
|
// let RRIcodewords = self.detectionRXingResultColumns[self.barcodeColumnCount as usize + 1].as_ref().unwrap().getCodewords();
|
|
for codewordsRow in 0..self.detectionRXingResultColumns[0]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()
|
|
.len()
|
|
{
|
|
// for (int codewordsRow = 0; codewordsRow < LRIcodewords.length; codewordsRow++) {
|
|
if self.detectionRXingResultColumns[0]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.is_some()
|
|
&& self.detectionRXingResultColumns[self.barcodeColumnCount + 1]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.is_some()
|
|
&& self.detectionRXingResultColumns[0]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getRowNumber()
|
|
== self.detectionRXingResultColumns[self.barcodeColumnCount + 1]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getRowNumber()
|
|
{
|
|
// if (LRIcodewords[codewordsRow] != null &&
|
|
// RRIcodewords[codewordsRow] != null &&
|
|
// LRIcodewords[codewordsRow].getRowNumber() == RRIcodewords[codewordsRow].getRowNumber()) {
|
|
for barcodeColumn in 1..=self.barcodeColumnCount {
|
|
// for (int barcodeColumn = 1; barcodeColumn <= barcodeColumnCount; barcodeColumn++) {
|
|
if self.detectionRXingResultColumns[barcodeColumn].is_some()
|
|
//let Some(dc_col) =
|
|
//&mut self.detectionRXingResultColumns[barcodeColumn]
|
|
{
|
|
if self.detectionRXingResultColumns[barcodeColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow]
|
|
.is_some()
|
|
{
|
|
//let Some(codeword) = &mut self.detectionRXingResultColumns[barcodeColumn].as_mut().unwrap().getCodewordsMut()[codewordsRow] {
|
|
let new_row_number = self.detectionRXingResultColumns[0]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getRowNumber();
|
|
self.detectionRXingResultColumns[barcodeColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow]
|
|
.as_mut()
|
|
.unwrap()
|
|
.setRowNumber(new_row_number);
|
|
if !self.detectionRXingResultColumns[barcodeColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow]
|
|
.as_ref()
|
|
.unwrap()
|
|
.hasValidRowNumber()
|
|
{
|
|
// self.detectionRXingResultColumns[barcodeColumn].getCodewords()[codewordsRow] = None;
|
|
self.detectionRXingResultColumns[barcodeColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow] = None;
|
|
}
|
|
} else {
|
|
continue;
|
|
}
|
|
} else {
|
|
continue;
|
|
}
|
|
// let codeword = self.detectionRXingResultColumns[barcodeColumn].getCodewords()[codewordsRow];
|
|
// if (codeword == null) {
|
|
// continue;
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
// if (detectionRXingResultColumns[0] == null || detectionRXingResultColumns[barcodeColumnCount + 1] == null) {
|
|
// return;
|
|
// }
|
|
}
|
|
|
|
fn adjustRowNumbersFromRRI(&mut self) -> u32 {
|
|
if self.detectionRXingResultColumns[self.barcodeColumnCount + 1].is_none() {
|
|
return 0;
|
|
}
|
|
// if let Some(col) = &self.detectionRXingResultColumns[self.barcodeColumnCount as usize + 1] {
|
|
let mut unadjustedCount = 0;
|
|
let codewords_len = self.detectionRXingResultColumns[self.barcodeColumnCount + 1]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()
|
|
.len();
|
|
for codewordsRow in 0..codewords_len {
|
|
// for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) {
|
|
// if let Some(codeword_col) = codewords[codewordsRow] {
|
|
if self.detectionRXingResultColumns[self.barcodeColumnCount + 1]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.is_none()
|
|
{
|
|
continue;
|
|
}
|
|
let rowIndicatorRowNumber = self.detectionRXingResultColumns
|
|
[self.barcodeColumnCount + 1]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getRowNumber();
|
|
let mut invalidRowCounts = 0;
|
|
let mut barcodeColumn = self.barcodeColumnCount + 1;
|
|
while barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP {
|
|
// for (int barcodeColumn = barcodeColumnCount + 1;
|
|
// barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
|
|
// barcodeColumn--) {
|
|
if let Some(bc_col) = &mut self.detectionRXingResultColumns[barcodeColumn] {
|
|
if let Some(codeword) = &mut bc_col.getCodewordsMut()[codewordsRow] {
|
|
invalidRowCounts = Self::adjustRowNumberIfValid(
|
|
rowIndicatorRowNumber,
|
|
invalidRowCounts,
|
|
codeword,
|
|
);
|
|
if !codeword.hasValidRowNumber() {
|
|
unadjustedCount += 1;
|
|
}
|
|
}
|
|
}
|
|
barcodeColumn -= 1;
|
|
}
|
|
// } else {
|
|
// continue;
|
|
// }
|
|
}
|
|
unadjustedCount
|
|
// } else {
|
|
// 0
|
|
// }
|
|
// if (detectionRXingResultColumns[barcodeColumnCount + 1] == null) {
|
|
// return 0;
|
|
// }
|
|
// int unadjustedCount = 0;
|
|
// Codeword[] codewords = detectionRXingResultColumns[barcodeColumnCount + 1].getCodewords();
|
|
// for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) {
|
|
// if (codewords[codewordsRow] == null) {
|
|
// continue;
|
|
// }
|
|
// int rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();
|
|
// int invalidRowCounts = 0;
|
|
// for (int barcodeColumn = barcodeColumnCount + 1;
|
|
// barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
|
|
// barcodeColumn--) {
|
|
// Codeword codeword = detectionRXingResultColumns[barcodeColumn].getCodewords()[codewordsRow];
|
|
// if (codeword != null) {
|
|
// invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);
|
|
// if (!codeword.hasValidRowNumber()) {
|
|
// unadjustedCount++;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// return unadjustedCount;
|
|
}
|
|
|
|
fn adjustRowNumbersFromLRI(&mut self) -> u32 {
|
|
if self.detectionRXingResultColumns[0].is_none() {
|
|
return 0;
|
|
}
|
|
|
|
// if let Some(col) = &self.detectionRXingResultColumns[0] {
|
|
let mut unadjustedCount = 0;
|
|
let codewords_len = self.detectionRXingResultColumns[0]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()
|
|
.len();
|
|
for codewordsRow in 0..codewords_len {
|
|
// for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) {
|
|
// if let Some(codeword_in_row) = codewords[codewordsRow] {
|
|
if self.detectionRXingResultColumns[0]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.is_none()
|
|
{
|
|
continue;
|
|
}
|
|
let rowIndicatorRowNumber = self.detectionRXingResultColumns[0]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getRowNumber();
|
|
let mut invalidRowCounts = 0;
|
|
let mut barcodeColumn = 1_usize;
|
|
while barcodeColumn < self.barcodeColumnCount + 1
|
|
&& invalidRowCounts < ADJUST_ROW_NUMBER_SKIP
|
|
{
|
|
// for (int barcodeColumn = 1;
|
|
// barcodeColumn < barcodeColumnCount + 1 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
|
|
// barcodeColumn++) {
|
|
if let Some(bc_column) = &mut self.detectionRXingResultColumns[barcodeColumn] {
|
|
if let Some(codeword) = &mut bc_column.getCodewordsMut()[codewordsRow] {
|
|
invalidRowCounts = Self::adjustRowNumberIfValid(
|
|
rowIndicatorRowNumber,
|
|
invalidRowCounts,
|
|
codeword,
|
|
);
|
|
if !codeword.hasValidRowNumber() {
|
|
unadjustedCount += 1;
|
|
}
|
|
}
|
|
}
|
|
// let codeword = self.detectionRXingResultColumns[barcodeColumn].getCodewords()[codewordsRow];
|
|
// if (codeword != null) {
|
|
// invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);
|
|
// if (!codeword.hasValidRowNumber()) {
|
|
// unadjustedCount+=1;
|
|
// }
|
|
// }
|
|
barcodeColumn += 1;
|
|
}
|
|
// } else {
|
|
// continue;
|
|
// }
|
|
// if (codewords[codewordsRow] == null) {
|
|
// continue;
|
|
// }
|
|
// let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();
|
|
// let invalidRowCounts = 0;
|
|
// for (int barcodeColumn = 1;
|
|
// barcodeColumn < barcodeColumnCount + 1 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
|
|
// barcodeColumn++) {
|
|
// Codeword codeword = detectionRXingResultColumns[barcodeColumn].getCodewords()[codewordsRow];
|
|
// if (codeword != null) {
|
|
// invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);
|
|
// if (!codeword.hasValidRowNumber()) {
|
|
// unadjustedCount++;
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
unadjustedCount
|
|
// } else {
|
|
// 0
|
|
// }
|
|
|
|
// if (detectionRXingResultColumns[0] == null) {
|
|
// return 0;
|
|
// }
|
|
// int unadjustedCount = 0;
|
|
// Codeword[] codewords = detectionRXingResultColumns[0].getCodewords();
|
|
// for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) {
|
|
// if (codewords[codewordsRow] == null) {
|
|
// continue;
|
|
// }
|
|
// int rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();
|
|
// int invalidRowCounts = 0;
|
|
// for (int barcodeColumn = 1;
|
|
// barcodeColumn < barcodeColumnCount + 1 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
|
|
// barcodeColumn++) {
|
|
// Codeword codeword = detectionRXingResultColumns[barcodeColumn].getCodewords()[codewordsRow];
|
|
// if (codeword != null) {
|
|
// invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);
|
|
// if (!codeword.hasValidRowNumber()) {
|
|
// unadjustedCount++;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// return unadjustedCount;
|
|
}
|
|
|
|
fn adjustRowNumberIfValid(
|
|
rowIndicatorRowNumber: i32,
|
|
mut invalidRowCounts: u32,
|
|
codeword: &mut Codeword,
|
|
) -> u32 {
|
|
// if let Some(codeword) = codeword {
|
|
if !codeword.hasValidRowNumber() {
|
|
if codeword.isValidRowNumber(rowIndicatorRowNumber) {
|
|
codeword.setRowNumber(rowIndicatorRowNumber);
|
|
invalidRowCounts = 0;
|
|
} else {
|
|
invalidRowCounts += 1;
|
|
}
|
|
}
|
|
invalidRowCounts
|
|
// } else {
|
|
// invalidRowCounts
|
|
// }
|
|
// if (codeword == null) {
|
|
// return invalidRowCounts;
|
|
// }
|
|
// if (!codeword.hasValidRowNumber()) {
|
|
// if (codeword.isValidRowNumber(rowIndicatorRowNumber)) {
|
|
// codeword.setRowNumber(rowIndicatorRowNumber);
|
|
// invalidRowCounts = 0;
|
|
// } else {
|
|
// invalidRowCounts+=1;
|
|
// }
|
|
// }
|
|
// return invalidRowCounts;
|
|
}
|
|
|
|
fn adjustRowNumbersWithCodewords(
|
|
&mut self,
|
|
barcodeColumn: usize,
|
|
codewordsRow: usize,
|
|
codewordsColumn: usize,
|
|
// codewords: &mut [Option<Codeword>],
|
|
) {
|
|
// let codewords = self.detectionRXingResultColumns[codewordsColumn]
|
|
// .as_mut()
|
|
// .unwrap()
|
|
// .getCodewordsMut();
|
|
|
|
let codewords_len = self.detectionRXingResultColumns[codewordsColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()
|
|
.len();
|
|
|
|
// let codeword = &mut codewords[codewordsRow];
|
|
|
|
let previousColumnCodewords = self.detectionRXingResultColumns[barcodeColumn - 1]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()
|
|
.to_vec();
|
|
|
|
let mut nextColumnCodewords = previousColumnCodewords.clone();
|
|
|
|
if self.detectionRXingResultColumns[barcodeColumn + 1].is_some() {
|
|
nextColumnCodewords = self.detectionRXingResultColumns[barcodeColumn + 1]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()
|
|
.to_vec(); //col.getCodewords();
|
|
}
|
|
// if (self.detectionRXingResultColumns[barcodeColumn + 1] != null) {
|
|
// nextColumnCodewords = self.detectionRXingResultColumns[barcodeColumn + 1].getCodewords();
|
|
// }
|
|
|
|
let mut otherCodewords = [None; 14]; // new Codeword[14];
|
|
|
|
otherCodewords[2] = previousColumnCodewords[codewordsRow];
|
|
otherCodewords[3] = nextColumnCodewords[codewordsRow];
|
|
|
|
if codewordsRow > 0 {
|
|
otherCodewords[0] = self.detectionRXingResultColumns[codewordsColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow - 1];
|
|
otherCodewords[4] = previousColumnCodewords[codewordsRow - 1];
|
|
otherCodewords[5] = nextColumnCodewords[codewordsRow - 1];
|
|
}
|
|
if codewordsRow > 1 {
|
|
otherCodewords[8] = self.detectionRXingResultColumns[codewordsColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow - 2];
|
|
otherCodewords[10] = previousColumnCodewords[codewordsRow - 2];
|
|
otherCodewords[11] = nextColumnCodewords[codewordsRow - 2];
|
|
}
|
|
if codewordsRow < codewords_len - 1 {
|
|
otherCodewords[1] = self.detectionRXingResultColumns[codewordsColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow + 1];
|
|
otherCodewords[6] = previousColumnCodewords[codewordsRow + 1];
|
|
otherCodewords[7] = nextColumnCodewords[codewordsRow + 1];
|
|
}
|
|
if codewordsRow < codewords_len - 2 {
|
|
otherCodewords[9] = self.detectionRXingResultColumns[codewordsColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow + 2];
|
|
otherCodewords[12] = previousColumnCodewords[codewordsRow + 2];
|
|
otherCodewords[13] = nextColumnCodewords[codewordsRow + 2];
|
|
}
|
|
for otherCodeword in otherCodewords {
|
|
if Self::adjustRowNumber(
|
|
self.detectionRXingResultColumns[codewordsColumn]
|
|
.as_mut()
|
|
.unwrap()
|
|
.getCodewordsMut()[codewordsRow]
|
|
.as_mut()
|
|
.unwrap(),
|
|
&otherCodeword,
|
|
) {
|
|
return;
|
|
}
|
|
}
|
|
// for (Codeword otherCodeword : otherCodewords) {
|
|
// if (adjustRowNumber(codeword, otherCodeword)) {
|
|
// return;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* @return true, if row number was adjusted, false otherwise
|
|
*/
|
|
fn adjustRowNumber(codeword: &mut Codeword, otherCodeword: &Option<Codeword>) -> bool {
|
|
if let Some(otherCodeword) = otherCodeword {
|
|
if otherCodeword.hasValidRowNumber()
|
|
&& otherCodeword.getBucket() == codeword.getBucket()
|
|
{
|
|
codeword.setRowNumber(otherCodeword.getRowNumber());
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
|
|
pub fn getBarcodeColumnCount(&self) -> usize {
|
|
self.barcodeColumnCount
|
|
}
|
|
|
|
pub fn getBarcodeRowCount(&self) -> u32 {
|
|
self.barcodeMetadata.getRowCount()
|
|
}
|
|
|
|
pub fn getBarcodeECLevel(&self) -> u32 {
|
|
self.barcodeMetadata.getErrorCorrectionLevel()
|
|
}
|
|
|
|
pub fn setBoundingBox(&mut self, boundingBox: Rc<BoundingBox>) {
|
|
self.boundingBox = boundingBox;
|
|
}
|
|
|
|
pub fn getBoundingBox(&self) -> Rc<BoundingBox> {
|
|
self.boundingBox.clone()
|
|
}
|
|
|
|
pub fn setDetectionRXingResultColumn(
|
|
&mut self,
|
|
barcodeColumn: usize,
|
|
detectionRXingResultColumn: Option<impl DetectionRXingResultRowIndicatorColumn + 'static>,
|
|
) {
|
|
self.detectionRXingResultColumns[barcodeColumn] =
|
|
if let Some(detectionRXingResultColumn) = detectionRXingResultColumn {
|
|
Some(Box::new(detectionRXingResultColumn))
|
|
} else {
|
|
None
|
|
};
|
|
}
|
|
|
|
pub fn getDetectionRXingResultColumn(
|
|
&self,
|
|
barcodeColumn: usize,
|
|
) -> &Option<Box<dyn DetectionRXingResultColumnTrait>> {
|
|
&self.detectionRXingResultColumns[barcodeColumn]
|
|
}
|
|
|
|
pub fn getDetectionRXingResultColumnMut(
|
|
&mut self,
|
|
barcodeColumn: usize,
|
|
) -> &mut Option<Box<dyn DetectionRXingResultColumnTrait>> {
|
|
&mut self.detectionRXingResultColumns[barcodeColumn]
|
|
}
|
|
}
|
|
|
|
impl Display for DetectionRXingResult {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let mut rowIndicatorColumn = &self.detectionRXingResultColumns[0];
|
|
if rowIndicatorColumn.is_none() {
|
|
rowIndicatorColumn = &self.detectionRXingResultColumns[self.barcodeColumnCount + 1];
|
|
}
|
|
// try (Formatter formatter = new Formatter()) {
|
|
for codewordsRow in 0..rowIndicatorColumn.as_ref().unwrap().getCodewords().len() {
|
|
// for (int codewordsRow = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) {
|
|
write!(f, "CW {codewordsRow:3}")?;
|
|
// formatter.format("CW %3d:", codewordsRow);
|
|
for barcodeColumn in 0..self.barcodeColumnCount + 2 {
|
|
// for (int barcodeColumn = 0; barcodeColumn < barcodeColumnCount + 2; barcodeColumn++) {
|
|
if self.detectionRXingResultColumns[barcodeColumn].is_none() {
|
|
write!(f, " | ")?;
|
|
// formatter.format(" | ");
|
|
continue;
|
|
}
|
|
let codeword = self.detectionRXingResultColumns[barcodeColumn]
|
|
.as_ref()
|
|
.unwrap()
|
|
.getCodewords()[codewordsRow];
|
|
if codeword.is_none() {
|
|
write!(f, " | ")?;
|
|
// formatter.format(" | ");
|
|
continue;
|
|
}
|
|
write!(
|
|
f,
|
|
" {}|{}",
|
|
codeword.as_ref().unwrap().getRowNumber(),
|
|
codeword.as_ref().unwrap().getValue()
|
|
)?;
|
|
// formatter.format(" %3d|%3d", codeword.getRowNumber(), codeword.getValue());
|
|
}
|
|
// formatter.format("%n");
|
|
writeln!(f)?;
|
|
}
|
|
// return formatter.toString();
|
|
write!(f, "")
|
|
// }
|
|
}
|
|
}
|
|
|
|
// @Override
|
|
// public String toString() {
|
|
// DetectionRXingResultColumn rowIndicatorColumn = detectionRXingResultColumns[0];
|
|
// if (rowIndicatorColumn == null) {
|
|
// rowIndicatorColumn = detectionRXingResultColumns[barcodeColumnCount + 1];
|
|
// }
|
|
// try (Formatter formatter = new Formatter()) {
|
|
// for (int codewordsRow = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) {
|
|
// formatter.format("CW %3d:", codewordsRow);
|
|
// for (int barcodeColumn = 0; barcodeColumn < barcodeColumnCount + 2; barcodeColumn++) {
|
|
// if (detectionRXingResultColumns[barcodeColumn] == null) {
|
|
// formatter.format(" | ");
|
|
// continue;
|
|
// }
|
|
// Codeword codeword = detectionRXingResultColumns[barcodeColumn].getCodewords()[codewordsRow];
|
|
// if (codeword == null) {
|
|
// formatter.format(" | ");
|
|
// continue;
|
|
// }
|
|
// formatter.format(" %3d|%3d", codeword.getRowNumber(), codeword.getValue());
|
|
// }
|
|
// formatter.format("%n");
|
|
// }
|
|
// return formatter.toString();
|
|
// }
|
|
// }
|