Tightened a condition to reduce accidentally detecting the alignment pattern as a...
[zxing.git] / core / src / com / google / zxing / qrcode / detector / FinderPatternFinder.java
index 6ec97b1..63592bf 100755 (executable)
@@ -33,7 +33,7 @@ import java.util.Vector;
  *\r
  * <p>This class is not thread-safe and should not be reused.</p>\r
  *\r
- * @author srowen@google.com (Sean Owen)\r
+ * @author Sean Owen\r
  */\r
 final class FinderPatternFinder {\r
 \r
@@ -45,6 +45,7 @@ final class FinderPatternFinder {
   private final MonochromeBitmapSource image;\r
   private final Vector possibleCenters;\r
   private boolean hasSkipped;\r
+  private final int[] crossCheckStateCount;\r
 \r
   /**\r
    * <p>Creates a finder that will search the image for three finder patterns.</p>\r
@@ -54,6 +55,7 @@ final class FinderPatternFinder {
   FinderPatternFinder(MonochromeBitmapSource image) {\r
     this.image = image;\r
     this.possibleCenters = new Vector();\r
+    this.crossCheckStateCount = new int[5];\r
   }\r
 \r
   FinderPatternInfo find(Hashtable hints) throws ReaderException {\r
@@ -74,9 +76,10 @@ final class FinderPatternFinder {
 \r
     boolean done = false;\r
     int[] stateCount = new int[5];\r
+    BitArray blackRow = new BitArray(maxJ);\r
     for (int i = iSkip - 1; i < maxI && !done; i += iSkip) {\r
       // Get a row of black/white values\r
-      BitArray blackRow = image.getBlackRow(i, null, 0, maxJ);\r
+      blackRow = image.getBlackRow(i, blackRow, 0, maxJ);\r
       stateCount[0] = 0;\r
       stateCount[1] = 0;\r
       stateCount[2] = 0;\r
@@ -96,7 +99,9 @@ final class FinderPatternFinder {
               if (foundPatternCross(stateCount)) { // Yes\r
                 boolean confirmed = handlePossibleCenter(stateCount, i, j);\r
                 if (confirmed) {\r
-                  iSkip = 1; // Go back to examining each line\r
+                  // Start examining every other line. Checking each line turned out to be too\r
+                  // expensive and didn't improve performance.\r
+                  iSkip = 2;\r
                   if (hasSkipped) {\r
                     done = haveMulitplyConfirmedCenters();\r
                   } else {\r
@@ -197,6 +202,15 @@ final class FinderPatternFinder {
         Math.abs(moduleSize - (stateCount[4] << INTEGER_MATH_SHIFT)) < maxVariance;\r
   }\r
 \r
+  private int[] getCrossCheckStateCount() {\r
+    crossCheckStateCount[0] = 0;\r
+    crossCheckStateCount[1] = 0;\r
+    crossCheckStateCount[2] = 0;\r
+    crossCheckStateCount[3] = 0;\r
+    crossCheckStateCount[4] = 0;\r
+    return crossCheckStateCount;\r
+  }\r
+\r
   /**\r
    * <p>After a horizontal scan finds a potential finder pattern, this method\r
    * "cross-checks" by scanning down vertically through the center of the possible\r
@@ -212,7 +226,7 @@ final class FinderPatternFinder {
     MonochromeBitmapSource image = this.image;\r
 \r
     int maxI = image.getHeight();\r
-    int[] stateCount = new int[5];\r
+    int[] stateCount = getCrossCheckStateCount();\r
 \r
     // Start counting up from center\r
     int i = startI;\r
@@ -282,7 +296,7 @@ final class FinderPatternFinder {
     MonochromeBitmapSource image = this.image;\r
 \r
     int maxJ = image.getWidth();\r
-    int[] stateCount = new int[5];\r
+    int[] stateCount = getCrossCheckStateCount();\r
 \r
     int j = startJ;\r
     while (j >= 0 && image.isBlack(j, centerI)) {\r
@@ -409,10 +423,10 @@ final class FinderPatternFinder {
           // How far down can we skip before resuming looking for the next\r
           // pattern? In the worst case, only the difference between the\r
           // difference in the x / y coordinates of the two centers.\r
-          // This is the case where you find top left first. Draw it out.\r
+          // This is the case where you find top left last.\r
           hasSkipped = true;\r
           return (int) (Math.abs(firstConfirmedCenter.getX() - center.getX()) -\r
-              Math.abs(firstConfirmedCenter.getY() - center.getY()));\r
+              Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2;\r
         }\r
       }\r
     }\r
@@ -448,7 +462,7 @@ final class FinderPatternFinder {
       FinderPattern pattern = (FinderPattern) possibleCenters.elementAt(i);\r
       totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average);\r
     }\r
-    return totalDeviation <= 0.15f * totalModuleSize;\r
+    return totalDeviation <= 0.05f * totalModuleSize;\r
   }\r
 \r
   /**\r
@@ -470,7 +484,7 @@ final class FinderPatternFinder {
 \r
     if (size < 3) {\r
       // Couldn't find enough finder patterns\r
-      throw new ReaderException("Could not find three finder patterns");\r
+      throw ReaderException.getInstance();\r
     }\r
 \r
     if (size > 3) {\r