diff --git a/core/src/com/google/zxing/common/GenericResultPoint.java b/core/src/com/google/zxing/common/GenericResultPoint.java index cc1dee19f..fcf94d1cb 100644 --- a/core/src/com/google/zxing/common/GenericResultPoint.java +++ b/core/src/com/google/zxing/common/GenericResultPoint.java @@ -43,7 +43,7 @@ public final class GenericResultPoint implements ResultPoint { } public String toString() { - StringBuffer result = new StringBuffer(); + StringBuffer result = new StringBuffer(25); result.append('('); result.append(posX); result.append(','); @@ -52,4 +52,66 @@ public final class GenericResultPoint implements ResultPoint { return result.toString(); } + public boolean equals(Object other) { + if (other instanceof GenericResultPoint) { + GenericResultPoint otherPoint = (GenericResultPoint) other; + return posX == otherPoint.posX && posY == otherPoint.posY; + } + return false; + } + + public int hashCode() { + return 31 * Float.floatToIntBits(posX) + Float.floatToIntBits(posY); + } + + /** + *

Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and + * BC < AC and the angle between BC and BA is less than 180 degrees. + */ + public static void orderBestPatterns(ResultPoint[] patterns) { + + // Find distances between pattern centers + float zeroOneDistance = distance(patterns[0], patterns[1]); + float oneTwoDistance = distance(patterns[1], patterns[2]); + float zeroTwoDistance = distance(patterns[0], patterns[2]); + + ResultPoint pointA, pointB, pointC; + // 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. + if ((pointC.getY() - pointB.getY()) * (pointA.getX() - pointB.getX()) > + (pointC.getX() - pointB.getX()) * (pointA.getY() - pointB.getY())) { + ResultPoint temp = pointA; + pointA = pointC; + pointC = temp; + } + + patterns[0] = pointA; + patterns[1] = pointB; + patterns[2] = pointC; + } + + + /** + * @return distance between two points + */ + public static float distance(ResultPoint pattern1, ResultPoint pattern2) { + float xDiff = pattern1.getX() - pattern2.getX(); + float yDiff = pattern1.getY() - pattern2.getY(); + return (float) Math.sqrt((double) (xDiff * xDiff + yDiff * yDiff)); + } + } \ No newline at end of file diff --git a/core/src/com/google/zxing/qrcode/detector/Detector.java b/core/src/com/google/zxing/qrcode/detector/Detector.java index 7ee4b654d..f57ae5873 100644 --- a/core/src/com/google/zxing/qrcode/detector/Detector.java +++ b/core/src/com/google/zxing/qrcode/detector/Detector.java @@ -22,6 +22,7 @@ import com.google.zxing.ReaderException; import com.google.zxing.ResultPoint; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.DetectorResult; +import com.google.zxing.common.GenericResultPoint; import com.google.zxing.common.GridSampler; import com.google.zxing.qrcode.decoder.Version; @@ -172,8 +173,8 @@ public final class Detector { ResultPoint topRight, ResultPoint bottomLeft, float moduleSize) throws ReaderException { - int tltrCentersDimension = round(FinderPatternFinder.distance(topLeft, topRight) / moduleSize); - int tlblCentersDimension = round(FinderPatternFinder.distance(topLeft, bottomLeft) / moduleSize); + int tltrCentersDimension = round(GenericResultPoint.distance(topLeft, topRight) / moduleSize); + int tlblCentersDimension = round(GenericResultPoint.distance(topLeft, bottomLeft) / moduleSize); int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7; switch (dimension & 0x03) { // mod 4 case 0: diff --git a/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java b/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java index 543467dd7..ea66cad09 100755 --- a/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java +++ b/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java @@ -19,10 +19,10 @@ package com.google.zxing.qrcode.detector; import com.google.zxing.DecodeHintType; import com.google.zxing.MonochromeBitmapSource; import com.google.zxing.ReaderException; -import com.google.zxing.ResultPoint; import com.google.zxing.common.BitArray; import com.google.zxing.common.Collections; import com.google.zxing.common.Comparator; +import com.google.zxing.common.GenericResultPoint; import java.util.Hashtable; import java.util.Vector; @@ -157,7 +157,7 @@ final class FinderPatternFinder { } FinderPattern[] patternInfo = selectBestPatterns(); - patternInfo = orderBestPatterns(patternInfo); + GenericResultPoint.orderBestPatterns(patternInfo); return new FinderPatternInfo(patternInfo); } @@ -503,63 +503,6 @@ final class FinderPatternFinder { }; } - /** - *

Having found three "best" finder patterns we need to decide which is the top-left, top-right, - * bottom-left. We assume that the one closest to the other two is the top-left one; this is not - * strictly true (imagine extreme perspective distortion) but for the moment is a serviceable assumption. - * Lastly we sort top-right from bottom-left by figuring out orientation from vector cross products.

- * - * @param patterns three best {@link FinderPattern}s - * @return same {@link FinderPattern}s ordered bottom-left, top-left, top-right - */ - private static FinderPattern[] orderBestPatterns(FinderPattern[] patterns) { - - // Find distances between pattern centers - float abDistance = distance(patterns[0], patterns[1]); - float bcDistance = distance(patterns[1], patterns[2]); - float acDistance = distance(patterns[0], patterns[2]); - - FinderPattern topLeft; - FinderPattern topRight; - FinderPattern bottomLeft; - // Assume one closest to other two is top left; - // topRight and bottomLeft will just be guesses below at first - if (bcDistance >= abDistance && bcDistance >= acDistance) { - topLeft = patterns[0]; - topRight = patterns[1]; - bottomLeft = patterns[2]; - } else if (acDistance >= bcDistance && acDistance >= abDistance) { - topLeft = patterns[1]; - topRight = patterns[0]; - bottomLeft = patterns[2]; - } else { - topLeft = patterns[2]; - topRight = patterns[0]; - bottomLeft = patterns[1]; - } - - // Use cross product to figure out which of other1/2 is the bottom left - // pattern. The vector "top-left -> bottom-left" x "top-left -> top-right" - // should yield a vector with positive z component - if ((bottomLeft.getY() - topLeft.getY()) * (topRight.getX() - topLeft.getX()) < - (bottomLeft.getX() - topLeft.getX()) * (topRight.getY() - topLeft.getY())) { - FinderPattern temp = topRight; - topRight = bottomLeft; - bottomLeft = temp; - } - - return new FinderPattern[]{bottomLeft, topLeft, topRight}; - } - - /** - * @return distance between two points - */ - static float distance(ResultPoint pattern1, ResultPoint pattern2) { - float xDiff = pattern1.getX() - pattern2.getX(); - float yDiff = pattern1.getY() - pattern2.getY(); - return (float) Math.sqrt((double) (xDiff * xDiff + yDiff * yDiff)); - } - /** *

Orders by {@link FinderPattern#getCount()}, descending.

*/