diff --git a/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java b/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java index 6c388a822..ebed5d069 100755 --- a/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java +++ b/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java @@ -132,11 +132,13 @@ public class FinderPatternFinder { } } } else { - // Advance to next black pixel - do { - j++; - } while (j < maxJ && !image.get(j, i)); - j--; // back up to that last white pixel + stateCount[0] = stateCount[2]; + stateCount[1] = stateCount[3]; + stateCount[2] = stateCount[4]; + stateCount[3] = 1; + stateCount[4] = 0; + currentState = 3; + continue; } // Clear state to start looking again currentState = 0; @@ -502,13 +504,22 @@ public class FinderPatternFinder { if (startSize > 3) { // But we can only afford to do so if we have at least 4 possibilities to choose from float totalModuleSize = 0.0f; + float square = 0.0f; for (int i = 0; i < startSize; i++) { - totalModuleSize += ((FinderPattern) possibleCenters.elementAt(i)).getEstimatedModuleSize(); + float size = ((FinderPattern) possibleCenters.elementAt(i)).getEstimatedModuleSize(); + totalModuleSize += size; + square += size * size; } float average = totalModuleSize / (float) startSize; + float stdDev = (float) Math.sqrt(square / startSize - average * average); + + Collections.insertionSort(possibleCenters, new FurthestFromAverageComparator(average)); + + float limit = Math.max(0.2f * average, stdDev); + for (int i = 0; i < possibleCenters.size() && possibleCenters.size() > 3; i++) { FinderPattern pattern = (FinderPattern) possibleCenters.elementAt(i); - if (Math.abs(pattern.getEstimatedModuleSize() - average) > 0.2f * average) { + if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) { possibleCenters.removeElementAt(i); i--; } @@ -517,7 +528,16 @@ public class FinderPatternFinder { if (possibleCenters.size() > 3) { // Throw away all but those first size candidate points we found. - Collections.insertionSort(possibleCenters, new CenterComparator()); + + float totalModuleSize = 0.0f; + for (int i = 0; i < possibleCenters.size(); i++) { + totalModuleSize += ((FinderPattern) possibleCenters.elementAt(i)).getEstimatedModuleSize(); + } + + float average = totalModuleSize / (float) possibleCenters.size(); + + Collections.insertionSort(possibleCenters, new CenterComparator(average)); + possibleCenters.setSize(3); } @@ -528,12 +548,37 @@ public class FinderPatternFinder { }; } + /** + *

Orders by furthest from average

+ */ + private static class FurthestFromAverageComparator implements Comparator { + private final float average; + public FurthestFromAverageComparator(float f) { + average = f; + } + public int compare(Object center1, Object center2) { + float dA = Math.abs(((FinderPattern) center2).getEstimatedModuleSize() - average); + float dB = Math.abs(((FinderPattern) center1).getEstimatedModuleSize() - average); + return dA < dB ? -1 : (dA == dB ? 0 : 1); + } + } + /** *

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

*/ private static class CenterComparator implements Comparator { + private final float average; + public CenterComparator(float f) { + average = f; + } public int compare(Object center1, Object center2) { - return ((FinderPattern) center2).getCount() - ((FinderPattern) center1).getCount(); + if (((FinderPattern) center2).getCount() != ((FinderPattern) center1).getCount()) { + return ((FinderPattern) center2).getCount() - ((FinderPattern) center1).getCount(); + } else { + float dA = Math.abs(((FinderPattern) center2).getEstimatedModuleSize() - average); + float dB = Math.abs(((FinderPattern) center1).getEstimatedModuleSize() - average); + return dA < dB ? 1 : (dA == dB ? 0 : -1); + } } } diff --git a/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox2TestCase.java b/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox2TestCase.java index 0fc76ebee..d4e64744f 100644 --- a/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox2TestCase.java +++ b/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox2TestCase.java @@ -28,8 +28,8 @@ public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase { public QRCodeBlackBox2TestCase() { super("test/data/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE); addTest(26, 26, 0.0f); - addTest(25, 25, 90.0f); - addTest(24, 24, 180.0f); + addTest(26, 26, 90.0f); + addTest(26, 26, 180.0f); addTest(25, 25, 270.0f); } diff --git a/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox3TestCase.java b/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox3TestCase.java index bcdba7266..0894020e7 100644 --- a/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox3TestCase.java +++ b/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox3TestCase.java @@ -27,10 +27,10 @@ public final class QRCodeBlackBox3TestCase extends AbstractBlackBoxTestCase { public QRCodeBlackBox3TestCase() { super("test/data/blackbox/qrcode-3", new MultiFormatReader(), BarcodeFormat.QR_CODE); - addTest(36, 36, 0.0f); + addTest(38, 38, 0.0f); addTest(38, 38, 90.0f); addTest(36, 36, 180.0f); - addTest(37, 37, 270.0f); + addTest(38, 38, 270.0f); } } diff --git a/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox5TestCase.java b/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox5TestCase.java index 833e1d3ea..ae5737b84 100644 --- a/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox5TestCase.java +++ b/core/test/src/com/google/zxing/qrcode/QRCodeBlackBox5TestCase.java @@ -31,10 +31,10 @@ public final class QRCodeBlackBox5TestCase extends AbstractBlackBoxTestCase { public QRCodeBlackBox5TestCase() { super("test/data/blackbox/qrcode-5", new MultiFormatReader(), BarcodeFormat.QR_CODE); - addTest(19, 19, 0.0f); + addTest(18, 18, 0.0f); addTest(19, 19, 90.0f); - addTest(18, 18, 180.0f); - addTest(18, 18, 270.0f); + addTest(19, 19, 180.0f); + addTest(19, 19, 270.0f); } }