likely fix to row indicator problem now a trait

This commit is contained in:
Henry Schimke
2022-12-20 17:43:22 -06:00
parent 925d9338e5
commit a6b9c3efc0
4 changed files with 179 additions and 149 deletions

View File

@@ -23,48 +23,42 @@ use super::{BarcodeMetadata, BarcodeValue, BoundingBox, Codeword, DetectionRXing
/**
* @author Guenther Grau
*/
pub struct DetectionRXingResultRowIndicatorColumn<'a>(DetectionRXingResultColumn<'a>, bool);
impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
pub trait DetectionRXingResultRowIndicatorColumn {
// TODO implement properly
// TODO maybe we should add missing codewords to store the correct row number to make
// finding row numbers for other columns easier
// use row height count to make detection of invalid row numbers more reliable
fn adjustCompleteIndicatorColumnRowNumbers(&mut self, barcodeMetadata: &BarcodeMetadata);
fn getRowHeights(&mut self) -> Option<Vec<u32>>;
fn getBarcodeMetadata(&mut self) -> Option<BarcodeMetadata>;
fn isLeft(&self) -> bool;
}
impl<'a> DetectionRXingResultRowIndicatorColumn for DetectionRXingResultColumn<'_> {
// private final boolean isLeft;
pub fn new(
boundingBox: &'a BoundingBox,
isLeft: bool,
) -> DetectionRXingResultRowIndicatorColumn<'a> {
DetectionRXingResultRowIndicatorColumn(DetectionRXingResultColumn::new(boundingBox), isLeft)
}
fn setRowNumbers(&mut self) {
for codeword_opt in self.0.getCodewordsMut() {
// for (Codeword codeword : getCodewords()) {
if let Some(codeword) = codeword_opt {
// if (codeword != null) {
codeword.setRowNumberAsRowIndicatorColumn();
}
}
}
// TODO implement properly
// TODO maybe we should add missing codewords to store the correct row number to make
// finding row numbers for other columns easier
// use row height count to make detection of invalid row numbers more reliable
pub fn adjustCompleteIndicatorColumnRowNumbers(&mut self, barcodeMetadata: &BarcodeMetadata) {
fn adjustCompleteIndicatorColumnRowNumbers(&mut self, barcodeMetadata: &BarcodeMetadata) {
// let codewords = self.0.getCodewordsMut();
self.setRowNumbers();
Self::removeIncorrectCodewords(self.0.getCodewordsMut(), barcodeMetadata, self.1);
let boundingBox = self.0.getBoundingBox();
let top = if self.1 {
setRowNumbers(self.getCodewordsMut());
let isLeft = self.isLeft.unwrap();
removeIncorrectCodewords(self.getCodewordsMut(), barcodeMetadata, isLeft);
let boundingBox = self.getBoundingBox();
let top = if self.isLeft() {
boundingBox.getTopLeft()
} else {
boundingBox.getTopRight()
};
let bottom = if self.1 {
let bottom = if self.isLeft() {
boundingBox.getBottomLeft()
} else {
boundingBox.getBottomRight()
};
let firstRow = self.0.imageRowToCodewordIndex(top.getY() as u32);
let lastRow = self.0.imageRowToCodewordIndex(bottom.getY() as u32);
let firstRow = self.imageRowToCodewordIndex(top.getY() as u32);
let lastRow = self.imageRowToCodewordIndex(bottom.getY() as u32);
// We need to be careful using the average row height. Barcode could be skewed so that we have smaller and
// taller rows
//float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount();
@@ -73,7 +67,7 @@ impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
let mut currentRowHeight = 0;
for codewordsRow in firstRow..lastRow {
// for (int codewordsRow = firstRow; codewordsRow < lastRow; codewordsRow++) {
if let Some(codeword) = self.0.getCodewordsMut()[codewordsRow] {
if let Some(codeword) = self.getCodewordsMut()[codewordsRow] {
// if (codewords[codewordsRow] == null) {
// continue;
// }
@@ -93,7 +87,7 @@ impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
|| codeword.getRowNumber() >= barcodeMetadata.getRowCount() as i32
|| rowDifference > codewordsRow as i32
{
self.0.getCodewordsMut()[codewordsRow] = None;
self.getCodewordsMut()[codewordsRow] = None;
} else {
let checkedRows;
if maxRowHeight > 2 {
@@ -108,12 +102,12 @@ impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
// there must be (height * rowDifference) number of codewords missing. For now we assume height = 1.
// This should hopefully get rid of most problems already.
closePreviousCodewordFound =
self.0.getCodewords()[codewordsRow as usize - i as usize].is_some();
self.getCodewords()[codewordsRow as usize - i as usize].is_some();
i += 1;
}
if closePreviousCodewordFound {
self.0.getCodewordsMut()[codewordsRow] = None;
self.getCodewordsMut()[codewordsRow] = None;
} else {
barcodeRow = codeword.getRowNumber();
currentRowHeight = 1;
@@ -126,11 +120,11 @@ impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
//return (int) (averageRowHeight + 0.5);
}
pub fn getRowHeights(&mut self) -> Option<Vec<u32>> {
fn getRowHeights(&mut self) -> Option<Vec<u32>> {
if let Some(barcodeMetadata) = self.getBarcodeMetadata() {
self.adjustIncompleteIndicatorColumnRowNumbers(&barcodeMetadata);
adjustIncompleteIndicatorColumnRowNumbers(self, &barcodeMetadata);
let mut result = vec![0; barcodeMetadata.getRowCount() as usize];
for codeword_opt in self.0.getCodewords() {
for codeword_opt in self.getCodewords() {
// for (Codeword codeword : getCodewords()) {
if let Some(codeword) = codeword_opt {
let rowNumber = codeword.getRowNumber();
@@ -151,59 +145,9 @@ impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
}
}
// TODO maybe we should add missing codewords to store the correct row number to make
// finding row numbers for other columns easier
// use row height count to make detection of invalid row numbers more reliable
fn adjustIncompleteIndicatorColumnRowNumbers(&mut self, barcodeMetadata: &BarcodeMetadata) {
let boundingBox = self.0.getBoundingBox();
let top = if self.1 {
boundingBox.getTopLeft()
} else {
boundingBox.getTopRight()
};
let bottom = if self.1 {
boundingBox.getBottomLeft()
} else {
boundingBox.getBottomRight()
};
let firstRow = self.0.imageRowToCodewordIndex(top.getY() as u32);
let lastRow = self.0.imageRowToCodewordIndex(bottom.getY() as u32);
//float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount();
let codewords = self.0.getCodewordsMut();
let mut barcodeRow = -1;
let mut maxRowHeight = 1;
let mut currentRowHeight = 0;
for codewordsRow in firstRow..lastRow {
// for (int codewordsRow = firstRow; codewordsRow < lastRow; codewordsRow++) {
if let Some(codeword) = &mut codewords[codewordsRow] {
codeword.setRowNumberAsRowIndicatorColumn();
let rowDifference = codeword.getRowNumber() - barcodeRow;
// TODO improve handling with case where first row indicator doesn't start with 0
if rowDifference == 0 {
currentRowHeight += 1;
} else if rowDifference == 1 {
maxRowHeight = maxRowHeight.max(currentRowHeight);
currentRowHeight = 1;
barcodeRow = codeword.getRowNumber();
} else if codeword.getRowNumber() >= barcodeMetadata.getRowCount() as i32 {
codewords[codewordsRow] = None;
} else {
barcodeRow = codeword.getRowNumber();
currentRowHeight = 1;
}
} else {
continue;
}
}
//return (int) (averageRowHeight + 0.5);
}
pub fn getBarcodeMetadata(&mut self) -> Option<BarcodeMetadata> {
let codewords = self.0.getCodewordsMut();
fn getBarcodeMetadata(&mut self) -> Option<BarcodeMetadata> {
let isLeft = self.isLeft.unwrap();
let codewords = self.getCodewordsMut();
let mut barcodeColumnCount = BarcodeValue::new();
let mut barcodeRowCountUpperPart = BarcodeValue::new();
let mut barcodeRowCountLowerPart = BarcodeValue::new();
@@ -214,7 +158,7 @@ impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
codeword.setRowNumberAsRowIndicatorColumn();
let rowIndicatorValue = codeword.getValue() % 30;
let mut codewordRowNumber = codeword.getRowNumber();
if !self.1 {
if !isLeft {
codewordRowNumber += 2;
}
match codewordRowNumber % 3 {
@@ -249,63 +193,128 @@ impl<'a> DetectionRXingResultRowIndicatorColumn<'_> {
barcodeRowCountLowerPart.getValue()[0],
barcodeECLevel.getValue()[0],
);
Self::removeIncorrectCodewords(codewords, &barcodeMetadata, self.1);
removeIncorrectCodewords(codewords, &barcodeMetadata, isLeft);
Some(barcodeMetadata)
}
fn removeIncorrectCodewords(
codewords: &mut [Option<Codeword>],
barcodeMetadata: &BarcodeMetadata,
isLeft: bool,
) {
// Remove codewords which do not match the metadata
// TODO Maybe we should keep the incorrect codewords for the start and end positions?
for codewordRow in 0..codewords.len() {
// for (int codewordRow = 0; codewordRow < codewords.length; codewordRow++) {
if let Some(codeword) = codewords[codewordRow] {
let rowIndicatorValue = codeword.getValue() % 30;
let mut codewordRowNumber = codeword.getRowNumber();
if codewordRowNumber > barcodeMetadata.getRowCount() as i32 {
codewords[codewordRow] = None;
continue;
}
if !isLeft {
codewordRowNumber += 2;
}
match codewordRowNumber % 3 {
0 => {
if rowIndicatorValue * 3 + 1 != barcodeMetadata.getRowCountUpperPart() {
codewords[codewordRow] = None;
}
}
1 => {
if rowIndicatorValue / 3 != barcodeMetadata.getErrorCorrectionLevel()
|| rowIndicatorValue % 3 != barcodeMetadata.getRowCountLowerPart()
{
codewords[codewordRow] = None;
}
}
2 => {
if rowIndicatorValue + 1 != barcodeMetadata.getColumnCount() {
codewords[codewordRow] = None;
}
}
_ => {}
}
} else {
continue;
}
fn isLeft(&self) -> bool {
self.isLeft.unwrap()
}
}
// impl Display for DetectionRXingResultRowIndicatorColumn {
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// write!(f, "IsLeft: {} \n {}", self.1, self.0)
// }
// }
fn setRowNumbers(code_words: &mut [Option<Codeword>]) {
for codeword_opt in code_words {
//self.0.getCodewordsMut() {
// for (Codeword codeword : getCodewords()) {
if let Some(codeword) = codeword_opt {
// if (codeword != null) {
codeword.setRowNumberAsRowIndicatorColumn();
}
}
}
pub fn isLeft(&self) -> bool {
self.1
fn removeIncorrectCodewords(
codewords: &mut [Option<Codeword>],
barcodeMetadata: &BarcodeMetadata,
isLeft: bool,
) {
// Remove codewords which do not match the metadata
// TODO Maybe we should keep the incorrect codewords for the start and end positions?
for codewordRow in 0..codewords.len() {
// for (int codewordRow = 0; codewordRow < codewords.length; codewordRow++) {
if let Some(codeword) = codewords[codewordRow] {
let rowIndicatorValue = codeword.getValue() % 30;
let mut codewordRowNumber = codeword.getRowNumber();
if codewordRowNumber > barcodeMetadata.getRowCount() as i32 {
codewords[codewordRow] = None;
continue;
}
if !isLeft {
codewordRowNumber += 2;
}
match codewordRowNumber % 3 {
0 => {
if rowIndicatorValue * 3 + 1 != barcodeMetadata.getRowCountUpperPart() {
codewords[codewordRow] = None;
}
}
1 => {
if rowIndicatorValue / 3 != barcodeMetadata.getErrorCorrectionLevel()
|| rowIndicatorValue % 3 != barcodeMetadata.getRowCountLowerPart()
{
codewords[codewordRow] = None;
}
}
2 => {
if rowIndicatorValue + 1 != barcodeMetadata.getColumnCount() {
codewords[codewordRow] = None;
}
}
_ => {}
}
} else {
continue;
}
}
}
impl Display for DetectionRXingResultRowIndicatorColumn<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "IsLeft: {} \n {}", self.1, self.0)
// TODO maybe we should add missing codewords to store the correct row number to make
// finding row numbers for other columns easier
// use row height count to make detection of invalid row numbers more reliable
fn adjustIncompleteIndicatorColumnRowNumbers(
col: &mut DetectionRXingResultColumn,
barcodeMetadata: &BarcodeMetadata,
) {
let boundingBox = col.getBoundingBox();
let top = if col.isLeft() {
boundingBox.getTopLeft()
} else {
boundingBox.getTopRight()
};
let bottom = if col.isLeft() {
boundingBox.getBottomLeft()
} else {
boundingBox.getBottomRight()
};
let firstRow = col.imageRowToCodewordIndex(top.getY() as u32);
let lastRow = col.imageRowToCodewordIndex(bottom.getY() as u32);
//float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount();
let codewords = col.getCodewordsMut();
let mut barcodeRow = -1;
let mut maxRowHeight = 1;
let mut currentRowHeight = 0;
for codewordsRow in firstRow..lastRow {
// for (int codewordsRow = firstRow; codewordsRow < lastRow; codewordsRow++) {
if let Some(codeword) = &mut codewords[codewordsRow] {
codeword.setRowNumberAsRowIndicatorColumn();
let rowDifference = codeword.getRowNumber() - barcodeRow;
// TODO improve handling with case where first row indicator doesn't start with 0
if rowDifference == 0 {
currentRowHeight += 1;
} else if rowDifference == 1 {
maxRowHeight = maxRowHeight.max(currentRowHeight);
currentRowHeight = 1;
barcodeRow = codeword.getRowNumber();
} else if codeword.getRowNumber() >= barcodeMetadata.getRowCount() as i32 {
codewords[codewordsRow] = None;
} else {
barcodeRow = codeword.getRowNumber();
currentRowHeight = 1;
}
} else {
continue;
}
}
//return (int) (averageRowHeight + 0.5);
}