Improved GridSampler API -- no need for reflection anymore. Reintroduced Android GridSampler implementation, which still doesn't quite work yet.

git-svn-id: https://zxing.googlecode.com/svn/trunk@221 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-02-22 17:01:38 +00:00
parent 47743fbb8e
commit 556225ab0a
4 changed files with 129 additions and 31 deletions

View file

@ -128,8 +128,6 @@
<arg value="-dontpreverify"/>
<arg value="-dontobfuscate"/>
<arg value="-keep public class com.google.zxing.client.android.BarcodeReaderCaptureActivity"/>
<arg value="-keep public class com.google.zxing.qrcode.detector.DefaultGridSampler"/>
<arg value="-keep public class com.google.zxing.qrcode.detector.GridSampler"/>
<arg value="-optimizationpasses 4"/>
<arg value="-verbose"/>
</java>

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;
/**
* <p>Sets the (fully-qualified) name of the implementation of {@link GridSampler} which will be
* returned from {@link #getInstance()}.</p>
*
* @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;
}