From b93f68f0db8ae9e6e5a754830c068d1d8a23ae90 Mon Sep 17 00:00:00 2001 From: srowen Date: Fri, 25 Nov 2011 01:17:28 +0000 Subject: [PATCH] Another half-percent from specializing some operations on bit arrays git-svn-id: https://zxing.googlecode.com/svn/trunk@2050 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- .../src/com/google/zxing/common/BitArray.java | 26 ++++++++++++++++ .../com/google/zxing/common/BitMatrix.java | 8 +++++ .../com/google/zxing/oned/CodaBarReader.java | 23 +++----------- .../com/google/zxing/oned/Code128Reader.java | 11 ++----- .../com/google/zxing/oned/Code39Reader.java | 31 ++++++------------- .../com/google/zxing/oned/Code93Reader.java | 23 +++----------- core/src/com/google/zxing/oned/ITFReader.java | 11 ++----- .../src/com/google/zxing/oned/OneDReader.java | 3 +- .../zxing/oned/UPCEANExtensionSupport.java | 4 +-- .../com/google/zxing/oned/UPCEANReader.java | 3 +- .../google/zxing/oned/rss/RSS14Reader.java | 3 +- .../oned/rss/expanded/RSSExpandedReader.java | 3 +- .../google/zxing/common/BitArrayTestCase.java | 25 +++++++++++++++ 13 files changed, 87 insertions(+), 87 deletions(-) diff --git a/core/src/com/google/zxing/common/BitArray.java b/core/src/com/google/zxing/common/BitArray.java index afab97c18..dc6eac100 100644 --- a/core/src/com/google/zxing/common/BitArray.java +++ b/core/src/com/google/zxing/common/BitArray.java @@ -78,6 +78,32 @@ public final class BitArray { bits[i >> 5] ^= 1 << (i & 0x1F); } + /** + * @param from first bit to check + * @return index of first bit that is set, starting from the given index, or size if none are set + */ + public int getNextSet(int from) { + int size = this.size; + if (from >= size) { + return size; + } + int bitsOffset = from >> 5; + int currentBits = bits[bitsOffset]; + int mask = 1 << (from & 0x1F); + while ((currentBits & mask) == 0) { + if (++from >= size) { + break; + } + if (mask == 0x80000000) { + mask = 1; + currentBits = bits[++bitsOffset]; + } else { + mask <<= 1; + } + } + return from; + } + /** * Sets a block of 32 bits, starting at bit i. * diff --git a/core/src/com/google/zxing/common/BitMatrix.java b/core/src/com/google/zxing/common/BitMatrix.java index a524355cd..877fba4b8 100755 --- a/core/src/com/google/zxing/common/BitMatrix.java +++ b/core/src/com/google/zxing/common/BitMatrix.java @@ -144,6 +144,14 @@ public final class BitMatrix { return row; } + /** + * @param y row to set + * @param row {@link BitArray} to copy from + */ + public void setRow(int y, BitArray row) { + System.arraycopy(row.getBitArray(), 0, bits, y * rowSize, rowSize); + } + /** * This is useful in detecting the enclosing rectangle of a 'pure' barcode. * diff --git a/core/src/com/google/zxing/oned/CodaBarReader.java b/core/src/com/google/zxing/oned/CodaBarReader.java index c39a94697..06c1f5647 100644 --- a/core/src/com/google/zxing/oned/CodaBarReader.java +++ b/core/src/com/google/zxing/oned/CodaBarReader.java @@ -66,14 +66,10 @@ public final class CodaBarReader extends OneDReader { throws NotFoundException { int[] start = findAsteriskPattern(row); start[1] = 0; // BAS: settings this to 0 improves the recognition rate somehow? - int nextStart = start[1]; + // Read off white space + int nextStart = row.getNextSet(start[1]); int end = row.getSize(); - // Read off white space - while (nextStart < end && !row.get(nextStart)) { - nextStart++; - } - StringBuilder result = new StringBuilder(); int[] counters = new int[7]; int lastStart; @@ -95,9 +91,7 @@ public final class CodaBarReader extends OneDReader { } // Read off white space - while (nextStart < end && !row.get(nextStart)) { - nextStart++; - } + nextStart = row.getNextSet(nextStart); } while (nextStart < end); // no fixed end pattern so keep on reading while data is available // Look for whitespace after pattern: @@ -157,13 +151,7 @@ public final class CodaBarReader extends OneDReader { private static int[] findAsteriskPattern(BitArray row) throws NotFoundException { int width = row.getSize(); - int rowOffset = 0; - while (rowOffset < width) { - if (row.get(rowOffset)) { - break; - } - rowOffset++; - } + int rowOffset = row.getNextSet(0); int counterPosition = 0; int[] counters = new int[7]; @@ -172,8 +160,7 @@ public final class CodaBarReader extends OneDReader { int patternLength = counters.length; for (int i = rowOffset; i < width; i++) { - boolean pixel = row.get(i); - if (pixel ^ isWhite) { + if (row.get(i) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { diff --git a/core/src/com/google/zxing/oned/Code128Reader.java b/core/src/com/google/zxing/oned/Code128Reader.java index c5a36179e..389d67d9b 100644 --- a/core/src/com/google/zxing/oned/Code128Reader.java +++ b/core/src/com/google/zxing/oned/Code128Reader.java @@ -168,13 +168,7 @@ public final class Code128Reader extends OneDReader { private static int[] findStartPattern(BitArray row) throws NotFoundException { int width = row.getSize(); - int rowOffset = 0; - while (rowOffset < width) { - if (row.get(rowOffset)) { - break; - } - rowOffset++; - } + int rowOffset = row.getNextSet(0); int counterPosition = 0; int[] counters = new int[6]; @@ -183,8 +177,7 @@ public final class Code128Reader extends OneDReader { int patternLength = counters.length; for (int i = rowOffset; i < width; i++) { - boolean pixel = row.get(i); - if (pixel ^ isWhite) { + if (row.get(i) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { diff --git a/core/src/com/google/zxing/oned/Code39Reader.java b/core/src/com/google/zxing/oned/Code39Reader.java index b88c0254e..32d3aa67c 100644 --- a/core/src/com/google/zxing/oned/Code39Reader.java +++ b/core/src/com/google/zxing/oned/Code39Reader.java @@ -98,14 +98,10 @@ public final class Code39Reader extends OneDReader { int[] counters = new int[9]; int[] start = findAsteriskPattern(row, counters); - int nextStart = start[1]; + // Read off white space + int nextStart = row.getNextSet(start[1]); int end = row.getSize(); - // Read off white space - while (nextStart < end && !row.get(nextStart)) { - nextStart++; - } - StringBuilder result = new StringBuilder(20); char decodedChar; int lastStart; @@ -122,11 +118,9 @@ public final class Code39Reader extends OneDReader { nextStart += counter; } // Read off white space - while (nextStart < end && !row.get(nextStart)) { - nextStart++; - } + nextStart = row.getNextSet(nextStart); } while (decodedChar != '*'); - result.deleteCharAt(result.length() - 1); // remove asterisk + result.setLength(result.length() - 1); // remove asterisk // Look for whitespace after pattern: int lastPatternSize = 0; @@ -136,7 +130,7 @@ public final class Code39Reader extends OneDReader { int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; // If 50% of last pattern size, following last pattern, is not whitespace, fail // (but if it's whitespace to the very end of the image, that's OK) - if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) { + if (nextStart != end && (whiteSpaceAfterEnd >> 1) < lastPatternSize) { throw NotFoundException.getNotFoundInstance(); } @@ -149,7 +143,7 @@ public final class Code39Reader extends OneDReader { if (result.charAt(max) != ALPHABET[total % 43]) { throw ChecksumException.getChecksumInstance(); } - result.deleteCharAt(max); + result.setLength(max); } if (result.length() < 4) { @@ -178,13 +172,7 @@ public final class Code39Reader extends OneDReader { private static int[] findAsteriskPattern(BitArray row, int[] counters) throws NotFoundException { int width = row.getSize(); - int rowOffset = 0; - while (rowOffset < width) { - if (row.get(rowOffset)) { - break; - } - rowOffset++; - } + int rowOffset = row.getNextSet(0); int counterPosition = 0; int patternStart = rowOffset; @@ -192,14 +180,13 @@ public final class Code39Reader extends OneDReader { int patternLength = counters.length; for (int i = rowOffset; i < width; i++) { - boolean pixel = row.get(i); - if (pixel ^ isWhite) { + if (row.get(i) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (toNarrowWidePattern(counters) == ASTERISK_ENCODING) { // Look for whitespace before start pattern, >= 50% of width of start pattern - if (row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) { + if (row.isRange(Math.max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false)) { return new int[]{patternStart, i}; } } diff --git a/core/src/com/google/zxing/oned/Code93Reader.java b/core/src/com/google/zxing/oned/Code93Reader.java index 3ab4362d3..c8fe2aa81 100644 --- a/core/src/com/google/zxing/oned/Code93Reader.java +++ b/core/src/com/google/zxing/oned/Code93Reader.java @@ -58,14 +58,10 @@ public final class Code93Reader extends OneDReader { throws NotFoundException, ChecksumException, FormatException { int[] start = findAsteriskPattern(row); - int nextStart = start[1]; + // Read off white space + int nextStart = row.getNextSet(start[1]); int end = row.getSize(); - // Read off white space - while (nextStart < end && !row.get(nextStart)) { - nextStart++; - } - StringBuilder result = new StringBuilder(20); int[] counters = new int[6]; char decodedChar; @@ -83,9 +79,7 @@ public final class Code93Reader extends OneDReader { nextStart += counter; } // Read off white space - while (nextStart < end && !row.get(nextStart)) { - nextStart++; - } + nextStart = row.getNextSet(nextStart); } while (decodedChar != '*'); result.deleteCharAt(result.length() - 1); // remove asterisk @@ -119,13 +113,7 @@ public final class Code93Reader extends OneDReader { private static int[] findAsteriskPattern(BitArray row) throws NotFoundException { int width = row.getSize(); - int rowOffset = 0; - while (rowOffset < width) { - if (row.get(rowOffset)) { - break; - } - rowOffset++; - } + int rowOffset = row.getNextSet(0); int counterPosition = 0; int[] counters = new int[6]; @@ -134,8 +122,7 @@ public final class Code93Reader extends OneDReader { int patternLength = counters.length; for (int i = rowOffset; i < width; i++) { - boolean pixel = row.get(i); - if (pixel ^ isWhite) { + if (row.get(i) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { diff --git a/core/src/com/google/zxing/oned/ITFReader.java b/core/src/com/google/zxing/oned/ITFReader.java index d6d7626fc..559c93bf9 100644 --- a/core/src/com/google/zxing/oned/ITFReader.java +++ b/core/src/com/google/zxing/oned/ITFReader.java @@ -227,13 +227,7 @@ public final class ITFReader extends OneDReader { */ private static int skipWhiteSpace(BitArray row) throws NotFoundException { int width = row.getSize(); - int endStart = 0; - while (endStart < width) { - if (row.get(endStart)) { - break; - } - endStart++; - } + int endStart = row.getNextSet(0); if (endStart == width) { throw NotFoundException.getNotFoundInstance(); } @@ -300,8 +294,7 @@ public final class ITFReader extends OneDReader { int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { - boolean pixel = row.get(x); - if (pixel ^ isWhite) { + if (row.get(x) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { diff --git a/core/src/com/google/zxing/oned/OneDReader.java b/core/src/com/google/zxing/oned/OneDReader.java index b59e88448..41e0fa222 100644 --- a/core/src/com/google/zxing/oned/OneDReader.java +++ b/core/src/com/google/zxing/oned/OneDReader.java @@ -203,8 +203,7 @@ public abstract class OneDReader implements Reader { int counterPosition = 0; int i = start; while (i < end) { - boolean pixel = row.get(i); - if (pixel ^ isWhite) { // that is, exactly one is true + if (row.get(i) ^ isWhite) { // that is, exactly one is true counters[counterPosition]++; } else { counterPosition++; diff --git a/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java b/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java index 9d305c38c..0bc1a900c 100644 --- a/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java +++ b/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java @@ -85,9 +85,7 @@ final class UPCEANExtensionSupport { } if (x != 4) { // Read off separator if not last - while (rowOffset < end && !row.get(rowOffset)) { - rowOffset++; - } + rowOffset = row.getNextSet(rowOffset); while (rowOffset < end && row.get(rowOffset)) { rowOffset++; } diff --git a/core/src/com/google/zxing/oned/UPCEANReader.java b/core/src/com/google/zxing/oned/UPCEANReader.java index 24c199358..731ceba4a 100644 --- a/core/src/com/google/zxing/oned/UPCEANReader.java +++ b/core/src/com/google/zxing/oned/UPCEANReader.java @@ -289,8 +289,7 @@ public abstract class UPCEANReader extends OneDReader { int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { - boolean pixel = row.get(x); - if (pixel ^ isWhite) { + if (row.get(x) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { diff --git a/core/src/com/google/zxing/oned/rss/RSS14Reader.java b/core/src/com/google/zxing/oned/rss/RSS14Reader.java index edea4191c..efbb0be3e 100644 --- a/core/src/com/google/zxing/oned/rss/RSS14Reader.java +++ b/core/src/com/google/zxing/oned/rss/RSS14Reader.java @@ -303,8 +303,7 @@ public final class RSS14Reader extends AbstractRSSReader { int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { - boolean pixel = row.get(x); - if (pixel ^ isWhite) { + if (row.get(x) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == 3) { diff --git a/core/src/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java b/core/src/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java index 2c388b263..4f69d479e 100644 --- a/core/src/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java +++ b/core/src/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java @@ -306,8 +306,7 @@ public final class RSSExpandedReader extends AbstractRSSReader { int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { - boolean pixel = row.get(x); - if (pixel ^ isWhite) { + if (row.get(x) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == 3) { diff --git a/core/test/src/com/google/zxing/common/BitArrayTestCase.java b/core/test/src/com/google/zxing/common/BitArrayTestCase.java index bf1c5ce7c..c9fd2d945 100644 --- a/core/test/src/com/google/zxing/common/BitArrayTestCase.java +++ b/core/test/src/com/google/zxing/common/BitArrayTestCase.java @@ -34,6 +34,31 @@ public final class BitArrayTestCase extends Assert { } } + @Test + public void testGetNextSet() { + BitArray array = new BitArray(32); + assertEquals(32, array.getNextSet(0)); + assertEquals(32, array.getNextSet(31)); + + array = new BitArray(33); + assertEquals(33, array.getNextSet(0)); + assertEquals(33, array.getNextSet(31)); + assertEquals(33, array.getNextSet(32)); + + array.set(31); + assertEquals(31, array.getNextSet(0)); + assertEquals(31, array.getNextSet(30)); + assertEquals(31, array.getNextSet(31)); + assertEquals(33, array.getNextSet(32)); + + array = new BitArray(33); + array.set(32); + assertEquals(32, array.getNextSet(0)); + assertEquals(32, array.getNextSet(30)); + assertEquals(32, array.getNextSet(31)); + assertEquals(32, array.getNextSet(32)); + } + @Test public void testSetBulk() { BitArray array = new BitArray(64);