package com.google.zxing.oned;
import com.google.zxing.BinaryBitmap;
+import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
+import com.google.zxing.FormatException;
+import com.google.zxing.NotFoundException;
import com.google.zxing.Reader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
+import java.util.Enumeration;
import java.util.Hashtable;
/**
*/
public abstract class OneDReader implements Reader {
- private static final int INTEGER_MATH_SHIFT = 8;
- static final int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT;
+ protected static final int INTEGER_MATH_SHIFT = 8;
+ protected static final int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT;
- public Result decode(BinaryBitmap image) throws ReaderException {
+ public Result decode(BinaryBitmap image) throws NotFoundException, FormatException {
return decode(image, null);
}
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
- public Result decode(BinaryBitmap image, Hashtable hints) throws ReaderException {
+ public Result decode(BinaryBitmap image, Hashtable hints) throws NotFoundException, FormatException {
try {
return doDecode(image, hints);
- } catch (ReaderException re) {
+ } catch (NotFoundException nfe) {
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
if (tryHarder && image.isRotateSupported()) {
BinaryBitmap rotatedImage = image.rotateCounterClockwise();
((Integer) metadata.get(ResultMetadataType.ORIENTATION)).intValue()) % 360;
}
result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(orientation));
+ // Update result points
+ ResultPoint[] points = result.getResultPoints();
+ int height = rotatedImage.getHeight();
+ for (int i = 0; i < points.length; i++) {
+ points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX());
+ }
return result;
} else {
- throw re;
+ throw nfe;
}
}
}
+ public void reset() {
+ // do nothing
+ }
+
/**
* We're going to examine rows from the middle outward, searching alternately above and below the
* middle, and farther out each time. rowStep is the number of rows between each successive
* @param image The image to decode
* @param hints Any hints that were requested
* @return The contents of the decoded barcode
- * @throws ReaderException Any spontaneous errors which occur
+ * @throws NotFoundException Any spontaneous errors which occur
*/
- private Result doDecode(BinaryBitmap image, Hashtable hints) throws ReaderException {
+ private Result doDecode(BinaryBitmap image, Hashtable hints) throws NotFoundException {
int width = image.getWidth();
int height = image.getHeight();
BitArray row = new BitArray(width);
int middle = height >> 1;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
- int rowStep = Math.max(1, height >> (tryHarder ? 7 : 4));
+ int rowStep = Math.max(1, height >> (tryHarder ? 8 : 5));
int maxLines;
if (tryHarder) {
maxLines = height; // Look at the whole image, not just the center
} else {
- maxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image
+ maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image
}
for (int x = 0; x < maxLines; x++) {
// Estimate black point for this row and load it:
try {
row = image.getBlackRow(rowNumber, row);
- } catch (ReaderException re) {
+ } catch (NotFoundException nfe) {
continue;
}
// 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);
+ Hashtable newHints = new Hashtable(); // Can't use clone() in J2ME
+ Enumeration hintEnum = hints.keys();
+ while (hintEnum.hasMoreElements()) {
+ Object key = hintEnum.nextElement();
+ if (!key.equals(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) {
+ newHints.put(key, hints.get(key));
+ }
+ }
+ hints = newHints;
}
}
try {
}
}
- throw ReaderException.getInstance();
+ throw NotFoundException.getNotFoundInstance();
}
/**
* @param row row to count from
* @param start offset into row to start at
* @param counters array into which to record counts
- * @throws ReaderException if counters cannot be filled entirely from row before running out
+ * @throws NotFoundException if counters cannot be filled entirely from row before running out
* of pixels
*/
- static void recordPattern(BitArray row, int start, int[] counters) throws ReaderException {
+ protected static void recordPattern(BitArray row, int start, int[] counters) throws NotFoundException {
int numCounters = counters.length;
for (int i = 0; i < numCounters; i++) {
counters[i] = 0;
}
int end = row.getSize();
if (start >= end) {
- throw ReaderException.getInstance();
+ throw NotFoundException.getNotFoundInstance();
}
boolean isWhite = !row.get(start);
int counterPosition = 0;
// If we read fully the last section of pixels and filled up our counters -- or filled
// the last counter but ran off the side of the image, OK. Otherwise, a problem.
if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end))) {
- throw ReaderException.getInstance();
+ throw NotFoundException.getNotFoundInstance();
+ }
+ }
+
+ protected static void recordPatternInReverse(BitArray row, int start, int[] counters)
+ throws NotFoundException {
+ // This could be more efficient I guess
+ int numTransitionsLeft = counters.length;
+ boolean last = row.get(start);
+ while (start > 0 && numTransitionsLeft >= 0) {
+ if (row.get(--start) != last) {
+ numTransitionsLeft--;
+ last = !last;
+ }
+ }
+ if (numTransitionsLeft >= 0) {
+ throw NotFoundException.getNotFoundInstance();
}
+ recordPattern(row, start + 1, counters);
}
/**
* the total variance between counters and patterns equals the pattern length, higher values mean
* even more variance
*/
- static int patternMatchVariance(int[] counters, int[] pattern, int maxIndividualVariance) {
+ protected static int patternMatchVariance(int[] counters, int[] pattern, int maxIndividualVariance) {
int numCounters = counters.length;
int total = 0;
int patternLength = 0;
* @param row the black/white pixel data of the row
* @param hints decode hints
* @return {@link Result} containing encoded string and start/end of barcode
- * @throws ReaderException if an error occurs or barcode cannot be found
+ * @throws NotFoundException if an error occurs or barcode cannot be found
*/
public abstract Result decodeRow(int rowNumber, BitArray row, Hashtable hints)
- throws ReaderException;
+ throws NotFoundException, ChecksumException, FormatException;
}