diff --git a/core/src/com/google/zxing/DecodeHintType.java b/core/src/com/google/zxing/DecodeHintType.java index 20c30c09d..4d48a4a22 100644 --- a/core/src/com/google/zxing/DecodeHintType.java +++ b/core/src/com/google/zxing/DecodeHintType.java @@ -56,6 +56,7 @@ public final class DecodeHintType { * Skip the first n barcodes found. Currently applies only to 1D formats. This * enables a caller to repeatedly decode and find multiple barcodes. Maps * to an {@link Integer}. + * @deprecated */ public static final DecodeHintType SKIP_N_BARCODES = new DecodeHintType(); diff --git a/core/src/com/google/zxing/MultiFormatReader.java b/core/src/com/google/zxing/MultiFormatReader.java index adab2f1d9..6b2c2401f 100644 --- a/core/src/com/google/zxing/MultiFormatReader.java +++ b/core/src/com/google/zxing/MultiFormatReader.java @@ -38,15 +38,19 @@ public final class MultiFormatReader implements Reader { public Result decode(MonochromeBitmapSource image, Hashtable hints) throws ReaderException { + boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); Vector possibleFormats = hints == null ? null : (Vector) hints.get(DecodeHintType.POSSIBLE_FORMATS); Vector readers = new Vector(); if (possibleFormats != null) { - if (possibleFormats.contains(BarcodeFormat.UPC_A) || + boolean addOneDReader = + possibleFormats.contains(BarcodeFormat.UPC_A) || possibleFormats.contains(BarcodeFormat.UPC_E) || possibleFormats.contains(BarcodeFormat.EAN_13) || possibleFormats.contains(BarcodeFormat.EAN_8) || possibleFormats.contains(BarcodeFormat.CODE_39) || - possibleFormats.contains(BarcodeFormat.CODE_128)) { + possibleFormats.contains(BarcodeFormat.CODE_128); + // Put 1D readers upfront in "normal" mode + if (addOneDReader && !tryHarder) { readers.addElement(new MultiFormatOneDReader()); } if (possibleFormats.contains(BarcodeFormat.QR_CODE)) { @@ -55,12 +59,21 @@ public final class MultiFormatReader implements Reader { if (possibleFormats.contains(BarcodeFormat.DATAMATRIX)) { readers.addElement(new DataMatrixReader()); } + // At end in "try harder" mode + if (addOneDReader && tryHarder) { + readers.addElement(new MultiFormatOneDReader()); + } } if (readers.isEmpty()) { - readers.addElement(new MultiFormatOneDReader()); + if (!tryHarder) { + readers.addElement(new MultiFormatOneDReader()); + } readers.addElement(new QRCodeReader()); // TODO re-enable once Data Matrix is ready // readers.addElement(new DataMatrixReader()); + if (tryHarder) { + readers.addElement(new MultiFormatOneDReader()); + } } for (int i = 0; i < readers.size(); i++) { diff --git a/core/src/com/google/zxing/common/BlackPointEstimator.java b/core/src/com/google/zxing/common/BlackPointEstimator.java index a9fc7933c..c3e373841 100644 --- a/core/src/com/google/zxing/common/BlackPointEstimator.java +++ b/core/src/com/google/zxing/common/BlackPointEstimator.java @@ -90,8 +90,8 @@ public final class BlackPointEstimator { // dynamic range in the image, that discriminating black and white is too error-prone. // Decoding the image/line is either pointless, or may in some cases lead to a false positive // for 1D formats, which are relatively lenient. - // We arbitrarily say "close" is "fewer than 1/8 of the total histogram buckets apart" - if (secondPeak - firstPeak < histogram.length >> 3) { + // We arbitrarily say "close" is "<= 1/16 of the total histogram buckets apart" + if (secondPeak - firstPeak <= histogram.length >> 4) { throw new ReaderException("Too little dynamic range in luminance"); } diff --git a/core/src/com/google/zxing/oned/AbstractOneDReader.java b/core/src/com/google/zxing/oned/AbstractOneDReader.java index 53a04a319..66eee2b03 100644 --- a/core/src/com/google/zxing/oned/AbstractOneDReader.java +++ b/core/src/com/google/zxing/oned/AbstractOneDReader.java @@ -69,13 +69,13 @@ public abstract class AbstractOneDReader implements OneDReader { BitArray row = new BitArray(width); - int barcodesToSkip = 0; - if (hints != null) { - Integer number = (Integer) hints.get(DecodeHintType.SKIP_N_BARCODES); - if (number != null) { - barcodesToSkip = number.intValue(); - } - } + //int barcodesToSkip = 0; + //if (hints != null) { + // Integer number = (Integer) hints.get(DecodeHintType.SKIP_N_BARCODES); + // if (number != null) { + // barcodesToSkip = number.intValue(); + // } + //} // 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 attempt above and below @@ -87,23 +87,27 @@ public abstract class AbstractOneDReader implements OneDReader { int middle = height >> 1; int rowStep = Math.max(1, height >> (tryHarder ? 7 : 4)); int maxLines; - if (tryHarder || barcodesToSkip > 0) { + //if (tryHarder || barcodesToSkip > 0) { + if (tryHarder) { maxLines = height; // Look at the whole image; looking for more than one barcode } else { maxLines = 7; } - Result lastResult = null; + //Result lastResult = null; for (int x = 0; x < maxLines; x++) { + // Scanning from the middle out. Determine which row we're looking at next: int rowStepsAboveOrBelow = (x + 1) >> 1; boolean isAbove = (x & 0x01) == 0; // i.e. is x even? int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow); if (rowNumber < 0 || rowNumber >= height) { + // Oops, if we run off the top or bottom, stop break; } + // Estimate black point for this row and load it: try { image.estimateBlackPoint(BlackPointEstimationMethod.ROW_SAMPLING, rowNumber); } catch (ReaderException re) { @@ -111,7 +115,9 @@ public abstract class AbstractOneDReader implements OneDReader { } image.getBlackRow(rowNumber, row, 0, width); + // We may try twice for each row, if "trying harder": for (int attempt = 0; attempt < 2; attempt++) { + if (attempt == 1) { // trying again? if (tryHarder) { // only if "trying harder" row.reverse(); // reverse the row and continue @@ -119,24 +125,33 @@ public abstract class AbstractOneDReader implements OneDReader { break; } } + try { + + // Look for a barcode Result result = decodeRow(rowNumber, row, hints); - if (lastResult == null || !lastResult.getText().equals(result.getText())) { - // Found new barcode, not just the last one again - if (barcodesToSkip > 0) { // See if we should skip and keep looking - barcodesToSkip--; - lastResult = result; // Remember what we just saw - } else { - if (attempt == 1) { - // Found it, but upside-down: - result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180)); - } - return result; + + //if (lastResult != null && lastResult.getText().equals(result.getText())) { + // Just saw the last barcode again, proceed + //continue; + //} + + //if (barcodesToSkip > 0) { // See if we should skip and keep looking + // barcodesToSkip--; + // lastResult = result; // Remember what we just saw + //} else { + // We found our barcode + if (attempt == 1) { + // But it was upside down, so note that + result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180)); } - } + return result; + //} + } catch (ReaderException re) { - // continue + // continue -- just couldn't decode this row } + } }