partial port of finder pattern finder

This commit is contained in:
Henry Schimke
2022-10-06 18:05:52 -05:00
parent 978a44f5d7
commit 8f831b63e8
2 changed files with 64 additions and 68 deletions

View File

@@ -14,20 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.zxing.qrcode.detector; use crate::{common::BitMatrix, RXingResultPointCallback, DecodingHintDictionary};
import com.google.zxing.DecodeHintType; use super::{FinderPattern, FinderPatternInfo};
import com.google.zxing.NotFoundException;
import com.google.zxing.RXingResultPoint;
import com.google.zxing.RXingResultPointCallback;
import com.google.zxing.common.BitMatrix;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/** /**
* <p>This class attempts to find finder patterns in a QR Code. Finder patterns are the square * <p>This class attempts to find finder patterns in a QR Code. Finder patterns are the square
@@ -37,44 +27,48 @@ import java.util.Map;
* *
* @author Sean Owen * @author Sean Owen
*/ */
public class FinderPatternFinder { pub struct FinderPatternFinder {
private static final int CENTER_QUORUM = 2; image:BitMatrix,
private static final EstimatedModuleComparator moduleComparator = new EstimatedModuleComparator(); possibleCenters:Vec<FinderPattern>,
protected static final int MIN_SKIP = 3; // 1 pixel/module times 3 modules/center hasSkipped:bool,
protected static final int MAX_MODULES = 97; // support up to version 20 for mobile clients crossCheckStateCount:Vec<u32>,
resultPointCallback:Option<RXingResultPointCallback>,
private final BitMatrix image; }
private final List<FinderPattern> possibleCenters; impl FinderPatternFinder{
private boolean hasSkipped; const CENTER_QUORUM :u32= 2;
private final int[] crossCheckStateCount; // private static final EstimatedModuleComparator moduleComparator = new EstimatedModuleComparator();
private final RXingResultPointCallback resultPointCallback; const MIN_SKIP :u32 = 3; // 1 pixel/module times 3 modules/center
const MAX_MODULES:u32 = 97; // support up to version 20 for mobile clients
/** /**
* <p>Creates a finder that will search the image for three finder patterns.</p> * <p>Creates a finder that will search the image for three finder patterns.</p>
* *
* @param image image to search * @param image image to search
*/ */
public FinderPatternFinder(BitMatrix image) { pub fn new( image:BitMatrix) -> Self{
this(image, null); Self::with_callback(image, None)
} }
public FinderPatternFinder(BitMatrix image, RXingResultPointCallback resultPointCallback) { pub fn with_callback( image:BitMatrix, resultPointCallback:Option<RXingResultPointCallback>) -> Self{
this.image = image; Self {
this.possibleCenters = new ArrayList<>(); image,
this.crossCheckStateCount = new int[5]; possibleCenters: Vec::new(),
this.resultPointCallback = resultPointCallback; hasSkipped: false,
crossCheckStateCount: [0u32;5],
resultPointCallback,
}
} }
protected final BitMatrix getImage() { pub fn getImage(&self) -> &BitMatrix{
return image; &self.image
} }
protected final List<FinderPattern> getPossibleCenters() { pub fn getPossibleCenters(&self) -> &Vec<FinderPattern>{
return possibleCenters; &self.possibleCenters
} }
final FinderPatternInfo find(Map<DecodeHintType,?> hints) throws NotFoundException { pub fn find(&self, hints:&DecodingHintDictionary) -> Result<FinderPatternInfo,Exceptions> {
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
int maxI = image.getHeight(); int maxI = image.getHeight();
int maxJ = image.getWidth(); int maxJ = image.getWidth();
@@ -171,7 +165,7 @@ public class FinderPatternFinder {
* Given a count of black/white/black/white/black pixels just seen and an end position, * Given a count of black/white/black/white/black pixels just seen and an end position,
* figures the location of the center of this run. * figures the location of the center of this run.
*/ */
private static float centerFromEnd(int[] stateCount, int end) { fn centerFromEnd(stateCount:&[u32], end:u32) -> f32 {
return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0f; return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0f;
} }
@@ -180,7 +174,7 @@ public class FinderPatternFinder {
* @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios
* used by finder patterns to be considered a match * used by finder patterns to be considered a match
*/ */
protected static boolean foundPatternCross(int[] stateCount) { pub fn foundPatternCross( stateCount:&[u32]) -> bool{
int totalModuleSize = 0; int totalModuleSize = 0;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
int count = stateCount[i]; int count = stateCount[i];
@@ -208,7 +202,7 @@ public class FinderPatternFinder {
* @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios
* used by finder patterns to be considered a match * used by finder patterns to be considered a match
*/ */
protected static boolean foundPatternDiagonal(int[] stateCount) { pub fn foundPatternDiagonal( stateCount: &[u32]) -> bool{
int totalModuleSize = 0; int totalModuleSize = 0;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
int count = stateCount[i]; int count = stateCount[i];
@@ -231,26 +225,26 @@ public class FinderPatternFinder {
Math.abs(moduleSize - stateCount[4]) < maxVariance; Math.abs(moduleSize - stateCount[4]) < maxVariance;
} }
private int[] getCrossCheckStateCount() { fn getCrossCheckStateCount(&self) -> &[u32] {
doClearCounts(crossCheckStateCount); doClearCounts(crossCheckStateCount);
return crossCheckStateCount; return crossCheckStateCount;
} }
@Deprecated #[deprecated]
protected final void clearCounts(int[] counts) { pub fn clearCounts(&self, counts:&[u32]) {
doClearCounts(counts); doClearCounts(counts);
} }
@Deprecated #[deprecated]
protected final void shiftCounts2(int[] stateCount) { pub fn shiftCounts2(&self, stateCount:&[u32]) {
doShiftCounts2(stateCount); doShiftCounts2(stateCount);
} }
protected static void doClearCounts(int[] counts) { pub fn doClearCounts(icounts:&[u32]) {
Arrays.fill(counts, 0); Arrays.fill(counts, 0);
} }
protected static void doShiftCounts2(int[] stateCount) { pub fn doShiftCounts2( stateCount:&[u32]) {
stateCount[0] = stateCount[2]; stateCount[0] = stateCount[2];
stateCount[1] = stateCount[3]; stateCount[1] = stateCount[3];
stateCount[2] = stateCount[4]; stateCount[2] = stateCount[4];
@@ -267,7 +261,7 @@ public class FinderPatternFinder {
* @param centerJ center of the section that appears to cross a finder pattern * @param centerJ center of the section that appears to cross a finder pattern
* @return true if proportions are withing expected limits * @return true if proportions are withing expected limits
*/ */
private boolean crossCheckDiagonal(int centerI, int centerJ) { fn crossCheckDiagonal(&self, centerI:u32, centerJ:u32) -> bool{
int[] stateCount = getCrossCheckStateCount(); int[] stateCount = getCrossCheckStateCount();
// Start counting up, left from center finding black center mass // Start counting up, left from center finding black center mass
@@ -338,8 +332,8 @@ public class FinderPatternFinder {
* observed in any reading state, based on the results of the horizontal scan * observed in any reading state, based on the results of the horizontal scan
* @return vertical center of finder pattern, or {@link Float#NaN} if not found * @return vertical center of finder pattern, or {@link Float#NaN} if not found
*/ */
private float crossCheckVertical(int startI, int centerJ, int maxCount, fn crossCheckVertical( &self, startI:u32, centerJ:u32, maxCount:u32,
int originalStateCountTotal) { originalStateCountTotal:u32) -> f32{
BitMatrix image = this.image; BitMatrix image = this.image;
int maxI = image.getHeight(); int maxI = image.getHeight();
@@ -410,8 +404,8 @@ public class FinderPatternFinder {
* except it reads horizontally instead of vertically. This is used to cross-cross * except it reads horizontally instead of vertically. This is used to cross-cross
* check a vertical cross check and locate the real center of the alignment pattern.</p> * check a vertical cross check and locate the real center of the alignment pattern.</p>
*/ */
private float crossCheckHorizontal(int startJ, int centerI, int maxCount, fn crossCheckHorizontal(&self, startJ:u32, centerI:u32, maxCount:u32,
int originalStateCountTotal) { originalStateCountTotal:u32) -> f32{
BitMatrix image = this.image; BitMatrix image = this.image;
int maxJ = image.getWidth(); int maxJ = image.getWidth();
@@ -483,8 +477,8 @@ public class FinderPatternFinder {
* @deprecated only exists for backwards compatibility * @deprecated only exists for backwards compatibility
* @see #handlePossibleCenter(int[], int, int) * @see #handlePossibleCenter(int[], int, int)
*/ */
@Deprecated #[deprecated]
protected final boolean handlePossibleCenter(int[] stateCount, int i, int j, boolean pureBarcode) { pub fn handlePossibleCenter(&self, stateCount:&[u32], i:u32, j:u32, pureBarcode:bool) -> bool{
return handlePossibleCenter(stateCount, i, j); return handlePossibleCenter(stateCount, i, j);
} }
@@ -505,7 +499,7 @@ public class FinderPatternFinder {
* @param j end of possible finder pattern in row * @param j end of possible finder pattern in row
* @return true if a finder pattern candidate was found this time * @return true if a finder pattern candidate was found this time
*/ */
protected final boolean handlePossibleCenter(int[] stateCount, int i, int j) { pub fn handlePossibleCenter(&self, stateCount:&[u32], i:u32, j:u32) -> bool{
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +
stateCount[4]; stateCount[4];
float centerJ = centerFromEnd(stateCount, j); float centerJ = centerFromEnd(stateCount, j);
@@ -544,7 +538,7 @@ public class FinderPatternFinder {
* allow us to infer that the third pattern must lie below a certain point farther * allow us to infer that the third pattern must lie below a certain point farther
* down in the image. * down in the image.
*/ */
private int findRowSkip() { fn findRowSkip(&self) -> u32{
int max = possibleCenters.size(); int max = possibleCenters.size();
if (max <= 1) { if (max <= 1) {
return 0; return 0;
@@ -574,7 +568,7 @@ public class FinderPatternFinder {
* at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the
* candidates is "pretty similar" * candidates is "pretty similar"
*/ */
private boolean haveMultiplyConfirmedCenters() { fn haveMultiplyConfirmedCenters(&self) -> bool {
int confirmedCount = 0; int confirmedCount = 0;
float totalModuleSize = 0.0f; float totalModuleSize = 0.0f;
int max = possibleCenters.size(); int max = possibleCenters.size();
@@ -602,7 +596,7 @@ public class FinderPatternFinder {
/** /**
* Get square of distance between a and b. * Get square of distance between a and b.
*/ */
private static double squaredDistance(FinderPattern a, FinderPattern b) { fn squaredDistance( a:&FinderPattern, b:&FinderPattern) -> f64{
double x = a.getX() - b.getX(); double x = a.getX() - b.getX();
double y = a.getY() - b.getY(); double y = a.getY() - b.getY();
return x * x + y * y; return x * x + y * y;
@@ -613,7 +607,7 @@ public class FinderPatternFinder {
* those have similar module size and form a shape closer to a isosceles right triangle. * those have similar module size and form a shape closer to a isosceles right triangle.
* @throws NotFoundException if 3 such finder patterns do not exist * @throws NotFoundException if 3 such finder patterns do not exist
*/ */
private FinderPattern[] selectBestPatterns() throws NotFoundException { fn selectBestPatterns(&self) -> Result<Vec<FinderPattern>,Exceptions> {
int startSize = possibleCenters.size(); int startSize = possibleCenters.size();
if (startSize < 3) { if (startSize < 3) {
@@ -702,14 +696,14 @@ public class FinderPatternFinder {
return bestPatterns; return bestPatterns;
} }
/**
* <p>Orders by {@link FinderPattern#getEstimatedModuleSize()}</p>
*/
private static final class EstimatedModuleComparator implements Comparator<FinderPattern>, Serializable {
@Override
public int compare(FinderPattern center1, FinderPattern center2) {
return Float.compare(center1.getEstimatedModuleSize(), center2.getEstimatedModuleSize());
}
} }
} // /**
// * <p>Orders by {@link FinderPattern#getEstimatedModuleSize()}</p>
// */
// private static final class EstimatedModuleComparator implements Comparator<FinderPattern>, Serializable {
// @Override
// public int compare(FinderPattern center1, FinderPattern center2) {
// return Float.compare(center1.getEstimatedModuleSize(), center2.getEstimatedModuleSize());
// }
// }

View File

@@ -2,8 +2,10 @@ mod finder_pattern_info;
mod finder_pattern; mod finder_pattern;
mod alignment_pattern; mod alignment_pattern;
mod alignment_pattern_finder; mod alignment_pattern_finder;
mod finder_pattern_finder;
pub use finder_pattern_info::*; pub use finder_pattern_info::*;
pub use finder_pattern::*; pub use finder_pattern::*;
pub use alignment_pattern::*; pub use alignment_pattern::*;
pub use alignment_pattern_finder::*; pub use alignment_pattern_finder::*;
pub use finder_pattern_finder::*;