From d222a98aad7aa47bcf2fa748752be66a54565742 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Fri, 26 Jan 2024 11:11:50 -0600 Subject: [PATCH] wip: incomplete port checking --- src/binarizer.rs | 5 +- src/binary_bitmap.rs | 7 +- src/common/bit_array.rs | 22 ++ .../base_extentions/bitmatrix.rs | 1 + src/common/cpp_essentials/pattern.rs | 4 + src/common/global_histogram_binarizer.rs | 6 + src/common/hybrid_binarizer.rs | 4 + src/common/line_orientation.rs | 5 + src/common/mod.rs | 3 + src/common/quad.rs | 18 +- src/oned/cpp/dxfilm_edge_reader.rs | 49 +++-- src/oned/cpp/one_d_reader.rs | 194 +++++++++++------- src/rxing_result.rs | 17 +- 13 files changed, 236 insertions(+), 99 deletions(-) create mode 100644 src/common/line_orientation.rs diff --git a/src/binarizer.rs b/src/binarizer.rs index 8b424b3..513e646 100644 --- a/src/binarizer.rs +++ b/src/binarizer.rs @@ -19,7 +19,7 @@ use std::borrow::Cow; use crate::{ - common::{BitArray, BitMatrix, Result}, + common::{BitArray, BitMatrix, LineOrientation, Result}, LuminanceSource, }; @@ -66,6 +66,9 @@ pub trait Binarizer { */ fn get_black_matrix(&self) -> Result<&BitMatrix>; + /// Get a row or column of the image + fn get_black_line(&self, l: usize, lt: LineOrientation) -> Result>; + /** * Creates a new object with the same type as this Binarizer implementation, but with pristine * state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache diff --git a/src/binary_bitmap.rs b/src/binary_bitmap.rs index f4882b6..056c72b 100644 --- a/src/binary_bitmap.rs +++ b/src/binary_bitmap.rs @@ -19,7 +19,7 @@ use std::{borrow::Cow, fmt}; use crate::{ - common::{BitArray, BitMatrix, Result}, + common::{BitArray, BitMatrix, LineOrientation, Result}, Binarizer, LuminanceSource, }; @@ -72,6 +72,11 @@ impl BinaryBitmap { self.binarizer.get_black_row(y) } + /// Get a row or column of the image + pub fn get_black_line(&self, l: usize, lt: LineOrientation) -> Result> { + self.binarizer.get_black_line(l, lt) + } + /** * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or diff --git a/src/common/bit_array.rs b/src/common/bit_array.rs index 79cb0e8..a6b8cf7 100644 --- a/src/common/bit_array.rs +++ b/src/common/bit_array.rs @@ -18,6 +18,7 @@ // import java.util.Arrays; +use std::ops::Index; use std::{cmp, fmt}; use crate::common::Result; @@ -420,6 +421,19 @@ impl From for Vec { impl From for Vec { 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) + } +} + +impl From<&BitArray> for Vec { + fn from(value: &BitArray) -> Self { let mut array = vec![false; value.size]; for (pixel, element) in array.iter_mut().enumerate().take(value.size) { @@ -429,3 +443,11 @@ impl From for Vec { array } } + +impl Index for BitArray { + type Output = bool; + + fn index(&self, index: usize) -> &Self::Output { + &self.get(index) + } +} diff --git a/src/common/cpp_essentials/base_extentions/bitmatrix.rs b/src/common/cpp_essentials/base_extentions/bitmatrix.rs index 4839bcb..a5c19f8 100644 --- a/src/common/cpp_essentials/base_extentions/bitmatrix.rs +++ b/src/common/cpp_essentials/base_extentions/bitmatrix.rs @@ -1,3 +1,4 @@ +use crate::common::cpp_essentials::PatternRow; use crate::common::BitMatrix; use crate::common::Result; use crate::point_f; diff --git a/src/common/cpp_essentials/pattern.rs b/src/common/cpp_essentials/pattern.rs index 7fc7bb5..6e6b288 100644 --- a/src/common/cpp_essentials/pattern.rs +++ b/src/common/cpp_essentials/pattern.rs @@ -51,6 +51,10 @@ impl PatternRow { pub fn sum(&self) -> PatternType { self.0.iter().sum() } + + pub fn rev(&mut self) { + self.0.reverse() + } } impl IntoIterator for PatternRow { diff --git a/src/common/global_histogram_binarizer.rs b/src/common/global_histogram_binarizer.rs index fee8ad1..722f4ee 100644 --- a/src/common/global_histogram_binarizer.rs +++ b/src/common/global_histogram_binarizer.rs @@ -51,6 +51,7 @@ pub struct GlobalHistogramBinarizer { source: LS, black_matrix: OnceCell, black_row_cache: Vec>, + black_column_cache: Vec>, } impl Binarizer for GlobalHistogramBinarizer { @@ -106,6 +107,10 @@ impl Binarizer for GlobalHistogramBinarizer { Ok(Cow::Borrowed(row)) } + fn get_black_line(&self, l: usize, lt: super::LineOrientation) -> Result> { + unimplemented!() + } + // Does not sharpen the data, as this call is intended to only be used by 2D Readers. fn get_black_matrix(&self) -> Result<&BitMatrix> { let matrix = self @@ -137,6 +142,7 @@ impl GlobalHistogramBinarizer { height: source.get_height(), black_matrix: OnceCell::new(), black_row_cache: vec![OnceCell::default(); source.get_height()], + black_column_cache: vec![OnceCell::default(); source.get_width()], source, } } diff --git a/src/common/hybrid_binarizer.rs b/src/common/hybrid_binarizer.rs index 3fd4dbf..bcb1ff8 100644 --- a/src/common/hybrid_binarizer.rs +++ b/src/common/hybrid_binarizer.rs @@ -64,6 +64,10 @@ impl Binarizer for HybridBinarizer { self.ghb.get_black_row(y) } + fn get_black_line(&self, l: usize, lt: super::LineOrientation) -> Result> { + self.ghb.get_black_line(l, lt) + } + /** * Calculates the final BitMatrix once for all requests. This could be called once from the * constructor instead, but there are some advantages to doing it lazily, such as making diff --git a/src/common/line_orientation.rs b/src/common/line_orientation.rs new file mode 100644 index 0000000..8d23cfb --- /dev/null +++ b/src/common/line_orientation.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum LineOrientation { + Row, + Column, +} diff --git a/src/common/mod.rs b/src/common/mod.rs index d011f1d..fe878d1 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -114,6 +114,9 @@ pub use quad::*; pub mod cpp_essentials; +mod line_orientation; +pub use line_orientation::LineOrientation; + #[cfg(feature = "otsu_level")] mod otsu_level_binarizer; #[cfg(feature = "otsu_level")] diff --git a/src/common/quad.rs b/src/common/quad.rs index 39dd1dc..27b2a2e 100644 --- a/src/common/quad.rs +++ b/src/common/quad.rs @@ -1,4 +1,4 @@ -use crate::{point_f, Point}; +use crate::{point_f, Exceptions, Point}; #[derive(Clone, Copy, Debug)] pub struct Quadrilateral(pub [Point; 4]); @@ -272,3 +272,19 @@ impl From<[Point; 4]> for Quadrilateral { Self(value) } } + +impl TryFrom<&Vec> for Quadrilateral { + type Error = Exceptions; + + fn try_from(value: &Vec) -> Result { + if value.len() == 4 { + Ok( + Self( + [value[0], value[1], value[2], value[3]] + ) + ) + }else{ + Err(Exceptions::INDEX_OUT_OF_BOUNDS) + } + } +} \ No newline at end of file diff --git a/src/oned/cpp/dxfilm_edge_reader.rs b/src/oned/cpp/dxfilm_edge_reader.rs index 39d07b8..632ac09 100644 --- a/src/oned/cpp/dxfilm_edge_reader.rs +++ b/src/oned/cpp/dxfilm_edge_reader.rs @@ -5,8 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - common::cpp_essentials::{ - FindLeftGuardBy, FixedPattern, IsRightGuard, PatternView, ToInt, ToIntPos, + common::{ + cpp_essentials::{ + FindLeftGuardBy, FixedPattern, IsRightGuard, PatternView, ToInt, ToIntPos, + }, + BitArray, }, point, point_i, BarcodeFormat, DecodeHintValue, DecodingHintDictionary, Exceptions, PointI, RXingResult, @@ -251,13 +254,20 @@ impl<'a> RowReader for DXFilmEdgeReader<'_> { next.skipSymbol(); // Read the data bits - let mut dataBits: Vec = Vec::default(); - while (next.isValidWithN(1) && dataBits.len() < clock.dataLength() as usize) { + let mut dataBits = BitArray::default(); + while (next.isValidWithN(1) && dataBits.get_size() < clock.dataLength() as usize) { let modules = (next[0] as f32 / clock.moduleSize() + 0.5) as u32; // even index means we are at a bar, otherwise at a space // dataBits.appendBits(if next.index() % 2 == 0 {0xFFFFFFFF} else {0x0}, modules); for i in 0..modules { - dataBits.push((if next.index() % 2 == 0 { 0xFF } else { 0x0 } >> (i - 1)) & 1); + dataBits.appendBits( + if next.index() % 2 == 0 { + 0xFFFFFFFF + } else { + 0x0 + }, + modules as usize, + ); // should it be 0xFFFFFFFF } @@ -265,7 +275,7 @@ impl<'a> RowReader for DXFilmEdgeReader<'_> { } // Check the data track length - if (dataBits.len() != clock.dataLength() as usize) { + if (dataBits.get_size() != clock.dataLength() as usize) { return Err(Exceptions::NOT_FOUND); } @@ -277,31 +287,36 @@ impl<'a> RowReader for DXFilmEdgeReader<'_> { } // The following bits are always white (=false), they are separators. - if (dataBits[0] != 0 - || dataBits[8] != 0 + if (dataBits[0] != false //0 + || dataBits[8] != false //0 || (if clock.hasFrameNr { - (dataBits[20] != 0 || dataBits[22] != 0) + (dataBits[20] != false/*0*/ || dataBits[22] != false/*0*/) } else { - dataBits[14] != 0 + dataBits[14] != false//0 })) { return Err(Exceptions::NOT_FOUND); } // Check the parity bit - let signalSum = dataBits.iter().rev().skip(2).sum::(); //Reduce(dataBits.begin(), dataBits.end() - 2, 0); - let parityBit = *(dataBits.last().unwrap_or(&0)); + let db_hld = Into::>::into(dataBits); //.iter().rev().skip(2).fold(0, |acc, e| acc + u8::from(*e)); + let signalSum = db_hld + .iter() + .rev() + .skip(2) + .fold(0, |acc, e| acc + u8::from(*e)); //dataBits.iter().rev().skip(2).sum::(); //Reduce(dataBits.begin(), dataBits.end() - 2, 0); + let parityBit = u8::from(*(db_hld.last().unwrap_or(&false))); if (signalSum % 2 != parityBit) { return Err(Exceptions::NOT_FOUND); } // Compute the DX 1 number (product number) - let Some(productNumber) = ToIntPos(&dataBits, 1, 7) else { + let Some(productNumber) = ToIntPos(&Into::>::into(dataBits), 1, 7) else { return Err(Exceptions::NOT_FOUND); }; // Compute the DX 2 number (generation number) - let Some(generationNumber) = ToIntPos(&dataBits, 9, 4) else { + let Some(generationNumber) = ToIntPos(&Into::>::into(dataBits), 9, 4) else { return Err(Exceptions::NOT_FOUND); }; @@ -311,9 +326,9 @@ impl<'a> RowReader for DXFilmEdgeReader<'_> { // txt.reserve(10); txt = (productNumber.to_string()) + "-" + (&generationNumber.to_string()); if (clock.hasFrameNr) { - let frameNr = ToIntPos(&dataBits, 13, 6).unwrap_or(0); + let frameNr = ToIntPos(&Into::>::into(dataBits), 13, 6).unwrap_or(0); txt += &("/".to_owned() + &(frameNr.to_string())); - if (dataBits[19] != 0) { + if (dataBits[19] != false/*0*/) { txt += "A"; } } @@ -332,7 +347,7 @@ impl<'a> RowReader for DXFilmEdgeReader<'_> { Ok(RXingResult::new( &txt, - dataBits, + dataBits.into(), Vec::new(), BarcodeFormat::DXFilmEdge, )) diff --git a/src/oned/cpp/one_d_reader.rs b/src/oned/cpp/one_d_reader.rs index da9fa2d..6032056 100644 --- a/src/oned/cpp/one_d_reader.rs +++ b/src/oned/cpp/one_d_reader.rs @@ -8,14 +8,14 @@ use std::any::Any; use std::collections::HashMap; -use crate::common::cpp_essentials::{PatternRow, PatternView}; +use crate::common::cpp_essentials::{GetPatternRow, PatternRow, PatternView}; use crate::Binarizer; use crate::{multi::MultipleBarcodeReader, RXingResult, Reader}; use crate::{ point, BarcodeFormat, BinaryBitmap, DecodingHintDictionary, Exceptions, PointT, ResultPoint, }; -use crate::common::Result; +use crate::common::{LineOrientation, Quadrilateral, Result}; use super::dxfilm_edge_reader::DXFilmEdgeReader; use super::row_reader::RowReader; @@ -32,14 +32,14 @@ pub struct ODReader<'a> { impl<'a> ODReader<'_> { /** - * We're going to examine rows from the middle outward, searching alternately above and below the - * middle, and farther out each time. rowStep is the number of rows between each successive - * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then - * middle + rowStep, then middle - (2 * rowStep), etc. - * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily - * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the - * image if "trying harder". - */ + * We're going to examine rows from the middle outward, searching alternately above and below the + * middle, and farther out each time. rowStep is the number of rows between each successive + * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then + * middle + rowStep, then middle - (2 * rowStep), etc. + * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily + * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the + * image if "trying harder". + */ pub fn DoDecode( reader: &DXFilmEdgeReader, image: &BinaryBitmap, @@ -50,13 +50,15 @@ impl<'a> ODReader<'_> { minLineCount: u32, returnErrors: bool, ) -> Vec { - let res: Vec = Vec::new(); + let mut res: Vec> = Vec::new(); - let decodingState = Vec::new(); + let mut decodingState: Vec<&mut Option> = Vec::new(); // std::vector> decodingState(readers.size()); - let width: i32 = image.get_width() as i32; - let height: i32 = image.get_height() as i32; + let mut minLineCount = minLineCount; + + let mut width: i32 = image.get_width() as i32; + let mut height: i32 = image.get_height() as i32; if (rotate) { std::mem::swap(&mut width, &mut height); @@ -73,36 +75,39 @@ impl<'a> ODReader<'_> { 32 }), ); - let maxLines: i32 = if tryHarder -{height} else // Look at the whole image, not just the center -{15}; // 15 rows spaced 1/32 apart is roughly the middle half of the image + let maxLines: i32 = if tryHarder { + height // Look at the whole image, not just the center + } else { + 15 // 15 rows spaced 1/32 apart is roughly the middle half of the image + }; if (isPure) { minLineCount = 1; } - let checkRows = Vec::new(); + let mut checkRows = Vec::new(); - let bars: PatternRow = PatternRow::new(vec![0; 128]); // e.g. EAN-13 has 59 bars/spaces + let mut bars: PatternRow = PatternRow::new(vec![0; 128]); // e.g. EAN-13 has 59 bars/spaces // bars.reserve(128); // e.g. EAN-13 has 59 bars/spaces // #ifdef PRINT_DEBUG // BitMatrix dbg(width, height); // #endif - 'outer: for i in 0..maxLines { + let mut i = 0; + 'outer: while i < maxLines { // for (int i = 0; i < maxLines; i++) { // Scanning from the middle out. Determine which row we're looking at next: let rowStepsAboveOrBelow: i32 = (i + 1) / 2; let isAbove: bool = (i & 0x01) == 0; // i.e. is x even? - let rowNumber: i32 = middle + let mut rowNumber: i32 = middle + rowStep * (if isAbove { rowStepsAboveOrBelow } else { -rowStepsAboveOrBelow }); - let isCheckRow: bool = false; + let mut isCheckRow: bool = false; if (rowNumber < 0 || rowNumber >= height) { // Oops, if we run off the top or bottom, stop break; @@ -110,18 +115,36 @@ impl<'a> ODReader<'_> { // See if we have additional check rows (see below) to process if (!checkRows.is_empty()) { - --i; - rowNumber = checkRows.back(); - checkRows.pop_back(); + //--i; + i -= 1; + rowNumber = *checkRows.last().unwrap_or(&0); + checkRows.pop(); isCheckRow = true; if (rowNumber < 0 || rowNumber >= height) { continue; } } - if (!image.getPatternRow(rowNumber, if rotate { 90 } else { 0 }, bars)) { + let br: Vec = if let Ok(r) = image.get_black_line( + rowNumber as usize, + if rotate { + LineOrientation::Column + } else { + LineOrientation::Row + }, + ) { + r.as_ref().into() + } else { continue; - } + }; + // let img = if rotate {let a = image.rotate_counter_clockwise(); &a} else {image}; + // let Ok(black_row ) = img.get_black_row(rowNumber as usize) else {continue;}; + // let br : Vec = black_row.as_ref().into(); + GetPatternRow(&br, &mut bars); + + // if (!image.getPatternRow(rowNumber, if rotate { 90 } else { 0 }, bars)) { + // continue; + // } // #ifdef PRINT_DEBUG // bool val = false; @@ -145,7 +168,7 @@ impl<'a> ODReader<'_> { if (upsideDown) { // reverse the row and continue // std::reverse(bars.begin(), bars.end()); - bars.reverse(); + bars.rev(); } let readers = vec![reader]; // Look for a barcode @@ -153,73 +176,75 @@ impl<'a> ODReader<'_> { // for (size_t r = 0; r < readers.size(); ++r) { // If this is a pure symbol, then checking a single non-empty line is sufficient for all but the stacked // DataBar codes. They are the only ones using the decodingState, which we can use as a flag here. - if (isPure && i && !decodingState[r]) { + if (isPure && i > 0 && decodingState[r].is_none()) { continue; } - let next = PatternView::from(bars); + let mut next = PatternView::new(&bars); loop { - let result = readers[r] - .decodePattern(rowNumber, &mut next, decodingState[r]) + let mut result_hld = readers[r] + .decodePattern(rowNumber as u32, &mut next, decodingState[r]) .ok(); - if (result.isValid() || (returnErrors && result.error())) { - IncrementLineCount(&result); + if result_hld.is_some() /*|| (returnErrors && result.is_none())*/ { + let mut result = result_hld.as_mut().unwrap(); + IncrementLineCount(&mut result); if (upsideDown) { // update position (flip horizontally). - let points = result.position(); + let points = result.getPointsMut(); for p in points { // for (auto& p : points) { - p = point(width - p.getX() - 1, p.getY()); + *p = point(width as f32 - p.getX() - 1.0, p.getY()); } - result.addPoints(points); + // result.addPoints(points); // result.setPosition(std::move(points)); } if (rotate) { - let points = result.position(); + let points = result.getPointsMut(); for p in points { // for (auto& p : points) { - p = point(p.getY(), width - p.getX() - 1); + *p = point(p.getY(), width as f32- p.getX() - 1.0); } - result.addPoints(points); + // result.addPoints(points); // result.setPosition(std::move(points)); } // check if we know this code already - for other in res { + for other_hld in res.iter_mut() { + let Some(mut other) = other_hld else{ continue;}; // for (auto& other : res) { - if (result == other) { + if (result == &other) { // merge the position information let dTop = PointT::maxAbsComponent( - other.position().topLeft() - result.position().topLeft(), + other.getPoints()[0] - result.getPoints()[0], ); let dBot = PointT::maxAbsComponent( - other.position().bottomLeft() - result.position().topLeft(), + other.getPoints()[2] - result.getPoints()[0], ); - let points = other.position(); + let mut points = other.getPoints().clone(); if (dTop < dBot || (dTop == dBot && rotate ^ (PointT::sumAbsComponent(points[0]) > PointT::sumAbsComponent( - result.position()[0], + result.getPoints()[0], )))) { - points[0] = result.position()[0]; - points[1] = result.position()[1]; + points[0] = result.getPoints()[0]; + points[1] = result.getPoints()[1]; } else { - points[2] = result.position()[2]; - points[3] = result.position()[3]; + points[2] = result.getPoints()[2]; + points[3] = result.getPoints()[3]; } - other.setPosition(points); - IncrementLineCount(&other); + other.replace_points(points); + IncrementLineCount(&mut other); // clear the result, so we don't insert it again below - result = None; //Result(); + result_hld = None; //Result(); break; } } - if (result.format() != BarcodeFormat::UNSUPORTED_FORMAT) { - res.push(result); + if (result.getBarcodeFormat() != &BarcodeFormat::UNSUPORTED_FORMAT) { + res.push(Some(result.clone())); // res.push_back(std::move(result)); // if we found a valid code we have not seen before but a minLineCount > 1, @@ -234,10 +259,14 @@ impl<'a> ODReader<'_> { } } - if (maxSymbols + if (maxSymbols > 0 && res.iter().fold(0, |acc, e| { - acc + i32::from((r.lineCount() >= minLineCount)) - }) == maxSymbols) + if let Some(itm) = &res[r] { + acc + i32::from((itm.line_count() >= minLineCount as usize)) + }else { + acc + } + }) == maxSymbols as i32) { break 'outer; } @@ -245,43 +274,53 @@ impl<'a> ODReader<'_> { // make sure we make progress and we start the next try on a bar next.shift(2 - (next.index() % 2)); next.extend(); - if !(tryHarder && next.size()) { + if !(tryHarder && next.size() > 0) { break; } } //while (tryHarder && next.size()); } } + i += 1; } // out: // remove all symbols with insufficient line count - let it = res.iter().filter(|e| e.lineCount() < minLineCount); + res.retain(|e| if let Some(itm) = e {itm.line_count() < minLineCount as usize} else {false}); // let it = std::remove_if(res.begin(), res.end(), [&](auto&& r) { return r.lineCount() < minLineCount; }); - res.erase(it, res.end()); + // res.erase(it, res.end()); // if symbols overlap, remove the one with a lower line count - for (i, a) in res.iter().enumerate() { + for (i, a_hld) in res.iter().enumerate() { + let a = a_hld.as_ref().unwrap(); // for (auto a = res.begin(); a != res.end(); ++a){ - for b in res.iter().skip(i) { + for b_hld in res.iter().skip(i) { + let b = b_hld.as_ref().unwrap(); // for (auto b = std::next(a); b != res.end(); ++b){ - if (PointT::HaveIntersectingBoundingBoxes(a.position(), b.position())) { - *(if a.lineCount() < b.lineCount() { a } else { b }) = None; + let Ok(q1) =Quadrilateral::try_from(a.getPoints()) else {continue;}; + let Ok(q2) = Quadrilateral::try_from(b.getPoints()) else {continue;}; + if (Quadrilateral::have_intersecting_bounding_boxes(&q1, &q2)) { + *(if a.line_count() < b.line_count() { + a_hld + } else { + b_hld + }) = None; } } } //TODO: C++20 res.erase_if() - it = res - .iter() - .filter(|r| r.getBarcodeFormat() == BarcodeFormat::None); + res + + .retain(|r| if let Some(itm) = r { + itm.getBarcodeFormat() == &BarcodeFormat::UNSUPORTED_FORMAT } else { false }); // it = std::remove_if(res.begin(), res.end(), [](auto&& r) { return r.format() == BarcodeFormat::None; }); - res.erase(it, res.end()); + // res.erase(it, res.end()); // #ifdef PRINT_DEBUG // SaveAsPBM(dbg, rotate ? "od-log-r.pnm" : "od-log.pnm"); // #endif - res + res.iter().cloned().filter_map(|e| e).collect() } } @@ -291,7 +330,7 @@ impl<'a> ODReader<'_> { hints: &DecodingHintDictionary, image: &BinaryBitmap, ) -> Result { - let result = Self::DoDecode( + let mut result = Self::DoDecode( &self.reader, image, self.try_harder, @@ -315,7 +354,7 @@ impl<'a> ODReader<'_> { ); } - result.first().ok_or(Exceptions::NOT_FOUND) + result.first().cloned().ok_or(Exceptions::NOT_FOUND) // return FirstOrDefault(std::move(result)); } @@ -325,7 +364,7 @@ impl<'a> ODReader<'_> { image: &BinaryBitmap, maxSymbols: u32, ) -> Result> { - let resH = Self::DoDecode( + let mut resH = Self::DoDecode( &self.reader, image, self.try_harder, @@ -335,8 +374,8 @@ impl<'a> ODReader<'_> { self.min_line_count, self.return_errors, ); - if ((!maxSymbols || (resH) < maxSymbols) && self.try_rotate) { - let resV = Self::DoDecode( + if ((!(maxSymbols != 0) || (resH.len()) < maxSymbols as usize) && self.try_rotate) { + let mut resV = Self::DoDecode( &self.reader, image, self.try_harder, @@ -397,7 +436,6 @@ impl<'a> ODReader<'_> { } } -fn IncrementLineCount(r: &RXingResult) { - unimplemented!() - // ++r._lineCount; +fn IncrementLineCount(r: &mut RXingResult) { + r.set_line_count(r.line_count() + 1) } diff --git a/src/rxing_result.rs b/src/rxing_result.rs index f888935..a5bd78e 100644 --- a/src/rxing_result.rs +++ b/src/rxing_result.rs @@ -30,7 +30,7 @@ use serde::{Deserialize, Serialize}; * @author Sean Owen */ #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq)] pub struct RXingResult { text: String, rawBytes: Vec, @@ -39,6 +39,7 @@ pub struct RXingResult { format: BarcodeFormat, resultMetadata: HashMap, timestamp: u128, + line_count: usize, } impl RXingResult { pub fn new( @@ -83,6 +84,7 @@ impl RXingResult { format, resultMetadata: HashMap::new(), timestamp, + line_count: 0, } } @@ -95,6 +97,7 @@ impl RXingResult { format: prev.format, resultMetadata: prev.resultMetadata, timestamp: prev.timestamp, + line_count: prev.line_count, } } @@ -229,6 +232,18 @@ impl RXingResult { pub fn getTimestamp(&self) -> u128 { self.timestamp } + + pub fn line_count(&self) -> usize { + self.line_count + } + + pub fn set_line_count(&mut self, lc: usize) { + self.line_count = lc + } + + pub fn replace_points(&mut self, points: Vec) { + self.resultPoints = points + } } impl fmt::Display for RXingResult {