mirror of
https://github.com/zxing/zxing.git
synced 2024-11-10 04:54:04 -08:00
Draft of 'thinking' visualization for barcode scanning. Works for 1D and QR codes.
git-svn-id: https://zxing.googlecode.com/svn/trunk@1125 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
aee98771a2
commit
d1973dce0a
|
@ -19,6 +19,7 @@
|
|||
<color name="encode_view">#ffffffff</color>
|
||||
<color name="help_button_view">#ffcccccc</color>
|
||||
<color name="help_view">#ff404040</color>
|
||||
<color name="possible_result_points">#c0ffff00</color>
|
||||
<color name="result_image_border">#ffffffff</color>
|
||||
<color name="result_minor_text">#ffc0c0c0</color>
|
||||
<color name="result_points">#c000ff00</color>
|
||||
|
|
|
@ -125,6 +125,10 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
|
|||
}
|
||||
};
|
||||
|
||||
ViewfinderView getViewfinderView() {
|
||||
return viewfinderView;
|
||||
}
|
||||
|
||||
public Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
|
|
@ -42,10 +42,12 @@ public final class CaptureActivityHandler extends Handler {
|
|||
DONE
|
||||
}
|
||||
|
||||
CaptureActivityHandler(CaptureActivity activity, String decodeMode,
|
||||
boolean beginScanning) {
|
||||
CaptureActivityHandler(CaptureActivity activity,
|
||||
String decodeMode,
|
||||
boolean beginScanning) {
|
||||
this.activity = activity;
|
||||
decodeThread = new DecodeThread(activity, decodeMode);
|
||||
decodeThread = new DecodeThread(activity, decodeMode,
|
||||
new ViewfinderResultPointCallback(activity.getViewfinderView()));
|
||||
decodeThread.start();
|
||||
state = State.SUCCESS;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.google.zxing.DecodeHintType;
|
|||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -47,10 +48,12 @@ final class DecodeThread extends Thread {
|
|||
private Handler handler;
|
||||
private final CaptureActivity activity;
|
||||
private final MultiFormatReader multiFormatReader;
|
||||
private final ResultPointCallback resultPointCallback;
|
||||
|
||||
DecodeThread(CaptureActivity activity, String mode) {
|
||||
DecodeThread(CaptureActivity activity, String mode, ResultPointCallback resultPointCallback) {
|
||||
this.activity = activity;
|
||||
multiFormatReader = new MultiFormatReader();
|
||||
this.resultPointCallback = resultPointCallback;
|
||||
|
||||
// The prefs can't change while the thread is running, so pick them up once here.
|
||||
if (mode == null || mode.length() == 0) {
|
||||
|
@ -101,39 +104,27 @@ final class DecodeThread extends Thread {
|
|||
}
|
||||
|
||||
private void setDecodeProductMode() {
|
||||
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>(4);
|
||||
vector.addElement(BarcodeFormat.UPC_A);
|
||||
vector.addElement(BarcodeFormat.UPC_E);
|
||||
vector.addElement(BarcodeFormat.EAN_13);
|
||||
vector.addElement(BarcodeFormat.EAN_8);
|
||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
|
||||
multiFormatReader.setHints(hints);
|
||||
doSetDecodeMode(BarcodeFormat.UPC_A,
|
||||
BarcodeFormat.UPC_E,
|
||||
BarcodeFormat.EAN_13,
|
||||
BarcodeFormat.EAN_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the 1D formats we want this client to decode by hand.
|
||||
*/
|
||||
private void setDecode1DMode() {
|
||||
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>(7);
|
||||
vector.addElement(BarcodeFormat.UPC_A);
|
||||
vector.addElement(BarcodeFormat.UPC_E);
|
||||
vector.addElement(BarcodeFormat.EAN_13);
|
||||
vector.addElement(BarcodeFormat.EAN_8);
|
||||
vector.addElement(BarcodeFormat.CODE_39);
|
||||
vector.addElement(BarcodeFormat.CODE_128);
|
||||
vector.addElement(BarcodeFormat.ITF);
|
||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
|
||||
multiFormatReader.setHints(hints);
|
||||
doSetDecodeMode(BarcodeFormat.UPC_A,
|
||||
BarcodeFormat.UPC_E,
|
||||
BarcodeFormat.EAN_13,
|
||||
BarcodeFormat.EAN_8,
|
||||
BarcodeFormat.CODE_39,
|
||||
BarcodeFormat.CODE_128,
|
||||
BarcodeFormat.ITF);
|
||||
}
|
||||
|
||||
private void setDecodeQRMode() {
|
||||
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>(1);
|
||||
vector.addElement(BarcodeFormat.QR_CODE);
|
||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
|
||||
multiFormatReader.setHints(hints);
|
||||
doSetDecodeMode(BarcodeFormat.QR_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,17 +132,24 @@ final class DecodeThread extends Thread {
|
|||
* explicitly set which formats are available.
|
||||
*/
|
||||
private void setDecodeAllMode() {
|
||||
doSetDecodeMode(BarcodeFormat.UPC_A,
|
||||
BarcodeFormat.UPC_E,
|
||||
BarcodeFormat.EAN_13,
|
||||
BarcodeFormat.EAN_8,
|
||||
BarcodeFormat.CODE_39,
|
||||
BarcodeFormat.CODE_128,
|
||||
BarcodeFormat.ITF,
|
||||
BarcodeFormat.QR_CODE);
|
||||
}
|
||||
|
||||
private void doSetDecodeMode(BarcodeFormat... formats) {
|
||||
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>(8);
|
||||
vector.addElement(BarcodeFormat.UPC_A);
|
||||
vector.addElement(BarcodeFormat.UPC_E);
|
||||
vector.addElement(BarcodeFormat.EAN_13);
|
||||
vector.addElement(BarcodeFormat.EAN_8);
|
||||
vector.addElement(BarcodeFormat.CODE_39);
|
||||
vector.addElement(BarcodeFormat.CODE_128);
|
||||
vector.addElement(BarcodeFormat.ITF);
|
||||
vector.addElement(BarcodeFormat.QR_CODE);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>(formats.length);
|
||||
for (BarcodeFormat format : formats) {
|
||||
vector.addElement(format);
|
||||
}
|
||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
|
||||
hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
|
||||
multiFormatReader.setHints(hints);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2009 ZXing authors
|
||||
*
|
||||
* 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.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
|
||||
final class ViewfinderResultPointCallback implements ResultPointCallback {
|
||||
|
||||
private final ViewfinderView viewfinderView;
|
||||
|
||||
ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
|
||||
this.viewfinderView = viewfinderView;
|
||||
}
|
||||
|
||||
public void foundPossibleResultPoint(ResultPoint point) {
|
||||
viewfinderView.addPossibleResultPoint(point);
|
||||
}
|
||||
|
||||
}
|
|
@ -24,6 +24,10 @@ import android.graphics.Paint;
|
|||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import com.google.zxing.ResultPoint;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial
|
||||
|
@ -34,15 +38,18 @@ import android.view.View;
|
|||
public final class ViewfinderView extends View {
|
||||
private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
|
||||
private static final long ANIMATION_DELAY = 100L;
|
||||
private static final int OPAQUE = 0xFF;
|
||||
|
||||
private final Paint paint;
|
||||
private final Rect box;
|
||||
private Bitmap resultBitmap;
|
||||
private final int maskColor;
|
||||
private final int resultColor;
|
||||
private final int frameColor;
|
||||
private final int laserColor;
|
||||
private final int resultPointColor;
|
||||
private int scannerAlpha;
|
||||
private Collection<ResultPoint> possibleResultPoints;
|
||||
private Collection<ResultPoint> lastPossibleResultPoints;
|
||||
|
||||
// This constructor is used when the class is built from an XML resource.
|
||||
public ViewfinderView(Context context, AttributeSet attrs) {
|
||||
|
@ -50,13 +57,14 @@ public final class ViewfinderView extends View {
|
|||
|
||||
// Initialize these once for performance rather than calling them every time in onDraw().
|
||||
paint = new Paint();
|
||||
box = new Rect();
|
||||
Resources resources = getResources();
|
||||
maskColor = resources.getColor(R.color.viewfinder_mask);
|
||||
resultColor = resources.getColor(R.color.result_view);
|
||||
frameColor = resources.getColor(R.color.viewfinder_frame);
|
||||
laserColor = resources.getColor(R.color.viewfinder_laser);
|
||||
resultPointColor = resources.getColor(R.color.possible_result_points);
|
||||
scannerAlpha = 0;
|
||||
possibleResultPoints = new HashSet<ResultPoint>(5);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,42 +78,55 @@ public final class ViewfinderView extends View {
|
|||
|
||||
// Draw the exterior (i.e. outside the framing rect) darkened
|
||||
paint.setColor(resultBitmap != null ? resultColor : maskColor);
|
||||
box.set(0, 0, width, frame.top);
|
||||
canvas.drawRect(box, paint);
|
||||
box.set(0, frame.top, frame.left, frame.bottom + 1);
|
||||
canvas.drawRect(box, paint);
|
||||
box.set(frame.right + 1, frame.top, width, frame.bottom + 1);
|
||||
canvas.drawRect(box, paint);
|
||||
box.set(0, frame.bottom + 1, width, height);
|
||||
canvas.drawRect(box, paint);
|
||||
canvas.drawRect(0, 0, width, frame.top, paint);
|
||||
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
|
||||
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
|
||||
canvas.drawRect(0, frame.bottom + 1, width, height, paint);
|
||||
|
||||
if (resultBitmap != null) {
|
||||
// Draw the opaque result bitmap over the scanning rectangle
|
||||
paint.setAlpha(255);
|
||||
paint.setAlpha(OPAQUE);
|
||||
canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
|
||||
} else {
|
||||
|
||||
// Draw a two pixel solid black border inside the framing rect
|
||||
paint.setColor(frameColor);
|
||||
box.set(frame.left, frame.top, frame.right + 1, frame.top + 2);
|
||||
canvas.drawRect(box, paint);
|
||||
box.set(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1);
|
||||
canvas.drawRect(box, paint);
|
||||
box.set(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1);
|
||||
canvas.drawRect(box, paint);
|
||||
box.set(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1);
|
||||
canvas.drawRect(box, paint);
|
||||
canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
|
||||
canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
|
||||
canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
|
||||
canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
|
||||
|
||||
// Draw a red "laser scanner" line through the middle to show decoding is active
|
||||
paint.setColor(laserColor);
|
||||
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
|
||||
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
|
||||
int middle = frame.height() / 2 + frame.top;
|
||||
box.set(frame.left + 2, middle - 1, frame.right - 1, middle + 2);
|
||||
canvas.drawRect(box, paint);
|
||||
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
|
||||
|
||||
Collection<ResultPoint> currentPossible = possibleResultPoints;
|
||||
Collection<ResultPoint> currentLast = lastPossibleResultPoints;
|
||||
if (currentPossible.isEmpty()) {
|
||||
lastPossibleResultPoints = null;
|
||||
} else {
|
||||
possibleResultPoints = new HashSet<ResultPoint>(5);
|
||||
lastPossibleResultPoints = currentPossible;
|
||||
paint.setAlpha(OPAQUE);
|
||||
paint.setColor(resultPointColor);
|
||||
for (ResultPoint point : currentPossible) {
|
||||
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
|
||||
}
|
||||
}
|
||||
if (currentLast != null) {
|
||||
paint.setAlpha(OPAQUE / 2);
|
||||
paint.setColor(resultPointColor);
|
||||
for (ResultPoint point : currentLast) {
|
||||
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
|
||||
}
|
||||
}
|
||||
|
||||
// Request another update at the animation interval, but only repaint the laser line,
|
||||
// not the entire viewfinder mask.
|
||||
postInvalidateDelayed(ANIMATION_DELAY, box.left, box.top, box.right, box.bottom);
|
||||
postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,4 +144,9 @@ public final class ViewfinderView extends View {
|
|||
resultBitmap = barcode;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void addPossibleResultPoint(ResultPoint point) {
|
||||
possibleResultPoints.add(point);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -62,6 +62,12 @@ public final class DecodeHintType {
|
|||
*/
|
||||
public static final DecodeHintType ASSUME_CODE_39_CHECK_DIGIT = new DecodeHintType();
|
||||
|
||||
/**
|
||||
* The caller needs to be notified via callback when a possible {@link ResultPoint}
|
||||
* is found. Maps to a {@link ResultPointCallback}.
|
||||
*/
|
||||
public static final DecodeHintType NEED_RESULT_POINT_CALLBACK = new DecodeHintType();
|
||||
|
||||
private DecodeHintType() {
|
||||
}
|
||||
|
||||
|
|
29
core/src/com/google/zxing/ResultPointCallback.java
Normal file
29
core/src/com/google/zxing/ResultPointCallback.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Callback which is invoked when a possible result point (significant
|
||||
* point in the barcode image such as a corner) is found.
|
||||
*
|
||||
* @see DecodeHintType#NEED_RESULT_POINT_CALLBACK
|
||||
*/
|
||||
public interface ResultPointCallback {
|
||||
|
||||
void foundPossibleResultPoint(ResultPoint point);
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ package com.google.zxing.multi.qrcode.detector;
|
|||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.google.zxing.common.Collections;
|
||||
import com.google.zxing.common.Comparator;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
|
@ -90,6 +91,10 @@ final class MultiFinderPatternFinder extends FinderPatternFinder {
|
|||
super(image);
|
||||
}
|
||||
|
||||
MultiFinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) {
|
||||
super(image, resultPointCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are
|
||||
* those that have been detected at least {@link #CENTER_QUORUM} times, and whose module
|
||||
|
|
|
@ -118,6 +118,14 @@ public abstract class AbstractOneDReader implements OneDReader {
|
|||
for (int attempt = 0; attempt < 2; attempt++) {
|
||||
if (attempt == 1) { // trying again?
|
||||
row.reverse(); // reverse the row and continue
|
||||
// This means we will only ever draw result points *once* in the life of this method
|
||||
// since we want to avoid drawing the wrong points after flipping the row, and,
|
||||
// don't want to clutter with noise from every single row scan -- just the scans
|
||||
// that start on the center line.
|
||||
if (hints != null && hints.containsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) {
|
||||
hints = (Hashtable) hints.clone();
|
||||
hints.remove(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Look for a barcode
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
package com.google.zxing.oned;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
@ -110,16 +112,40 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
|
|||
|
||||
public final Result decodeRow(int rowNumber, BitArray row, Hashtable hints)
|
||||
throws ReaderException {
|
||||
return decodeRow(rowNumber, row, findStartGuardPattern(row));
|
||||
return decodeRow(rowNumber, row, findStartGuardPattern(row), hints);
|
||||
}
|
||||
|
||||
public final Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange)
|
||||
public final Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, Hashtable hints)
|
||||
throws ReaderException {
|
||||
|
||||
ResultPointCallback resultPointCallback = hints == null ? null :
|
||||
(ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
|
||||
|
||||
if (resultPointCallback != null) {
|
||||
resultPointCallback.foundPossibleResultPoint(new ResultPoint(
|
||||
(startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber
|
||||
));
|
||||
}
|
||||
|
||||
StringBuffer result = decodeRowStringBuffer;
|
||||
result.setLength(0);
|
||||
int endStart = decodeMiddle(row, startGuardRange, result);
|
||||
|
||||
if (resultPointCallback != null) {
|
||||
resultPointCallback.foundPossibleResultPoint(new ResultPoint(
|
||||
endStart, rowNumber
|
||||
));
|
||||
}
|
||||
|
||||
int[] endRange = decodeEnd(row, endStart);
|
||||
|
||||
if (resultPointCallback != null) {
|
||||
resultPointCallback.foundPossibleResultPoint(new ResultPoint(
|
||||
(endRange[0] + endRange[1]) / 2.0f, rowNumber
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// Make sure there is a quiet zone at least as big as the end pattern after the barcode. The
|
||||
// spec might want more whitespace, but in practice this is the maximum we can count on.
|
||||
int end = endRange[1];
|
||||
|
|
|
@ -68,7 +68,7 @@ public final class MultiFormatUPCEANReader extends AbstractOneDReader {
|
|||
UPCEANReader reader = (UPCEANReader) readers.elementAt(i);
|
||||
Result result;
|
||||
try {
|
||||
result = reader.decodeRow(rowNumber, row, startGuardPattern);
|
||||
result = reader.decodeRow(rowNumber, row, startGuardPattern, hints);
|
||||
} catch (ReaderException re) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -34,8 +34,9 @@ public final class UPCAReader implements UPCEANReader {
|
|||
|
||||
private final UPCEANReader ean13Reader = new EAN13Reader();
|
||||
|
||||
public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange) throws ReaderException {
|
||||
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange));
|
||||
public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, Hashtable hints)
|
||||
throws ReaderException {
|
||||
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange, hints));
|
||||
}
|
||||
|
||||
public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
|
||||
|
|
|
@ -20,6 +20,8 @@ import com.google.zxing.ReaderException;
|
|||
import com.google.zxing.Result;
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* <p>This interfaces captures additional functionality that readers of
|
||||
* UPC/EAN family of barcodes should expose.</p>
|
||||
|
@ -33,6 +35,7 @@ public interface UPCEANReader extends OneDReader {
|
|||
* allows caller to inform method about where the UPC/EAN start pattern is
|
||||
* found. This allows this to be computed once and reused across many implementations.</p>
|
||||
*/
|
||||
Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange) throws ReaderException;
|
||||
Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, Hashtable hints)
|
||||
throws ReaderException;
|
||||
|
||||
}
|
|
@ -17,6 +17,8 @@
|
|||
package com.google.zxing.qrcode.detector;
|
||||
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
|
||||
import java.util.Vector;
|
||||
|
@ -45,6 +47,7 @@ final class AlignmentPatternFinder {
|
|||
private final int height;
|
||||
private final float moduleSize;
|
||||
private final int[] crossCheckStateCount;
|
||||
private final ResultPointCallback resultPointCallback;
|
||||
|
||||
/**
|
||||
* <p>Creates a finder that will look in a portion of the whole image.</p>
|
||||
|
@ -61,7 +64,8 @@ final class AlignmentPatternFinder {
|
|||
int startY,
|
||||
int width,
|
||||
int height,
|
||||
float moduleSize) {
|
||||
float moduleSize,
|
||||
ResultPointCallback resultPointCallback) {
|
||||
this.image = image;
|
||||
this.possibleCenters = new Vector(5);
|
||||
this.startX = startX;
|
||||
|
@ -70,6 +74,7 @@ final class AlignmentPatternFinder {
|
|||
this.height = height;
|
||||
this.moduleSize = moduleSize;
|
||||
this.crossCheckStateCount = new int[3];
|
||||
this.resultPointCallback = resultPointCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -262,7 +267,11 @@ final class AlignmentPatternFinder {
|
|||
}
|
||||
}
|
||||
// Hadn't found this before; save it
|
||||
possibleCenters.addElement(new AlignmentPattern(centerJ, centerI, estimatedModuleSize));
|
||||
ResultPoint point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
|
||||
possibleCenters.addElement(point);
|
||||
if (resultPointCallback != null) {
|
||||
resultPointCallback.foundPossibleResultPoint(point);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
|
||||
package com.google.zxing.qrcode.detector;
|
||||
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.common.DetectorResult;
|
||||
import com.google.zxing.common.GridSampler;
|
||||
|
@ -34,6 +36,7 @@ import java.util.Hashtable;
|
|||
public class Detector {
|
||||
|
||||
private final BitMatrix image;
|
||||
private ResultPointCallback resultPointCallback;
|
||||
|
||||
public Detector(BitMatrix image) {
|
||||
this.image = image;
|
||||
|
@ -62,7 +65,10 @@ public class Detector {
|
|||
*/
|
||||
public DetectorResult detect(Hashtable hints) throws ReaderException {
|
||||
|
||||
FinderPatternFinder finder = new FinderPatternFinder(image);
|
||||
resultPointCallback = hints == null ? null :
|
||||
(ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
|
||||
|
||||
FinderPatternFinder finder = new FinderPatternFinder(image, resultPointCallback);
|
||||
FinderPatternInfo info = finder.find(hints);
|
||||
|
||||
return processFinderPatternInfo(info);
|
||||
|
@ -347,7 +353,8 @@ public class Detector {
|
|||
alignmentAreaTopY,
|
||||
alignmentAreaRightX - alignmentAreaLeftX,
|
||||
alignmentAreaBottomY - alignmentAreaTopY,
|
||||
overallEstModuleSize);
|
||||
overallEstModuleSize,
|
||||
resultPointCallback);
|
||||
return alignmentFinder.find();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.google.zxing.qrcode.detector;
|
|||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.google.zxing.common.Collections;
|
||||
import com.google.zxing.common.Comparator;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
|
@ -45,6 +46,7 @@ public class FinderPatternFinder {
|
|||
private final Vector possibleCenters;
|
||||
private boolean hasSkipped;
|
||||
private final int[] crossCheckStateCount;
|
||||
private final ResultPointCallback resultPointCallback;
|
||||
|
||||
/**
|
||||
* <p>Creates a finder that will search the image for three finder patterns.</p>
|
||||
|
@ -52,9 +54,14 @@ public class FinderPatternFinder {
|
|||
* @param image image to search
|
||||
*/
|
||||
public FinderPatternFinder(BitMatrix image) {
|
||||
this(image, null);
|
||||
}
|
||||
|
||||
public FinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) {
|
||||
this.image = image;
|
||||
this.possibleCenters = new Vector();
|
||||
this.crossCheckStateCount = new int[5];
|
||||
this.resultPointCallback = resultPointCallback;
|
||||
}
|
||||
|
||||
protected BitMatrix getImage() {
|
||||
|
@ -401,7 +408,11 @@ public class FinderPatternFinder {
|
|||
}
|
||||
}
|
||||
if (!found) {
|
||||
possibleCenters.addElement(new FinderPattern(centerJ, centerI, estimatedModuleSize));
|
||||
ResultPoint point = new FinderPattern(centerJ, centerI, estimatedModuleSize);
|
||||
possibleCenters.addElement(point);
|
||||
if (resultPointCallback != null) {
|
||||
resultPointCallback.foundPossibleResultPoint(point);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue