Aligning implementation with the Java original version.

Added:
 @ BitArray => ported flip function
 @ BitMatrix => ported flip, rotate180, getEnclosingRectangle
This commit is contained in:
favoritas37 2016-06-14 00:12:12 +03:00
parent 148deb5108
commit b381f9cc5e
6 changed files with 220 additions and 105 deletions

View File

@ -311,7 +311,7 @@ QImage QZXing::encodeData(const QString& data)
qRgb(255,255,255));
image = image.scaled(240, 240);
//bool success = image.save("tmp.bmp","BMP");
bool success = image.save("tmp.bmp","BMP");
} catch (std::exception& e) {
std::cout << "Error: " << e.what() << std::endl;
}

View File

@ -27,7 +27,7 @@ using zxing::BitArray;
using zxing::Ref;
int BitArray::makeArraySize(int size) {
return (size + bitsPerWord-1) >> logBits;
return (size + 31) / 32;
}
BitArray::BitArray(): size(0), bits(1) {}
@ -48,7 +48,7 @@ int BitArray::getSizeInBytes() const
}
void BitArray::setBulk(int i, int newBits) {
bits[i >> logBits] = newBits;
bits[i / 32] = newBits;
}
void BitArray::clear() {
@ -66,13 +66,13 @@ bool BitArray::isRange(int start, int end, bool value) {
return true; // empty range matches
}
end--; // will be easier to treat this as the last actually set bit -- inclusive
int firstInt = start >> logBits;
int lastInt = end >> logBits;
int firstInt = start / 32;
int lastInt = end / 32;
for (int i = firstInt; i <= lastInt; i++) {
int firstBit = i > firstInt ? 0 : start & bitsMask;
int lastBit = i < lastInt ? (bitsPerWord-1) : end & bitsMask;
int firstBit = i > firstInt ? 0 : start & 0x1F;
int lastBit = i < lastInt ? 31 : end & 0x1F;
int mask;
if (firstBit == 0 && lastBit == (bitsPerWord-1)) {
if (firstBit == 0 && lastBit == 31) {
mask = -1;
} else {
mask = 0;
@ -94,13 +94,36 @@ vector<int>& BitArray::getBitArray() {
return bits->values();
}
void BitArray::reverse() {
void BitArray::reverse()
{
ArrayRef<int> newBits(bits->size());
int size = this->size;
for (int i = 0; i < size; i++) {
if (get(size - i - 1)) {
newBits[i >> logBits] |= 1 << (i & bitsMask);
}
// reverse all int's first
int len = ((this->size-1) / 32);
int oldBitsLen = len + 1;
for (int i = 0; i < oldBitsLen; i++) {
long x = (long) bits[i];
x = ((x >> 1) & 0x55555555L) | ((x & 0x55555555L) << 1);
x = ((x >> 2) & 0x33333333L) | ((x & 0x33333333L) << 2);
x = ((x >> 4) & 0x0f0f0f0fL) | ((x & 0x0f0f0f0fL) << 4);
x = ((x >> 8) & 0x00ff00ffL) | ((x & 0x00ff00ffL) << 8);
x = ((x >> 16) & 0x0000ffffL) | ((x & 0x0000ffffL) << 16);
newBits[len - i] = (int) x;
}
// now correct the int's if the bit size isn't a multiple of 32
if (size != oldBitsLen * 32) {
int leftOffset = oldBitsLen * 32 - size;
int mask = 1;
for (int i = 0; i < 31 - leftOffset; i++) {
mask = (mask << 1) | 1;
}
int currentInt = (newBits[0] >> leftOffset) & mask;
for (int i = 1; i < oldBitsLen; i++) {
int nextInt = newBits[i];
currentInt |= nextInt << (32 - leftOffset);
newBits[i - 1] = currentInt;
currentInt = (nextInt >> leftOffset) & mask;
}
newBits[oldBitsLen - 1] = currentInt;
}
bits = newBits;
}

View File

@ -47,13 +47,17 @@ public:
int getSizeInBytes() const;
bool get(int i) const {
return (bits[i >> logBits] & (1 << (i & bitsMask))) != 0;
return (bits[i / 32] & (1 << (i & 0x1F))) != 0;
}
void set(int i) {
bits[i >> logBits] |= 1 << (i & bitsMask);
bits[i / 32] |= 1 << (i & 0x1F);
}
void flip(int i) {
bits[i / 32] ^= 1 << (i & 0x1F);
}
int getNextSet(int from);
int getNextUnset(int from);

View File

@ -31,113 +31,197 @@ using zxing::ArrayRef;
using zxing::Ref;
void BitMatrix::init(int width, int height) {
if (width < 1 || height < 1) {
throw IllegalArgumentException("Both dimensions must be greater than 0");
}
this->width = width;
this->height = height;
this->rowSize = (width + bitsPerWord - 1) >> logBits;
bits = ArrayRef<int>(rowSize * height);
if (width < 1 || height < 1) {
throw IllegalArgumentException("Both dimensions must be greater than 0");
}
this->width = width;
this->height = height;
this->rowSize = (width + 31) >> 5;
bits = ArrayRef<int>(rowSize * height);
}
BitMatrix::BitMatrix(int dimension) {
init(dimension, dimension);
init(dimension, dimension);
}
BitMatrix::BitMatrix(int width, int height) {
init(width, height);
init(width, height);
}
BitMatrix::~BitMatrix() {}
void BitMatrix::flip(int x, int y) {
int offset = y * rowSize + (x >> logBits);
bits[offset] ^= 1 << (x & bitsMask);
int offset = y * rowSize + (x >> 5);
bits[offset] ^= 1 << (x & 0x1f);
}
void BitMatrix::rotate180()
{
int width = getWidth();
int height = getHeight();
Ref<BitArray> topRow( new BitArray(width) );
Ref<BitArray> bottomRow( new BitArray(width) );
for (int i = 0; i < (height+1) / 2; i++) {
getRow(i, topRow);
bottomRow = getRow(height - 1 - i, bottomRow);
topRow->reverse();
bottomRow->reverse();
setRow(i, bottomRow);
setRow(height - 1 - i, topRow);
}
}
void BitMatrix::setRegion(int left, int top, int width, int height) {
if (top < 0 || left < 0) {
throw IllegalArgumentException("Left and top must be nonnegative");
}
if (height < 1 || width < 1) {
throw IllegalArgumentException("Height and width must be at least 1");
}
int right = left + width;
int bottom = top + height;
if (bottom > this->height || right > this->width) {
throw IllegalArgumentException("The region must fit inside the matrix");
}
for (int y = top; y < bottom; y++) {
int offset = y * rowSize;
for (int x = left; x < right; x++) {
bits[offset + (x >> logBits)] |= 1 << (x & bitsMask);
if (top < 0 || left < 0) {
throw IllegalArgumentException("Left and top must be nonnegative");
}
if (height < 1 || width < 1) {
throw IllegalArgumentException("Height and width must be at least 1");
}
int right = left + width;
int bottom = top + height;
if (bottom > this->height || right > this->width) {
throw IllegalArgumentException("The region must fit inside the matrix");
}
for (int y = top; y < bottom; y++) {
int offset = y * rowSize;
for (int x = left; x < right; x++) {
bits[offset + (x >> 5)] |= 1 << (x & 0x1f);
}
}
}
}
Ref<BitArray> BitMatrix::getRow(int y, Ref<BitArray> row) {
if (row.empty() || row->getSize() < width) {
row = new BitArray(width);
}
int offset = y * rowSize;
for (int x = 0; x < rowSize; x++) {
row->setBulk(x << logBits, bits[offset + x]);
}
return row;
if (row.empty() || row->getSize() < width) {
row = new BitArray(width);
}
int offset = y * rowSize;
for (int x = 0; x < rowSize; x++) {
row->setBulk(x << 5, bits[offset + x]);
}
return row;
}
void BitMatrix::setRow(int y, Ref<zxing::BitArray> row)
{
if (y < 0 || y >= bits->size() ||
row->getSize() != width)
{
throw IllegalArgumentException("setRow arguments invalid");
}
//change with memcopy
for(size_t i=0; i<width; i++)
bits[y * rowSize + i] = row->get(i);
}
int BitMatrix::getWidth() const {
return width;
return width;
}
int BitMatrix::getHeight() const {
return height;
return height;
}
ArrayRef<int> BitMatrix::getTopLeftOnBit() const {
int bitsOffset = 0;
while (bitsOffset < bits->size() && bits[bitsOffset] == 0) {
bitsOffset++;
}
if (bitsOffset == bits->size()) {
return ArrayRef<int>();
}
int y = bitsOffset / rowSize;
int x = (bitsOffset % rowSize) << 5;
int bitsOffset = 0;
while (bitsOffset < bits->size() && bits[bitsOffset] == 0) {
bitsOffset++;
}
if (bitsOffset == bits->size()) {
return ArrayRef<int>();
}
int y = bitsOffset / rowSize;
int x = (bitsOffset % rowSize) << 5;
int theBits = bits[bitsOffset];
int bit = 0;
while ((theBits << (31-bit)) == 0) {
bit++;
}
x += bit;
ArrayRef<int> res (2);
res[0]=x;
res[1]=y;
return res;
int theBits = bits[bitsOffset];
int bit = 0;
while ((theBits << (31-bit)) == 0) {
bit++;
}
x += bit;
ArrayRef<int> res (2);
res[0]=x;
res[1]=y;
return res;
}
ArrayRef<int> BitMatrix::getBottomRightOnBit() const {
int bitsOffset = bits->size() - 1;
while (bitsOffset >= 0 && bits[bitsOffset] == 0) {
bitsOffset--;
}
if (bitsOffset < 0) {
return ArrayRef<int>();
}
int bitsOffset = bits->size() - 1;
while (bitsOffset >= 0 && bits[bitsOffset] == 0) {
bitsOffset--;
}
if (bitsOffset < 0) {
return ArrayRef<int>();
}
int y = bitsOffset / rowSize;
int x = (bitsOffset % rowSize) << 5;
int y = bitsOffset / rowSize;
int x = (bitsOffset % rowSize) << 5;
int theBits = bits[bitsOffset];
int bit = 31;
while ((theBits >> bit) == 0) {
bit--;
}
x += bit;
int theBits = bits[bitsOffset];
int bit = 31;
while ((theBits >> bit) == 0) {
bit--;
}
x += bit;
ArrayRef<int> res (2);
res[0]=x;
res[1]=y;
return res;
ArrayRef<int> res (2);
res[0]=x;
res[1]=y;
return res;
}
ArrayRef<int> BitMatrix::getEnclosingRectangle() const
{
int left = width;
int top = height;
int right = -1;
int bottom = -1;
for (int y = 0; y < height; y++) {
for (int x32 = 0; x32 < rowSize; x32++) {
int theBits = bits[y * rowSize + x32];
if (theBits != 0) {
if (y < top) {
top = y;
}
if (y > bottom) {
bottom = y;
}
if (x32 * 32 < left) {
int bit = 0;
while ((theBits << (31 - bit)) == 0) {
bit++;
}
if ((x32 * 32 + bit) < left) {
left = x32 * 32 + bit;
}
}
if (x32 * 32 + 31 > right) {
int bit = 31;
while (((unsigned)theBits >> (unsigned)bit) == 0) {
bit--;
}
if ((x32 * 32 + bit) > right) {
right = x32 * 32 + bit;
}
}
}
}
}
int width = right - left;
int height = bottom - top;
if (width < 0 || height < 0) {
return ArrayRef<int>();
}
ArrayRef<int> res(4);
res[0] = left;
res[1] = top;
res[2] = width;
res[3] = height;
return res;
}

View File

@ -38,16 +38,16 @@ private:
int rowSize;
ArrayRef<int> bits;
#define ZX_LOG_DIGITS(digits) \
((digits == 8) ? 3 : \
((digits == 16) ? 4 : \
((digits == 32) ? 5 : \
((digits == 64) ? 6 : \
((digits == 128) ? 7 : \
(-1))))))
//#define ZX_LOG_DIGITS(digits) \
// ((digits == 8) ? 3 : \
// ((digits == 16) ? 4 : \
// ((digits == 32) ? 5 : \
// ((digits == 64) ? 6 : \
// ((digits == 128) ? 7 : \
// (-1))))))
static const int logBits = ZX_LOG_DIGITS(bitsPerWord);
static const int bitsMask = (1 << logBits) - 1;
// static const int logBits = ZX_LOG_DIGITS(bitsPerWord);
// static const int bitsMask = (1 << logBits) - 1;
public:
BitMatrix(int dimension);
@ -56,25 +56,29 @@ public:
~BitMatrix();
bool get(int x, int y) const {
int offset = y * rowSize + (x >> logBits);
return ((((unsigned)bits[offset]) >> (x & bitsMask)) & 1) != 0;
int offset = y * rowSize + (x >> 5);
return ((((unsigned)bits[offset]) >> (x & 0x1f)) & 1) != 0;
}
void set(int x, int y) {
int offset = y * rowSize + (x >> logBits);
bits[offset] |= 1 << (x & bitsMask);
int offset = y * rowSize + (x >> 5);
bits[offset] |= 1 << (x & 0x1f);
}
void flip(int x, int y);
void rotate180();
void clear();
void setRegion(int left, int top, int width, int height);
Ref<BitArray> getRow(int y, Ref<BitArray> row);
void setRow(int y, Ref<BitArray> row);
int getWidth() const;
int getHeight() const;
ArrayRef<int> getTopLeftOnBit() const;
ArrayRef<int> getBottomRightOnBit() const;
ArrayRef<int> getEnclosingRectangle() const;
friend std::ostream& operator<<(std::ostream &out, const BitMatrix &bm);
const char *description();

View File

@ -98,7 +98,7 @@ private:
private:
// Check if "value" is empty.
static bool isEmpty(int value) { return value == -1; }
static bool isEmpty(int value) { return value == 255; }
static void embedTimingPatterns(ByteMatrix& matrix);