port finder pattern finder

This commit is contained in:
Henry Schimke
2022-10-07 18:25:46 -05:00
parent 8f831b63e8
commit a205e1e08b
7 changed files with 895 additions and 771 deletions

View File

@@ -23,7 +23,7 @@ use crate::{
BitMatrix, DefaultGridSampler, GridSampler, BitMatrix, DefaultGridSampler, GridSampler,
}, },
exceptions::Exceptions, exceptions::Exceptions,
RXingResultPoint, RXingResultPoint, ResultPoint,
}; };
use super::AztecDetectorResult::AztecDetectorRXingResult; use super::AztecDetectorResult::AztecDetectorRXingResult;

View File

@@ -1,6 +1,6 @@
pub mod MathUtils; pub mod MathUtils;
use crate::common::BitMatrix; use crate::common::BitMatrix;
use crate::{Exceptions, RXingResultPoint}; use crate::{Exceptions, RXingResultPoint, ResultPoint};
/* /*
* Copyright 2009 ZXing authors * Copyright 2009 ZXing authors

View File

@@ -1,8 +1,8 @@
pub mod aztec; pub mod aztec;
pub mod qrcode;
pub mod client; pub mod client;
pub mod common; pub mod common;
mod exceptions; mod exceptions;
pub mod qrcode;
pub use exceptions::Exceptions; pub use exceptions::Exceptions;
@@ -26,10 +26,9 @@ mod PlanarYUVLuminanceSourceTestCase;
#[cfg(test)] #[cfg(test)]
mod RGBLuminanceSourceTestCase; mod RGBLuminanceSourceTestCase;
pub type EncodingHintDictionary = HashMap<EncodeHintType, EncodeHintValue>;
pub type EncodingHintDictionary = HashMap<EncodeHintType,EncodeHintValue>; pub type DecodingHintDictionary = HashMap<DecodeHintType, DecodeHintValue>;
pub type DecodingHintDictionary= HashMap<DecodeHintType,DecodeHintValue>; pub type MetadataDictionary = HashMap<RXingResultMetadataType, RXingResultMetadataValue>;
pub type MetadataDictionary = HashMap<RXingResultMetadataType,RXingResultMetadataValue>;
/* /*
* Copyright 2007 ZXing authors * Copyright 2007 ZXing authors
@@ -54,7 +53,7 @@ pub type MetadataDictionary = HashMap<RXingResultMetadataType,RXingResultMetadat
* *
* @author Sean Owen * @author Sean Owen
*/ */
#[derive(Debug, PartialEq, Eq, Hash,Clone, Copy)] #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum BarcodeFormat { pub enum BarcodeFormat {
/** Aztec 2D barcode format. */ /** Aztec 2D barcode format. */
AZTEC, AZTEC,
@@ -566,7 +565,7 @@ pub enum DecodeHintType {
* *
* @see DecodeHintType#NEED_RESULT_POINT_CALLBACK * @see DecodeHintType#NEED_RESULT_POINT_CALLBACK
*/ */
pub type RXingResultPointCallback = fn(&RXingResultPoint); pub type RXingResultPointCallback = fn(&dyn ResultPoint);
#[derive(Clone)] #[derive(Clone)]
pub enum DecodeHintValue { pub enum DecodeHintValue {
/** /**
@@ -885,21 +884,21 @@ impl From<String> for RXingResultMetadataType {
"OTHER" => RXingResultMetadataType::OTHER, "OTHER" => RXingResultMetadataType::OTHER,
"ORIENTATION" => RXingResultMetadataType::ORIENTATION, "ORIENTATION" => RXingResultMetadataType::ORIENTATION,
"BYTE_SEGMENTS" => RXingResultMetadataType::BYTE_SEGMENTS, "BYTE_SEGMENTS" => RXingResultMetadataType::BYTE_SEGMENTS,
"ERROR_CORRECTION_LEVEL"=> RXingResultMetadataType::ERROR_CORRECTION_LEVEL, "ERROR_CORRECTION_LEVEL" => RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
"ISSUE_NUMBER"=> RXingResultMetadataType::ISSUE_NUMBER, "ISSUE_NUMBER" => RXingResultMetadataType::ISSUE_NUMBER,
"SUGGESTED_PRICE"=> RXingResultMetadataType::SUGGESTED_PRICE, "SUGGESTED_PRICE" => RXingResultMetadataType::SUGGESTED_PRICE,
"POSSIBLE_COUNTRY"=> RXingResultMetadataType::POSSIBLE_COUNTRY, "POSSIBLE_COUNTRY" => RXingResultMetadataType::POSSIBLE_COUNTRY,
"UPC_EAN_EXTENSION"=>RXingResultMetadataType::UPC_EAN_EXTENSION, "UPC_EAN_EXTENSION" => RXingResultMetadataType::UPC_EAN_EXTENSION,
"PDF417_EXTRA_METADATA"=> RXingResultMetadataType::PDF417_EXTRA_METADATA, "PDF417_EXTRA_METADATA" => RXingResultMetadataType::PDF417_EXTRA_METADATA,
"STRUCTURED_APPEND_SEQUENCE"=> RXingResultMetadataType::STRUCTURED_APPEND_SEQUENCE, "STRUCTURED_APPEND_SEQUENCE" => RXingResultMetadataType::STRUCTURED_APPEND_SEQUENCE,
"STRUCTURED_APPEND_PARITY"=>RXingResultMetadataType::STRUCTURED_APPEND_PARITY, "STRUCTURED_APPEND_PARITY" => RXingResultMetadataType::STRUCTURED_APPEND_PARITY,
"SYMBOLOGY_IDENTIFIER"=>RXingResultMetadataType::SYMBOLOGY_IDENTIFIER, "SYMBOLOGY_IDENTIFIER" => RXingResultMetadataType::SYMBOLOGY_IDENTIFIER,
_ => RXingResultMetadataType::OTHER, _ => RXingResultMetadataType::OTHER,
} }
} }
} }
#[derive(Debug,PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum RXingResultMetadataValue { pub enum RXingResultMetadataValue {
/** /**
* Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.
@@ -1174,6 +1173,107 @@ impl fmt::Display for RXingResult {
//package com.google.zxing; //package com.google.zxing;
use crate::common::detector::MathUtils; use crate::common::detector::MathUtils;
pub trait ResultPoint {
fn getX(&self) -> f32;
fn getY(&self) -> f32;
}
pub mod result_point_utils {
use crate::{common::detector::MathUtils, ResultPoint};
/**
* Orders an array of three RXingResultPoints in an order [A,B,C] such that AB is less than AC
* and BC is less than AC, and the angle between BC and BA is less than 180 degrees.
*
* @param patterns array of three {@code RXingResultPoint} to order
*/
pub fn orderBestPatterns<T: ResultPoint+Copy+Clone>(patterns: &mut [T; 3]) {
// Find distances between pattern centers
let zeroOneDistance = MathUtils::distance_float(
patterns[0].getX(),
patterns[0].getY(),
patterns[1].getX(),
patterns[1].getY(),
);
let oneTwoDistance = MathUtils::distance_float(
patterns[1].getX(),
patterns[1].getY(),
patterns[2].getX(),
patterns[2].getY(),
);
let zeroTwoDistance = MathUtils::distance_float(
patterns[0].getX(),
patterns[0].getY(),
patterns[2].getX(),
patterns[2].getY(),
);
let mut pointA; //: &RXingResultPoint;
let mut pointB; //: &RXingResultPoint;
let mut pointC; //: &RXingResultPoint;
// Assume one closest to other two is B; A and C will just be guesses at first
if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance {
pointB = patterns[0];
pointA = patterns[1];
pointC = patterns[2];
} else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance {
pointB = patterns[1];
pointA = patterns[0];
pointC = patterns[2];
} else {
pointB = patterns[2];
pointA = patterns[0];
pointC = patterns[1];
}
// Use cross product to figure out whether A and C are correct or flipped.
// This asks whether BC x BA has a positive z component, which is the arrangement
// we want for A, B, C. If it's negative, then we've got it flipped around and
// should swap A and C.
if crossProductZ(pointA, pointB, pointC) < 0.0f32 {
let temp = pointA;
pointA = pointC;
pointC = temp;
}
let pa = pointA;
let pb = pointB;
let pc = pointC;
patterns[0] = pa;
patterns[1] = pb;
patterns[2] = pc;
}
/**
* @param pattern1 first pattern
* @param pattern2 second pattern
* @return distance between two points
*/
pub fn distance<T:ResultPoint>(pattern1: T, pattern2: T) -> f32 {
return MathUtils::distance_float(
pattern1.getX(),
pattern1.getY(),
pattern2.getX(),
pattern2.getY(),
);
}
/**
* Returns the z component of the cross product between vectors BC and BA.
*/
pub fn crossProductZ<T: ResultPoint>(
pointA: T,
pointB: T,
pointC: T,
) -> f32 {
let bX = pointB.getX();
let bY = pointB.getY();
return ((pointC.getX() - bX) * (pointA.getY() - bY))
- ((pointC.getY() - bY) * (pointA.getX() - bX));
}
}
/** /**
* <p>Encapsulates a point of interest in an image containing a barcode. Typically, this * <p>Encapsulates a point of interest in an image containing a barcode. Typically, this
* would be the location of a finder pattern or the corner of the barcode, for example.</p> * would be the location of a finder pattern or the corner of the barcode, for example.</p>
@@ -1201,100 +1301,16 @@ impl RXingResultPoint {
pub const fn new(x: f32, y: f32) -> Self { pub const fn new(x: f32, y: f32) -> Self {
Self { x, y } Self { x, y }
} }
}
pub fn getX(&self) -> f32 { impl ResultPoint for RXingResultPoint {
fn getX(&self) -> f32 {
return self.x; return self.x;
} }
pub fn getY(&self) -> f32 { fn getY(&self) -> f32 {
return self.y; return self.y;
} }
/**
* Orders an array of three RXingResultPoints in an order [A,B,C] such that AB is less than AC
* and BC is less than AC, and the angle between BC and BA is less than 180 degrees.
*
* @param patterns array of three {@code RXingResultPoint} to order
*/
pub fn orderBestPatterns(patterns: &mut Vec<RXingResultPoint>) {
// Find distances between pattern centers
let zeroOneDistance = MathUtils::distance_float(
patterns[0].getX(),
patterns[0].getY(),
patterns[1].getX(),
patterns[1].getY(),
);
let oneTwoDistance = MathUtils::distance_float(
patterns[1].getX(),
patterns[1].getY(),
patterns[2].getX(),
patterns[2].getY(),
);
let zeroTwoDistance = MathUtils::distance_float(
patterns[0].getX(),
patterns[0].getY(),
patterns[2].getX(),
patterns[2].getY(),
);
let mut pointA: &RXingResultPoint;
let mut pointB: &RXingResultPoint;
let mut pointC: &RXingResultPoint;
// Assume one closest to other two is B; A and C will just be guesses at first
if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance {
pointB = &patterns[0];
pointA = &patterns[1];
pointC = &patterns[2];
} else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance {
pointB = &patterns[1];
pointA = &patterns[0];
pointC = &patterns[2];
} else {
pointB = &patterns[2];
pointA = &patterns[0];
pointC = &patterns[1];
}
// Use cross product to figure out whether A and C are correct or flipped.
// This asks whether BC x BA has a positive z component, which is the arrangement
// we want for A, B, C. If it's negative, then we've got it flipped around and
// should swap A and C.
if RXingResultPoint::crossProductZ(&pointA, &pointB, &pointC) < 0.0f32 {
let temp = pointA;
pointA = pointC;
pointC = temp;
}
let pa = (*pointA).clone();
let pb = (*pointB).clone();
let pc = (*pointC).clone();
patterns[0] = pa;
patterns[1] = pb;
patterns[2] = pc;
}
/**
* @param pattern1 first pattern
* @param pattern2 second pattern
* @return distance between two points
*/
pub fn distance(pattern1: &RXingResultPoint, pattern2: &RXingResultPoint) -> f32 {
return MathUtils::distance_float(pattern1.x, pattern1.y, pattern2.x, pattern2.y);
}
/**
* Returns the z component of the cross product between vectors BC and BA.
*/
pub fn crossProductZ(
pointA: &RXingResultPoint,
pointB: &RXingResultPoint,
pointC: &RXingResultPoint,
) -> f32 {
let bX = pointB.x;
let bY = pointB.y;
return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
}
} }
impl fmt::Display for RXingResultPoint { impl fmt::Display for RXingResultPoint {

View File

@@ -16,7 +16,7 @@
//RXingResultPoint //RXingResultPoint
use crate::RXingResultPoint; use crate::{RXingResultPoint, ResultPoint};
/** /**
* <p>Encapsulates an alignment pattern, which are the smaller square patterns found in * <p>Encapsulates an alignment pattern, which are the smaller square patterns found in
@@ -24,17 +24,27 @@ use crate::RXingResultPoint;
* *
* @author Sean Owen * @author Sean Owen
*/ */
#[derive(Clone)] #[derive(Debug,Clone, Copy,PartialEq)]
pub struct AlignmentPattern { pub struct AlignmentPattern {
estimatedModuleSize: f32, estimatedModuleSize: f32,
internal_result_point: RXingResultPoint, point: (f32, f32),
}
impl ResultPoint for AlignmentPattern {
fn getX(&self) -> f32 {
self.point.0
}
fn getY(&self) -> f32 {
self.point.1
}
} }
impl AlignmentPattern { impl AlignmentPattern {
pub fn new(posX: f32, posY: f32, estimatedModuleSize: f32) -> Self { pub fn new(posX: f32, posY: f32, estimatedModuleSize: f32) -> Self {
Self { Self {
estimatedModuleSize, estimatedModuleSize,
internal_result_point: RXingResultPoint { x: posX, y: posY }, point: (posX, posY),
} }
} }
@@ -43,9 +53,7 @@ impl AlignmentPattern {
* position and size -- meaning, it is at nearly the same center with nearly the same size.</p> * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
*/ */
pub fn aboutEquals(&self, moduleSize: f32, i: f32, j: f32) -> bool { pub fn aboutEquals(&self, moduleSize: f32, i: f32, j: f32) -> bool {
if (i - self.internal_result_point.getY()).abs() <= moduleSize if (i - self.getY()).abs() <= moduleSize && (j - self.getX()).abs() <= moduleSize {
&& (j - self.internal_result_point.getX()).abs() <= moduleSize
{
let moduleSizeDiff = (moduleSize - self.estimatedModuleSize).abs(); let moduleSizeDiff = (moduleSize - self.estimatedModuleSize).abs();
return moduleSizeDiff <= 1.0 || moduleSizeDiff <= self.estimatedModuleSize; return moduleSizeDiff <= 1.0 || moduleSizeDiff <= self.estimatedModuleSize;
} }
@@ -57,13 +65,9 @@ impl AlignmentPattern {
* with a new estimate. It returns a new {@code FinderPattern} containing an average of the two. * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two.
*/ */
pub fn combineEstimate(&self, i: f32, j: f32, newModuleSize: f32) -> AlignmentPattern { pub fn combineEstimate(&self, i: f32, j: f32, newModuleSize: f32) -> AlignmentPattern {
let combinedX = (self.internal_result_point.getX() + j) / 2.0; let combinedX = (self.getX() + j) / 2.0;
let combinedY = (self.internal_result_point.getY() + i) / 2.0; let combinedY = (self.getY() + i) / 2.0;
let combinedModuleSize = (self.estimatedModuleSize + newModuleSize) / 2.0; let combinedModuleSize = (self.estimatedModuleSize + newModuleSize) / 2.0;
AlignmentPattern::new(combinedX, combinedY, combinedModuleSize) AlignmentPattern::new(combinedX, combinedY, combinedModuleSize)
} }
pub fn as_RXingResultPoint(&self) -> &RXingResultPoint {
&self.internal_result_point
}
} }

View File

@@ -306,7 +306,7 @@ impl AlignmentPatternFinder {
// Hadn't found this before; save it // Hadn't found this before; save it
let point = AlignmentPattern::new(centerJ, centerI, estimatedModuleSize); let point = AlignmentPattern::new(centerJ, centerI, estimatedModuleSize);
if self.resultPointCallback.is_some() { if self.resultPointCallback.is_some() {
self.resultPointCallback.as_ref().unwrap()(point.as_RXingResultPoint()); self.resultPointCallback.as_ref().unwrap()(&point);
} }
self.possibleCenters.push(point); self.possibleCenters.push(point);
// if self.resultPointCallback.is_some() { // if self.resultPointCallback.is_some() {

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::RXingResultPoint; use crate::{RXingResultPoint, ResultPoint};
/** /**
* <p>Encapsulates a finder pattern, which are the three square patterns found in * <p>Encapsulates a finder pattern, which are the three square patterns found in
@@ -23,10 +23,21 @@ use crate::RXingResultPoint;
* *
* @author Sean Owen * @author Sean Owen
*/ */
pub struct FinderPattern { #[derive(Debug,Clone, Copy,PartialEq)]
pub struct FinderPattern {
estimatedModuleSize: f32, estimatedModuleSize: f32,
count: usize, count: usize,
internal_result_point: RXingResultPoint, point: (f32, f32),
}
impl ResultPoint for FinderPattern {
fn getX(&self) -> f32 {
self.point.0
}
fn getY(&self) -> f32 {
self.point.1
}
} }
impl FinderPattern { impl FinderPattern {
@@ -38,7 +49,7 @@ impl FinderPattern {
Self { Self {
estimatedModuleSize, estimatedModuleSize,
count, count,
internal_result_point: RXingResultPoint::new(posX, posY), point: (posX, posY),
} }
} }
@@ -55,9 +66,7 @@ impl FinderPattern {
* position and size -- meaning, it is at nearly the same center with nearly the same size.</p> * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
*/ */
pub fn aboutEquals(&self, moduleSize: f32, i: f32, j: f32) -> bool { pub fn aboutEquals(&self, moduleSize: f32, i: f32, j: f32) -> bool {
if (i - self.internal_result_point.getY()).abs() <= moduleSize if (i - self.getY()).abs() <= moduleSize && (j - self.getX()).abs() <= moduleSize {
&& (j - self.internal_result_point.getX()).abs() <= moduleSize
{
let moduleSizeDiff = (moduleSize - self.estimatedModuleSize).abs(); let moduleSizeDiff = (moduleSize - self.estimatedModuleSize).abs();
return moduleSizeDiff <= 1.0 || moduleSizeDiff <= self.estimatedModuleSize; return moduleSizeDiff <= 1.0 || moduleSizeDiff <= self.estimatedModuleSize;
} }
@@ -71,8 +80,8 @@ impl FinderPattern {
*/ */
pub fn combineEstimate(&self, i: f32, j: f32, newModuleSize: f32) -> FinderPattern { pub fn combineEstimate(&self, i: f32, j: f32, newModuleSize: f32) -> FinderPattern {
let combinedCount = self.count as f32 + 1.0; let combinedCount = self.count as f32 + 1.0;
let combinedX = (self.count as f32 * self.internal_result_point.getX() + j) / combinedCount; let combinedX = (self.count as f32 * self.getX() + j) / combinedCount;
let combinedY = (self.count as f32 * self.internal_result_point.getY() + i) / combinedCount; let combinedY = (self.count as f32 * self.getY() + i) / combinedCount;
let combinedModuleSize = let combinedModuleSize =
(self.count as f32 * self.estimatedModuleSize + newModuleSize) / combinedCount; (self.count as f32 * self.estimatedModuleSize + newModuleSize) / combinedCount;
FinderPattern::private_new( FinderPattern::private_new(

File diff suppressed because it is too large Load Diff