diff --git a/core/src/com/google/zxing/common/BitArray.java b/core/src/com/google/zxing/common/BitArray.java index 91ad8b3dc..3bfc3c92b 100644 --- a/core/src/com/google/zxing/common/BitArray.java +++ b/core/src/com/google/zxing/common/BitArray.java @@ -73,6 +73,50 @@ public final class BitArray { } } + /** + * Efficient method to check if a range of bits is set, or not set. + * + * @param start start of range, inclusive. + * @param end end of range, exclusive + * @param value if true, checks that bits in range are set, otherwise checks that they are not set + * @return true iff all bits are set or not set in range, according to value argument + * @throws IllegalArgumentException if end is less than or equal to start + */ + public boolean isRange(int start, int end, boolean value) { + if (end < start) { + throw new IllegalArgumentException(); + } + if (end == start) { + return true; // empty range matches + } + end--; // will be easier to treat this as the last actually set bit -- inclusive + int firstInt = start >> 5; + int lastInt = end >> 5; + for (int i = firstInt; i <= lastInt; i++) { + int firstBit = i > firstInt ? 0 : start & 0x1F; + int lastBit = i < lastInt ? 31 : end & 0x1F; + int mask; + if (firstBit == 0 && lastBit == 31) { + mask = -1; + } else { + mask = 0; + for (int j = firstBit; j <= lastBit; j++) { + mask |= 1 << j; + } + } + if (value) { + if ((bits[i] & mask) != mask) { + return false; + } + } else { + if ((bits[i] & mask) != 0) { + return false; + } + } + } + return true; + } + /** * @return underlying array of ints. The first element holds the first 32 bits, and the least * significant bit is bit 0. diff --git a/core/src/com/google/zxing/oned/AbstractUPCEANReader.java b/core/src/com/google/zxing/oned/AbstractUPCEANReader.java index ac5f7e7ed..ea5f11e78 100644 --- a/core/src/com/google/zxing/oned/AbstractUPCEANReader.java +++ b/core/src/com/google/zxing/oned/AbstractUPCEANReader.java @@ -82,7 +82,7 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements nextStart = startRange[1]; // As a check, we want to see some white in front of this "start pattern", // maybe as wide as the start pattern itself? - foundStart = isWhiteRange(row, Math.max(0, start - 2 * (startRange[1] - start)), start); + foundStart = row.isRange(Math.max(0, start - 2 * (startRange[1] - start)), start, false); } return startRange; } @@ -101,7 +101,7 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements // Check for whitespace after the pattern int end = endRange[1]; - if (!isWhiteRange(row, end, Math.min(row.getSize(), end + 2 * (end - endRange[0])))) { + if (!row.isRange(end, Math.min(row.getSize(), end + 2 * (end - endRange[0])), false)) { throw new ReaderException("Pattern not followed by whitespace"); } @@ -115,18 +115,6 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements new GenericResultPoint((float) (endRange[1] - endRange[0]) / 2.0f, (float) rowNumber)}); } - /** - * @return true iff row consists of white values in the range [start,end) - */ - protected static boolean isWhiteRange(BitArray row, int start, int end) { - for (int i = start; i < end; i++) { - if (row.get(i)) { - return false; - } - } - return true; - } - /** * Computes the UPC/EAN checksum on a string of digits, and reports * whether the checksum is correct or not. diff --git a/core/test/src/com/google/zxing/common/BitArrayTestCase.java b/core/test/src/com/google/zxing/common/BitArrayTestCase.java index 6f203a68a..a47ae47ac 100644 --- a/core/test/src/com/google/zxing/common/BitArrayTestCase.java +++ b/core/test/src/com/google/zxing/common/BitArrayTestCase.java @@ -63,4 +63,25 @@ public final class BitArrayTestCase extends TestCase { assertEquals(Integer.MIN_VALUE, ints[1]); } + public void testIsRange() { + BitArray array = new BitArray(64); + assertTrue(array.isRange(0, 64, false)); + assertFalse(array.isRange(0, 64, true)); + array.set(32); + assertTrue(array.isRange(32, 33, true)); + array.set(31); + assertTrue(array.isRange(31, 33, true)); + array.set(34); + assertFalse(array.isRange(31, 35, true)); + for (int i = 0; i < 31; i++) { + array.set(i); + } + assertTrue(array.isRange(0, 33, true)); + for (int i = 33; i < 64; i++) { + array.set(i); + } + assertTrue(array.isRange(0, 64, true)); + assertFalse(array.isRange(0, 64, false)); + } + } \ No newline at end of file