mirror of https://github.com/status-im/qzxing.git
Aligning implementation with the Java original version.
Added: @ BitArray => ported flip function @ BitMatrix => ported flip, rotate180, getEnclosingRectangle
This commit is contained in:
parent
148deb5108
commit
b381f9cc5e
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue