mirror of
https://github.com/zxing/zxing.git
synced 2024-11-10 04:54:04 -08:00
Faster getNextSet; more gains from getNextUnset
git-svn-id: https://zxing.googlecode.com/svn/trunk@2051 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
b93f68f0db
commit
8f005274c0
|
@ -81,27 +81,46 @@ public final class BitArray {
|
|||
/**
|
||||
* @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
|
||||
* at or beyond this given index
|
||||
* @see #getNextUnset(int)
|
||||
*/
|
||||
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;
|
||||
// mask off lesser bits first
|
||||
currentBits &= ~((1 << (from & 0x1F)) - 1);
|
||||
while (currentBits == 0) {
|
||||
if (++bitsOffset == bits.length) {
|
||||
return size;
|
||||
}
|
||||
currentBits = bits[bitsOffset];
|
||||
}
|
||||
return from;
|
||||
int result = (bitsOffset << 5) + Integer.numberOfTrailingZeros(currentBits);
|
||||
return result > size ? size : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getNextSet(int)
|
||||
*/
|
||||
public int getNextUnset(int from) {
|
||||
if (from >= size) {
|
||||
return size;
|
||||
}
|
||||
int bitsOffset = from >> 5;
|
||||
int currentBits = ~bits[bitsOffset];
|
||||
// mask off lesser bits first
|
||||
currentBits &= ~((1 << (from & 0x1F)) - 1);
|
||||
while (currentBits == 0) {
|
||||
if (++bitsOffset == bits.length) {
|
||||
return size;
|
||||
}
|
||||
currentBits = ~bits[bitsOffset];
|
||||
}
|
||||
int result = (bitsOffset << 5) + Integer.numberOfTrailingZeros(currentBits);
|
||||
return result > size ? size : result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -413,12 +413,10 @@ public final class Code128Reader extends OneDReader {
|
|||
// Check for ample whitespace following pattern, but, to do this we first need to remember that
|
||||
// we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left
|
||||
// to read off. Would be slightly better to properly read. Here we just skip it:
|
||||
int width = row.getSize();
|
||||
while (nextStart < width && row.get(nextStart)) {
|
||||
nextStart++;
|
||||
}
|
||||
if (!row.isRange(nextStart, Math.min(width, nextStart + (nextStart - lastStart) / 2),
|
||||
false)) {
|
||||
nextStart = row.getNextUnset(nextStart);
|
||||
if (!row.isRange(nextStart,
|
||||
Math.min(row.getSize(), nextStart + (nextStart - lastStart) / 2),
|
||||
false)) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
|
|
|
@ -86,9 +86,7 @@ final class UPCEANExtensionSupport {
|
|||
if (x != 4) {
|
||||
// Read off separator if not last
|
||||
rowOffset = row.getNextSet(rowOffset);
|
||||
while (rowOffset < end && row.get(rowOffset)) {
|
||||
rowOffset++;
|
||||
}
|
||||
rowOffset = row.getNextUnset(rowOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -277,15 +277,8 @@ public abstract class UPCEANReader extends OneDReader {
|
|||
int[] counters) throws NotFoundException {
|
||||
int patternLength = pattern.length;
|
||||
int width = row.getSize();
|
||||
boolean isWhite = false;
|
||||
while (rowOffset < width) {
|
||||
isWhite = !row.get(rowOffset);
|
||||
if (whiteFirst == isWhite) {
|
||||
break;
|
||||
}
|
||||
rowOffset++;
|
||||
}
|
||||
|
||||
boolean isWhite = whiteFirst;
|
||||
rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset);
|
||||
int counterPosition = 0;
|
||||
int patternStart = rowOffset;
|
||||
for (int x = rowOffset; x < width; x++) {
|
||||
|
|
|
@ -190,18 +190,14 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
|||
}
|
||||
|
||||
private static int getNextSecondBar(BitArray row, int initialPos){
|
||||
int currentPos = initialPos;
|
||||
boolean current = row.get(currentPos);
|
||||
|
||||
while(currentPos < row.getSize() && row.get(currentPos) == current) {
|
||||
currentPos++;
|
||||
int currentPos;
|
||||
if (row.get(initialPos)) {
|
||||
currentPos = row.getNextUnset(initialPos);
|
||||
currentPos = row.getNextSet(currentPos);
|
||||
} else {
|
||||
currentPos = row.getNextSet(initialPos);
|
||||
currentPos = row.getNextUnset(currentPos);
|
||||
}
|
||||
|
||||
current = !current;
|
||||
while(currentPos < row.getSize() && row.get(currentPos) == current) {
|
||||
currentPos++;
|
||||
}
|
||||
|
||||
return currentPos;
|
||||
}
|
||||
|
||||
|
@ -237,7 +233,6 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
|||
throw nfe;
|
||||
}
|
||||
}
|
||||
|
||||
return new ExpandedPair(leftChar, rightChar, pattern, mayBeLast);
|
||||
}
|
||||
|
||||
|
@ -374,10 +369,7 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
|||
|
||||
start = this.startEnd[0];
|
||||
|
||||
int firstElementStart = this.startEnd[1] + 1;
|
||||
while (firstElementStart < row.getSize() && row.get(firstElementStart)) {
|
||||
firstElementStart++;
|
||||
}
|
||||
int firstElementStart = row.getNextUnset(this.startEnd[1] + 1);
|
||||
|
||||
end = firstElementStart;
|
||||
firstCounter = end - this.startEnd[1];
|
||||
|
|
|
@ -19,6 +19,9 @@ package com.google.zxing.common;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
|
@ -35,30 +38,93 @@ public final class BitArrayTestCase extends Assert {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetNextSet() {
|
||||
public void testGetNextSet1() {
|
||||
BitArray array = new BitArray(32);
|
||||
assertEquals(32, array.getNextSet(0));
|
||||
assertEquals(32, array.getNextSet(31));
|
||||
|
||||
for (int i = 0; i < array.getSize(); i++) {
|
||||
assertEquals(String.valueOf(i), 32, array.getNextSet(i));
|
||||
}
|
||||
array = new BitArray(33);
|
||||
assertEquals(33, array.getNextSet(0));
|
||||
assertEquals(33, array.getNextSet(31));
|
||||
assertEquals(33, array.getNextSet(32));
|
||||
for (int i = 0; i < array.getSize(); i++) {
|
||||
assertEquals(String.valueOf(i), 33, array.getNextSet(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNextSet2() {
|
||||
BitArray array = new BitArray(33);
|
||||
array.set(31);
|
||||
assertEquals(31, array.getNextSet(0));
|
||||
assertEquals(31, array.getNextSet(30));
|
||||
assertEquals(31, array.getNextSet(31));
|
||||
assertEquals(33, array.getNextSet(32));
|
||||
|
||||
for (int i = 0; i < array.getSize(); i++) {
|
||||
assertEquals(String.valueOf(i), i <= 31 ? 31 : 33, array.getNextSet(i));
|
||||
}
|
||||
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));
|
||||
for (int i = 0; i < array.getSize(); i++) {
|
||||
assertEquals(String.valueOf(i), 32, array.getNextSet(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNextSet3() {
|
||||
BitArray array = new BitArray(63);
|
||||
array.set(31);
|
||||
array.set(32);
|
||||
for (int i = 0; i < array.getSize(); i++) {
|
||||
int expected;
|
||||
if (i <= 31) {
|
||||
expected = 31;
|
||||
} else if (i == 32) {
|
||||
expected = 32;
|
||||
} else {
|
||||
expected = 63;
|
||||
}
|
||||
assertEquals(String.valueOf(i), expected, array.getNextSet(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNextSet4() {
|
||||
BitArray array = new BitArray(63);
|
||||
array.set(33);
|
||||
array.set(40);
|
||||
for (int i = 0; i < array.getSize(); i++) {
|
||||
int expected;
|
||||
if (i <= 33) {
|
||||
expected = 33;
|
||||
} else if (i <= 40) {
|
||||
expected = 40;
|
||||
} else {
|
||||
expected = 63;
|
||||
}
|
||||
assertEquals(String.valueOf(i), expected, array.getNextSet(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNextSet5() {
|
||||
Random r = new SecureRandom(new byte[] {(byte) 0xDE, (byte) 0xAD, (byte) 0xBE, (byte) 0xEF});
|
||||
for (int i = 0; i < 10; i++) {
|
||||
BitArray array = new BitArray(1 + r.nextInt(100));
|
||||
int numSet = r.nextInt(20);
|
||||
for (int j = 0; j < numSet; j++) {
|
||||
array.set(r.nextInt(array.getSize()));
|
||||
}
|
||||
int numQueries = r.nextInt(20);
|
||||
for (int j = 0; j < numQueries; j++) {
|
||||
int query = r.nextInt(array.getSize());
|
||||
int expected = query;
|
||||
while (expected < array.getSize() && !array.get(expected)) {
|
||||
expected++;
|
||||
}
|
||||
int actual = array.getNextSet(query);
|
||||
if (actual != expected) {
|
||||
array.getNextSet(query);
|
||||
}
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSetBulk() {
|
||||
BitArray array = new BitArray(64);
|
||||
|
|
Loading…
Reference in a new issue