mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
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:
parent
35cf29b720
commit
b93f68f0db
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue