mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-28 05:12:34 +00:00
partial port of finder pattern finder
This commit is contained in:
@@ -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());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -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::*;
|
||||||
Reference in New Issue
Block a user