From dd82274ad175466b90415cc100435dd9ba606fe9 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Wed, 14 Dec 2022 10:34:12 -0600 Subject: [PATCH] rss_14 passes integration --- src/oned/code_128_reader.rs | 8 +- src/oned/code_39_reader.rs | 4 +- src/oned/code_93_reader.rs | 4 +- src/oned/itf_reader.rs | 8 +- src/oned/one_d_reader.rs | 154 ++++++++++++++-------------- src/oned/rss/abstract_rss_reader.rs | 19 +--- src/oned/rss/rss_14_reader.rs | 95 +++++++---------- src/oned/upc_ean_reader.rs | 8 +- 8 files changed, 132 insertions(+), 168 deletions(-) diff --git a/src/oned/code_128_reader.rs b/src/oned/code_128_reader.rs index 7343343..ad0f7e6 100644 --- a/src/oned/code_128_reader.rs +++ b/src/oned/code_128_reader.rs @@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader; use crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult}; -use super::OneDReader; +use super::{OneDReader, one_d_reader}; /** *

Decodes Code 128 barcodes.

@@ -383,7 +383,7 @@ impl Code128Reader { let mut bestMatch = -1_isize; for startCode in CODE_START_A..=CODE_START_C { // for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) { - let variance = self.patternMatchVariance( + let variance = one_d_reader::patternMatchVariance( &counters, &CODE_PATTERNS[startCode as usize], MAX_INDIVIDUAL_VARIANCE, @@ -428,13 +428,13 @@ impl Code128Reader { counters: &mut [u32; 6], rowOffset: usize, ) -> Result { - self.recordPattern(row, rowOffset, counters)?; + one_d_reader::recordPattern(row, rowOffset, counters)?; let mut bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept let mut bestMatch = -1_isize; for d in 0..CODE_PATTERNS.len() { // for (int d = 0; d < CODE_PATTERNS.len(); d++) { let pattern = &CODE_PATTERNS[d]; - let variance = self.patternMatchVariance(counters, &pattern, MAX_INDIVIDUAL_VARIANCE); + let variance = one_d_reader::patternMatchVariance(counters, &pattern, MAX_INDIVIDUAL_VARIANCE); if variance < bestVariance { bestVariance = variance; bestMatch = d as isize; diff --git a/src/oned/code_39_reader.rs b/src/oned/code_39_reader.rs index 9f8fd06..85f0115 100644 --- a/src/oned/code_39_reader.rs +++ b/src/oned/code_39_reader.rs @@ -19,7 +19,7 @@ use one_d_reader_derive::OneDReader; use crate::common::BitArray; use crate::{BarcodeFormat, Exceptions, RXingResult}; -use super::OneDReader; +use super::{OneDReader, one_d_reader}; /** *

Decodes Code 39 barcodes. Supports "Full ASCII Code 39" if USE_CODE_39_EXTENDED_MODE is set.

@@ -56,7 +56,7 @@ impl OneDReader for Code39Reader { let mut decodedChar; let mut lastStart; loop { - self.recordPattern(row, nextStart, &mut counters)?; + one_d_reader::recordPattern(row, nextStart, &mut counters)?; let pattern = Self::toNarrowWidePattern(&counters); if pattern < 0 { return Err(Exceptions::NotFoundException("".to_owned())); diff --git a/src/oned/code_93_reader.rs b/src/oned/code_93_reader.rs index c8993c2..fa98390 100644 --- a/src/oned/code_93_reader.rs +++ b/src/oned/code_93_reader.rs @@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader; use crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult}; -use super::OneDReader; +use super::{OneDReader, one_d_reader}; /** *

Decodes Code 93 barcodes.

@@ -51,7 +51,7 @@ impl OneDReader for Code93Reader { let mut decodedChar; let mut lastStart; loop { - self.recordPattern(row, nextStart, &mut theCounters)?; + one_d_reader::recordPattern(row, nextStart, &mut theCounters)?; let pattern = Self::toPattern(&theCounters); if pattern < 0 { return Err(Exceptions::NotFoundException("".to_owned())); diff --git a/src/oned/itf_reader.rs b/src/oned/itf_reader.rs index 48bc21f..c505328 100644 --- a/src/oned/itf_reader.rs +++ b/src/oned/itf_reader.rs @@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader; use crate::{common::BitArray, BarcodeFormat, DecodeHintValue, Exceptions, RXingResult}; -use super::OneDReader; +use super::{OneDReader, one_d_reader}; const MAX_AVG_VARIANCE: f32 = 0.38; const MAX_INDIVIDUAL_VARIANCE: f32 = 0.5; @@ -198,7 +198,7 @@ impl ITFReader { while payloadStart < payloadEnd { // Get 10 runs of black/white. - self.recordPattern(row, payloadStart, &mut counterDigitPair)?; + one_d_reader::recordPattern(row, payloadStart, &mut counterDigitPair)?; // Split them into each array for k in 0..5 { // for (int k = 0; k < 5; k++) { @@ -375,7 +375,7 @@ impl ITFReader { counters[counterPosition] += 1; } else { if counterPosition == patternLength - 1 { - if self.patternMatchVariance(&counters, pattern, MAX_INDIVIDUAL_VARIANCE) + if one_d_reader::patternMatchVariance(&counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE { return Ok([patternStart, x]); @@ -412,7 +412,7 @@ impl ITFReader { for i in 0..max { // for (int i = 0; i < max; i++) { let pattern = &PATTERNS[i]; - let variance = self.patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); + let variance = one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); if variance < bestVariance { bestVariance = variance; bestMatch = i as isize; diff --git a/src/oned/one_d_reader.rs b/src/oned/one_d_reader.rs index 7fd4110..60af80f 100644 --- a/src/oned/one_d_reader.rs +++ b/src/oned/one_d_reader.rs @@ -146,6 +146,78 @@ pub trait OneDReader: Reader { return Err(Exceptions::NotFoundException("".to_owned())); } + /** + *

Attempts to decode a one-dimensional barcode format given a single row of + * an image.

+ * + * @param rowNumber row number from top of the row + * @param row the black/white pixel data of the row + * @param hints decode hints + * @return {@link RXingResult} containing encoded string and start/end of barcode + * @throws NotFoundException if no potential barcode is found + * @throws ChecksumException if a potential barcode is found but does not pass its checksum + * @throws FormatException if a potential barcode is found but format is invalid + */ + fn decodeRow( + &mut self, + rowNumber: u32, + row: &BitArray, + hints: &DecodingHintDictionary, + ) -> Result; +} + + +/** + * Determines how closely a set of observed counts of runs of black/white values matches a given + * target pattern. This is reported as the ratio of the total variance from the expected pattern + * proportions across all pattern elements, to the length of the pattern. + * + * @param counters observed counters + * @param pattern expected pattern + * @param maxIndividualVariance The most any counter can differ before we give up + * @return ratio of total variance between counters and pattern compared to total pattern size + */ +pub fn patternMatchVariance( + counters: &[u32], + pattern: &[u32], + maxIndividualVariance: f32, +) -> f32 { + let mut maxIndividualVariance = maxIndividualVariance; + let numCounters = counters.len(); + let mut total = 0.0; + let mut patternLength = 0; + for i in 0..numCounters { + // for (int i = 0; i < numCounters; i++) { + total += counters[i] as f32; + patternLength += pattern[i]; + } + if total < patternLength as f32 { + // If we don't even have one pixel per unit of bar width, assume this is too small + // to reliably match, so fail: + return f32::INFINITY; + } + + let unitBarWidth = total / patternLength as f32; + maxIndividualVariance *= unitBarWidth as f32; + + let mut totalVariance = 0.0; + for x in 0..numCounters { + // for (int x = 0; x < numCounters; x++) { + let counter = counters[x]; + let scaledPattern = (pattern[x] as f32) * unitBarWidth; + let variance = if (counter as f32) > scaledPattern { + counter as f32 - scaledPattern + } else { + scaledPattern - counter as f32 + }; + if variance > maxIndividualVariance { + return f32::INFINITY; + } + totalVariance += variance; + } + return totalVariance / total; +} + /** * Records the size of successive runs of white and black pixels in a row, starting at a given point. * The values are recorded in the given array, and the number of runs recorded is equal to the size @@ -159,8 +231,7 @@ pub trait OneDReader: Reader { * @throws NotFoundException if counters cannot be filled entirely from row before running out * of pixels */ - fn recordPattern( - &self, + pub fn recordPattern( row: &BitArray, start: usize, counters: &mut [u32], @@ -197,8 +268,7 @@ pub trait OneDReader: Reader { Ok(()) } - fn recordPatternInReverse( - &self, + pub fn recordPatternInReverse( row: &BitArray, start: usize, counters: &mut [u32], @@ -217,79 +287,7 @@ pub trait OneDReader: Reader { if numTransitionsLeft >= 0 { return Err(Exceptions::NotFoundException("".to_owned())); } - self.recordPattern(row, start + 1, counters)?; + recordPattern(row, start + 1, counters)?; Ok(()) - } - - /** - * Determines how closely a set of observed counts of runs of black/white values matches a given - * target pattern. This is reported as the ratio of the total variance from the expected pattern - * proportions across all pattern elements, to the length of the pattern. - * - * @param counters observed counters - * @param pattern expected pattern - * @param maxIndividualVariance The most any counter can differ before we give up - * @return ratio of total variance between counters and pattern compared to total pattern size - */ - fn patternMatchVariance( - &self, - counters: &[u32], - pattern: &[u32], - maxIndividualVariance: f32, - ) -> f32 { - let mut maxIndividualVariance = maxIndividualVariance; - let numCounters = counters.len(); - let mut total = 0.0; - let mut patternLength = 0; - for i in 0..numCounters { - // for (int i = 0; i < numCounters; i++) { - total += counters[i] as f32; - patternLength += pattern[i]; - } - if total < patternLength as f32 { - // If we don't even have one pixel per unit of bar width, assume this is too small - // to reliably match, so fail: - return f32::INFINITY; - } - - let unitBarWidth = total / patternLength as f32; - maxIndividualVariance *= unitBarWidth as f32; - - let mut totalVariance = 0.0; - for x in 0..numCounters { - // for (int x = 0; x < numCounters; x++) { - let counter = counters[x]; - let scaledPattern = (pattern[x] as f32) * unitBarWidth; - let variance = if (counter as f32) > scaledPattern { - counter as f32 - scaledPattern - } else { - scaledPattern - counter as f32 - }; - if variance > maxIndividualVariance { - return f32::INFINITY; - } - totalVariance += variance; - } - return totalVariance / total; - } - - /** - *

Attempts to decode a one-dimensional barcode format given a single row of - * an image.

- * - * @param rowNumber row number from top of the row - * @param row the black/white pixel data of the row - * @param hints decode hints - * @return {@link RXingResult} containing encoded string and start/end of barcode - * @throws NotFoundException if no potential barcode is found - * @throws ChecksumException if a potential barcode is found but does not pass its checksum - * @throws FormatException if a potential barcode is found but format is invalid - */ - fn decodeRow( - &mut self, - rowNumber: u32, - row: &BitArray, - hints: &DecodingHintDictionary, - ) -> Result; -} + } \ No newline at end of file diff --git a/src/oned/rss/abstract_rss_reader.rs b/src/oned/rss/abstract_rss_reader.rs index b3af23d..729b7e4 100644 --- a/src/oned/rss/abstract_rss_reader.rs +++ b/src/oned/rss/abstract_rss_reader.rs @@ -14,7 +14,7 @@ * limitations under the License. */ -use crate::{oned::OneDReader, Exceptions}; +use crate::{oned::{OneDReader, one_d_reader}, Exceptions}; /** * Superclass of {@link OneDReader} implementations that read barcodes in the RSS family @@ -43,26 +43,13 @@ pub trait AbstractRSSReaderTrait: OneDReader { // evenCounts = new int[dataCharacterCounters.length / 2]; // } - fn getDecodeFinderCounters(&mut self) -> &mut [u32]; - - fn getDataCharacterCounters(&mut self) -> &mut [u32]; - - fn getOddRoundingErrors(&mut self) -> &mut [f32]; - - fn getEvenRoundingErrors(&mut self) -> &mut [f32]; - - fn getOddCounts(&mut self) -> &mut [u32]; - - fn getEvenCounts(&mut self) -> &mut [u32]; - fn parseFinderValue( - &self, counters: &[u32], finderPatterns: &[[u32; 4]; 9], ) -> Result { for value in 0..finderPatterns.len() { // for (int value = 0; value < finderPatterns.length; value++) { - if self.patternMatchVariance( + if one_d_reader::patternMatchVariance( counters, &finderPatterns[value], Self::MAX_INDIVIDUAL_VARIANCE, @@ -110,7 +97,7 @@ pub trait AbstractRSSReaderTrait: OneDReader { array[index] -= 1; } - fn isFinderPattern(&self, counters: &[u32]) -> bool { + fn isFinderPattern( counters: &[u32]) -> bool { let firstTwoSum = counters[0] + counters[1]; let sum = firstTwoSum + counters[2] + counters[3]; let ratio: f32 = (firstTwoSum as f32) / (sum as f32); diff --git a/src/oned/rss/rss_14_reader.rs b/src/oned/rss/rss_14_reader.rs index 2bff9b6..d2ba498 100644 --- a/src/oned/rss/rss_14_reader.rs +++ b/src/oned/rss/rss_14_reader.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; use crate::{ common::{detector::MathUtils, BitArray}, - oned::OneDReader, + oned::{OneDReader, one_d_reader}, BarcodeFormat, DecodeHintType, DecodingHintDictionary, Exceptions, RXingResult, RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint, }; @@ -41,31 +41,8 @@ pub struct RSS14Reader { evenCounts: [u32; 4], } -impl AbstractRSSReaderTrait for RSS14Reader { - fn getDecodeFinderCounters(&mut self) -> &mut [u32] { - &mut self.decodeFinderCounters - } +impl AbstractRSSReaderTrait for RSS14Reader {} - fn getDataCharacterCounters(&mut self) -> &mut [u32] { - &mut self.dataCharacterCounters - } - - fn getOddRoundingErrors(&mut self) -> &mut [f32] { - &mut self.oddRoundingErrors - } - - fn getEvenRoundingErrors(&mut self) -> &mut [f32] { - &mut self.evenRoundingErrors - } - - fn getOddCounts(&mut self) -> &mut [u32] { - &mut self.oddCounts - } - - fn getEvenCounts(&mut self) -> &mut [u32] { - &mut self.evenCounts - } -} impl OneDReader for RSS14Reader { fn decodeRow( &mut self, @@ -316,17 +293,19 @@ impl RSS14Reader { pattern: &FinderPattern, outsideChar: bool, ) -> Result { - let mut counters = [0_u32; 8]; //self.getDataCharacterCounters(); + let counters = &mut self.dataCharacterCounters; //[0_u32; 8]; //self.getDataCharacterCounters(); //Arrays.fill(counters, 0); // counters.fill(0); + counters.fill(0); + if outsideChar { - self.recordPatternInReverse(row, pattern.getStartEnd()[0], &mut counters)?; + one_d_reader::recordPatternInReverse(row, pattern.getStartEnd()[0], &mut counters[..])?; } else { - self.recordPattern(row, pattern.getStartEnd()[1], &mut counters)?; + one_d_reader::recordPattern(row, pattern.getStartEnd()[1], &mut counters[..])?; // reverse it let mut i = 0; - let mut j = counters.len(); + let mut j = counters.len() -1; while i < j { // for (int i = 0, j = counters.length - 1; i < j; i++, j--) { let temp = counters[i]; @@ -342,10 +321,10 @@ impl RSS14Reader { let elementWidth: f32 = counters.iter().sum::() as f32 / numModules as f32; - let mut oddCounts = [0u32; 4]; //self.getOddCounts(); - let mut evenCounts = [0u32; 4]; // self.getEvenCounts(); - let mut oddRoundingErrors = [0f32; 4]; // self.getOddRoundingErrors(); - let mut evenRoundingErrors = [0f32; 4]; // self.getEvenRoundingErrors(); + // let oddCounts = &mut self.oddCounts;//[0u32; 4]; //self.getOddCounts(); + // let evenCounts = //&mut self.evenCounts;//[0u32; 4]; // self.getEvenCounts(); + // let oddRoundingErrors = //&mut self.oddRoundingErrors;//[0f32; 4]; // self.getOddRoundingErrors(); + // let evenRoundingErrors = &mut self.evenRoundingErrors;//[0f32; 4]; // self.getEvenRoundingErrors(); for i in 0..counters.len() { // for (int i = 0; i < counters.length; i++) { @@ -358,11 +337,11 @@ impl RSS14Reader { } let offset = i / 2; if (i & 0x01) == 0 { - oddCounts[offset] = count; - oddRoundingErrors[offset] = value - count as f32; + self.oddCounts[offset] = count; + self.oddRoundingErrors[offset] = value - count as f32; } else { - evenCounts[offset] = count; - evenRoundingErrors[offset] = value - count as f32; + self.evenCounts[offset] = count; + self.evenRoundingErrors[offset] = value - count as f32; } } @@ -370,27 +349,22 @@ impl RSS14Reader { let mut oddSum = 0; let mut oddChecksumPortion = 0; - for i in (0..oddCounts.len()).rev() { + for i in (0..self.oddCounts.len()).rev() { // for (int i = oddCounts.length - 1; i >= 0; i--) { oddChecksumPortion *= 9; - oddChecksumPortion += oddCounts[i]; - oddSum += oddCounts[i]; + oddChecksumPortion += &self.oddCounts[i]; + oddSum += &self.oddCounts[i]; } let mut evenChecksumPortion = 0; let mut evenSum = 0; - for i in (0..evenCounts.len()).rev() { + for i in (0..self.evenCounts.len()).rev() { // for (int i = evenCounts.length - 1; i >= 0; i--) { evenChecksumPortion *= 9; - evenChecksumPortion += evenCounts[i]; - evenSum += evenCounts[i]; + evenChecksumPortion += self.evenCounts[i]; + evenSum += self.evenCounts[i]; } let checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion; - self.oddCounts = oddCounts; - self.evenCounts = evenCounts; - self.oddRoundingErrors = oddRoundingErrors; - self.evenRoundingErrors = evenRoundingErrors; - if outsideChar { if (oddSum & 0x01) != 0 || oddSum > 12 || oddSum < 4 { return Err(Exceptions::NotFoundException("".to_owned())); @@ -398,8 +372,8 @@ impl RSS14Reader { let group = ((12 - oddSum) / 2) as usize; let oddWidest = Self::OUTSIDE_ODD_WIDEST[group]; let evenWidest = 9 - oddWidest; - let vOdd = rss_utils::getRSSvalue(&oddCounts, oddWidest, false); - let vEven = rss_utils::getRSSvalue(&evenCounts, evenWidest, true); + let vOdd = rss_utils::getRSSvalue(&self.oddCounts, oddWidest, false); + let vEven = rss_utils::getRSSvalue(&self.evenCounts, evenWidest, true); let tEven = Self::OUTSIDE_EVEN_TOTAL_SUBSET[group]; let gSum = Self::OUTSIDE_GSUM[group]; return Ok(DataCharacter::new( @@ -413,8 +387,8 @@ impl RSS14Reader { let group = ((10 - evenSum) / 2) as usize; let oddWidest = Self::INSIDE_ODD_WIDEST[group]; let evenWidest = 9 - oddWidest; - let vOdd = rss_utils::getRSSvalue(&oddCounts, oddWidest, true); - let vEven = rss_utils::getRSSvalue(&evenCounts, evenWidest, false); + let vOdd = rss_utils::getRSSvalue(&self.oddCounts, oddWidest, true); + let vEven = rss_utils::getRSSvalue(&self.evenCounts, evenWidest, false); let tOdd = Self::INSIDE_ODD_TOTAL_SUBSET[group]; let gSum = Self::INSIDE_GSUM[group]; return Ok(DataCharacter::new( @@ -434,7 +408,8 @@ impl RSS14Reader { // counters[1] = 0; // counters[2] = 0; // counters[3] = 0; - let mut counters = [0u32; 4]; + let counters = &mut self.decodeFinderCounters; + counters.fill(0); let width = row.getSize(); let mut isWhite = false; @@ -456,7 +431,7 @@ impl RSS14Reader { counters[counterPosition] += 1; } else { if counterPosition == 3 { - if self.isFinderPattern(&counters) { + if Self::isFinderPattern(counters) { return Ok([patternStart, x]); } patternStart += (counters[0] + counters[1]) as usize; @@ -491,13 +466,17 @@ impl RSS14Reader { } firstElementStart += 1; let firstCounter = startEnd[0] - firstElementStart as usize; + let mut counters = &mut self.decodeFinderCounters; + let counter_len = counters.len(); + let slc = counters[0..counter_len-1].to_vec(); + counters[1..counter_len].copy_from_slice(&slc); // Make 'counters' hold 1-4 // let counters = self.getDecodeFinderCounters(); // System.arraycopy(counters, 0, counters, 1, counters.length - 1); // counters.fill(0); - let mut counters = [0u32; 4]; + counters[0] = firstCounter as u32; - let value = self.parseFinderValue(&counters, &Self::FINDER_PATTERNS)?; + let value = Self::parseFinderValue(counters, &Self::FINDER_PATTERNS)?; let mut start = firstElementStart as usize; let mut end = startEnd[1]; if right { @@ -520,8 +499,8 @@ impl RSS14Reader { outsideChar: bool, numModules: u32, ) -> Result<(), Exceptions> { - let oddSum = self.getOddCounts().iter().sum::(); //MathUtils.sum(getOddCounts()); - let evenSum = self.getEvenCounts().iter().sum::(); //MathUtils.sum(getEvenCounts()); + let oddSum = self.oddCounts.iter().sum::(); //MathUtils.sum(getOddCounts()); + let evenSum = self.evenCounts.iter().sum::(); //MathUtils.sum(getEvenCounts()); let mut incrementOdd = false; let mut decrementOdd = false; diff --git a/src/oned/upc_ean_reader.rs b/src/oned/upc_ean_reader.rs index 46e0eaa..cd2868c 100644 --- a/src/oned/upc_ean_reader.rs +++ b/src/oned/upc_ean_reader.rs @@ -19,7 +19,7 @@ use crate::{ RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, }; -use super::{EANManufacturerOrgSupport, OneDReader, UPCEANExtensionSupport}; +use super::{EANManufacturerOrgSupport, OneDReader, UPCEANExtensionSupport, one_d_reader}; use lazy_static::lazy_static; @@ -433,7 +433,7 @@ pub trait UPCEANReader: OneDReader { counters[counterPosition] += 1; } else { if counterPosition == patternLength - 1 { - if self.patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) + if one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE { return Ok([patternStart, x]); @@ -475,7 +475,7 @@ pub trait UPCEANReader: OneDReader { rowOffset: usize, patterns: &[[u32; 4]], ) -> Result { - self.recordPattern(row, rowOffset, counters)?; + one_d_reader::recordPattern(row, rowOffset, counters)?; let mut bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept let mut bestMatch = -1_isize; let max = patterns.len(); @@ -483,7 +483,7 @@ pub trait UPCEANReader: OneDReader { // for (int i = 0; i < max; i++) { let pattern = &patterns[i]; let variance: f32 = - self.patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); + one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); if variance < bestVariance { bestVariance = variance; bestMatch = i as isize;