diff --git a/android/build.xml b/android/build.xml
index 04bd85eb3..f19d5f4b8 100644
--- a/android/build.xml
+++ b/android/build.xml
@@ -128,8 +128,6 @@
-
-
diff --git a/android/src/com/google/zxing/client/android/AndroidGraphicsGridSampler.java b/android/src/com/google/zxing/client/android/AndroidGraphicsGridSampler.java
new file mode 100755
index 000000000..d91deda1d
--- /dev/null
+++ b/android/src/com/google/zxing/client/android/AndroidGraphicsGridSampler.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.MonochromeBitmapSource;
+import com.google.zxing.ReaderException;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.detector.AlignmentPattern;
+import com.google.zxing.qrcode.detector.FinderPattern;
+import com.google.zxing.qrcode.detector.GridSampler;
+
+import android.graphics.Matrix;
+
+/**
+ * Implementation based on Android's
+ * {@link Matrix#setPolyToPoly(float[], int, float[], int, int)}
+ * class, which should offer faster performance for these matrix
+ * operations.
+ *
+ * @author srowen@google.com (Sean Owen)
+ */
+public final class AndroidGraphicsGridSampler extends GridSampler {
+
+ @Override
+ protected BitMatrix sampleGrid(MonochromeBitmapSource image,
+ FinderPattern topLeft,
+ FinderPattern topRight,
+ FinderPattern bottomLeft,
+ AlignmentPattern alignmentPattern,
+ int dimension) throws ReaderException {
+ float dimMinusThree = (float) dimension - 3.5f;
+ float bottomRightX, bottomRightY;
+ float sourceBottomRightX, sourceBottomRightY;
+ if (alignmentPattern != null) {
+ bottomRightX = alignmentPattern.getX();
+ bottomRightY = alignmentPattern.getY();
+ sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;
+ } else {
+ // Don't have an alignment pattern, just make up the bottom-right point
+ bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();
+ bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();
+ sourceBottomRightX = sourceBottomRightY = dimMinusThree;
+ }
+
+ Matrix transformMatrix = new Matrix();
+ boolean succeeded = transformMatrix.setPolyToPoly(
+ new float[] {
+ topLeft.getX(),
+ topLeft.getY(),
+ topRight.getX(),
+ topRight.getY(),
+ bottomLeft.getX(),
+ bottomLeft.getY(),
+ bottomRightX,
+ bottomRightY
+ },
+ 0,
+ new float[] {
+ 3.5f,
+ 3.5f,
+ dimMinusThree,
+ 3.5f,
+ 3.5f,
+ dimMinusThree,
+ sourceBottomRightX,
+ sourceBottomRightY,
+ },
+ 0,
+ 4
+ );
+ if (!succeeded) {
+ throw new ReaderException("Could not establish transformation matrix");
+ }
+
+ BitMatrix bits = new BitMatrix(dimension);
+ float[] points = new float[dimension << 1];
+ for (int i = 0; i < dimension; i++) {
+ int max = points.length;
+ float iValue = (float) i + 0.5f;
+ for (int j = 0; j < max; j += 2) {
+ points[j] = (float) (j >> 1) + 0.5f;
+ points[j + 1] = iValue;
+ }
+ transformMatrix.mapPoints(points);
+ // Quick check to see if points transformed to something inside the image;
+ // sufficent to check the endpoints
+ checkEndpoint(image, points);
+ for (int j = 0; j < max; j += 2) {
+ if (image.isBlack((int) points[j], (int) points[j + 1])) {
+ // Black(-ish) pixel
+ bits.set(i, j >> 1);
+ }
+ }
+ }
+ return bits;
+ }
+
+}
diff --git a/android/src/com/google/zxing/client/android/BarcodeReaderCaptureActivity.java b/android/src/com/google/zxing/client/android/BarcodeReaderCaptureActivity.java
index 38a48ee59..3b72d2689 100644
--- a/android/src/com/google/zxing/client/android/BarcodeReaderCaptureActivity.java
+++ b/android/src/com/google/zxing/client/android/BarcodeReaderCaptureActivity.java
@@ -63,6 +63,9 @@ public final class BarcodeReaderCaptureActivity extends Activity {
workerThread = new WorkerThread(surfaceView, cameraManager, messageHandler);
workerThread.requestPreviewLoop();
workerThread.start();
+
+ // TODO re-enable this when issues with Matrix.setPolyToPoly() are resolved
+ //GridSampler.setGridSampler(new AndroidGraphicsGridSampler());
}
@Override
diff --git a/core/src/com/google/zxing/qrcode/detector/GridSampler.java b/core/src/com/google/zxing/qrcode/detector/GridSampler.java
index c9df5b868..880ad485d 100644
--- a/core/src/com/google/zxing/qrcode/detector/GridSampler.java
+++ b/core/src/com/google/zxing/qrcode/detector/GridSampler.java
@@ -28,52 +28,37 @@ import com.google.zxing.common.BitMatrix;
* Imaging library, but which may not be available in other environments such as J2ME, and vice
* versa.
*
- * The implementation used can be controlled by calling {@link #setGridSamplerClassName(String)}
- * with the name of a class which implements this interface.
+ * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}
+ * with an instance of a class which implements this interface.
*
* @author srowen@google.com (Sean Owen)
*/
public abstract class GridSampler {
- private static final String DEFAULT_IMPL_CLASS = "com.google.zxing.qrcode.detector.DefaultGridSampler";
-
- private static String gridSamplerClassName = DEFAULT_IMPL_CLASS;
private static GridSampler gridSampler;
/**
- *
Sets the (fully-qualified) name of the implementation of {@link GridSampler} which will be
- * returned from {@link #getInstance()}.
- *
- * @param className {@link GridSampler} implementation to instantiate
+ * Sets the implementation of {@link GridSampler} used by the library. One global
+ * instance is stored, which may sound problematic. But, the implementation provided
+ * ought to be appropriate for the entire platform, and all uses of this library
+ * in the whole lifetime of the JVM. For instance, an Android activity can swap in
+ * an implementation that takes advantage of native platform libraries.
+ *
+ * @param newGridSampler
*/
- public static void setGridSamplerClassName(String className) {
- if (className == null) {
+ public static void setGridSampler(GridSampler newGridSampler) {
+ if (newGridSampler == null) {
throw new IllegalArgumentException();
}
- gridSamplerClassName = className;
+ gridSampler = newGridSampler;
}
/**
- * @return the current implementation of {@link GridSampler}, instantiating one if one does
- * not already exist. The class which is instantied may be set by
- * {@link #setGridSamplerClassName(String)}
+ * @return the current implementation of {@link GridSampler}
*/
public static GridSampler getInstance() {
if (gridSampler == null) {
- // We don't need to synchronize this -- don't really care if two threads initialize at once.
- // The second one will win.
- try {
- Class gridSamplerClass = Class.forName(gridSamplerClassName);
- gridSampler = (GridSampler) gridSamplerClass.newInstance();
- } catch (ClassNotFoundException cnfe) {
- // The exceptions below would represent bad programming errors;
- // For J2ME we're punting them out with RuntimeException
- throw new RuntimeException(cnfe.toString());
- } catch (IllegalAccessException iae) {
- throw new RuntimeException(iae.toString());
- } catch (InstantiationException ie) {
- throw new RuntimeException(ie.toString());
- }
+ gridSampler = new DefaultGridSampler();
}
return gridSampler;
}