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
This commit is contained in:
srowen 2011-11-25 01:17:28 +00:00
parent 35cf29b720
commit b93f68f0db
13 changed files with 87 additions and 87 deletions

View file

@ -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.
*

View file

@ -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.
*

View file

@ -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) {

View file

@ -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) {

View file

@ -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};
}
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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++;

View file

@ -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++;
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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);