diff --git a/android/src/com/google/zxing/client/android/AndroidGraphicsGridSampler.java b/android/src/com/google/zxing/client/android/AndroidGraphicsGridSampler.java index a571c4919..9aa3f78af 100755 --- a/android/src/com/google/zxing/client/android/AndroidGraphicsGridSampler.java +++ b/android/src/com/google/zxing/client/android/AndroidGraphicsGridSampler.java @@ -68,7 +68,7 @@ public final class AndroidGraphicsGridSampler extends GridSampler { transformMatrix.mapPoints(points); // Quick check to see if points transformed to something inside the image; // sufficent to check the endpoints - checkEndpoint(image, points); + checkAndNudgePoints(image, points); for (int j = 0; j < max; j += 2) { if (image.isBlack((int) points[j], (int) points[j + 1])) { // Black(-ish) pixel diff --git a/core/src/com/google/zxing/common/DefaultGridSampler.java b/core/src/com/google/zxing/common/DefaultGridSampler.java index 1cdaf3f9c..e8f032f26 100644 --- a/core/src/com/google/zxing/common/DefaultGridSampler.java +++ b/core/src/com/google/zxing/common/DefaultGridSampler.java @@ -51,7 +51,7 @@ public final class DefaultGridSampler extends GridSampler { transform.transformPoints(points); // Quick check to see if points transformed to something inside the image; // sufficent to check the endpoints - checkEndpoint(image, points); + checkAndNudgePoints(image, points); for (int j = 0; j < max; j += 2) { if (image.isBlack((int) points[j], (int) points[j + 1])) { // Black(-ish) pixel diff --git a/core/src/com/google/zxing/common/GridSampler.java b/core/src/com/google/zxing/common/GridSampler.java index 12b056ea6..29b5e9050 100644 --- a/core/src/com/google/zxing/common/GridSampler.java +++ b/core/src/com/google/zxing/common/GridSampler.java @@ -98,40 +98,69 @@ public abstract class GridSampler { /** *
Checks a set of points that have been transformed to sample points on an image against - * the image's dimensions to see if the endpoints are even within the image. - * This method actually only checks the endpoints since the points are assumed to lie - * on a line.
+ * the image's dimensions to see if the point are even within the image. * *This method will actually "nudge" the endpoints back onto the image if they are found to be barely * (less than 1 pixel) off the image. This accounts for imperfect detection of finder patterns in an image * where the QR Code runs all the way to the image border.
* + *For efficiency, the method will check points from either end of the line until one is found + * to be within the image. Because the set of points are assumed to be linear, this is valid.
+ * * @param image image into which the points should map * @param points actual points in x1,y1,...,xn,yn form * @throws ReaderException if an endpoint is lies outside the image boundaries */ - protected static void checkEndpoint(MonochromeBitmapSource image, float[] points) throws ReaderException { + protected static void checkAndNudgePoints(MonochromeBitmapSource image, float[] points) throws ReaderException { int width = image.getWidth(); int height = image.getHeight(); - checkOneEndpoint(points, 0, width, height); - checkOneEndpoint(points, points.length - 2, width, height); - } - - private static void checkOneEndpoint(float[] points, int offset, int width, int height) throws ReaderException { - int x = (int) points[offset]; - int y = (int) points[offset + 1]; - if (x < -1 || x > width || y < -1 || y > height) { - throw new ReaderException("Transformed point out of bounds at " + x + ',' + y); + // Check and nudge points from start until we see some that are OK: + boolean nudged = true; + for (int offset = 0; offset < points.length && nudged; offset += 2) { + int x = (int) points[offset]; + int y = (int) points[offset + 1]; + if (x < -1 || x > width || y < -1 || y > height) { + throw new ReaderException("Transformed point out of bounds at " + x + ',' + y); + } + nudged = false; + if (x == -1) { + points[offset] = 0.0f; + nudged = true; + } else if (x == width) { + points[offset] = width - 1; + nudged = true; + } + if (y == -1) { + points[offset + 1] = 0.0f; + nudged = true; + } else if (y == height) { + points[offset + 1] = height - 1; + nudged = true; + } } - if (x == -1) { - points[offset] = 0.0f; - } else if (x == width) { - points[offset] = width - 1; - } - if (y == -1) { - points[offset + 1] = 0.0f; - } else if (y == height) { - points[offset + 1] = height - 1; + // Check and nudge points from end: + nudged = true; + for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) { + int x = (int) points[offset]; + int y = (int) points[offset + 1]; + if (x < -1 || x > width || y < -1 || y > height) { + throw new ReaderException("Transformed point out of bounds at " + x + ',' + y); + } + nudged = false; + if (x == -1) { + points[offset] = 0.0f; + nudged = true; + } else if (x == width) { + points[offset] = width - 1; + nudged = true; + } + if (y == -1) { + points[offset + 1] = 0.0f; + nudged = true; + } else if (y == height) { + points[offset + 1] = height - 1; + nudged = true; + } } }