Sped up QrCode.getPenaltyScore() by combining and rewriting loops.

pull/134/head
Project Nayuki 7 years ago
parent 797d5bc3d0
commit aef4073a22

@ -378,72 +378,72 @@ public final class QrCode {
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
private int getPenaltyScore() { private int getPenaltyScore() {
int result = 0; int result = 0;
int black = 0;
// Adjacent modules in row having same color // Iterate over adjacent pairs of rows
for (int y = 0; y < size; y++) { for (int index = 0, downIndex = size, end = size * size; index < end; ) {
int colorX = 0; int bits = 0;
for (int x = 0, runX = 0; x < size; x++) { int downBits = 0;
if (x == 0 || getModuleUnchecked(x, y) != colorX) { int runColor = 0;
colorX = getModuleUnchecked(x, y); int runLen = 0;
runX = 1; for (int x = 0; x < size; x++, index++, downIndex++) {
// Adjacent modules having same color
int bit = (modules[index >>> 5] >>> index) & 1;
if (bit != runColor) {
runColor = bit;
runLen = 1;
} else { } else {
runX++; runLen++;
if (runX == 5) if (runLen == 5)
result += PENALTY_N1; result += PENALTY_N1;
else if (runX > 5) else if (runLen > 5)
result++; result++;
} }
}
}
// Adjacent modules in column having same color
for (int x = 0; x < size; x++) {
int colorY = 0;
for (int y = 0, runY = 0; y < size; y++) {
if (y == 0 || getModuleUnchecked(x, y) != colorY) {
colorY = getModuleUnchecked(x, y);
runY = 1;
} else {
runY++;
if (runY == 5)
result += PENALTY_N1;
else if (runY > 5)
result++;
}
}
}
black += bit;
bits = ((bits & 0b1111111111) << 1) | bit;
if (downIndex < end) {
downBits = ((downBits & 1) << 1) | ((modules[downIndex >>> 5] >>> downIndex) & 1);
// 2*2 blocks of modules having same color // 2*2 blocks of modules having same color
for (int y = 0; y < size - 1; y++) { if (x >= 1 && (downBits == 0 || downBits == 3) && downBits == (bits & 3))
for (int x = 0; x < size - 1; x++) {
int color = getModuleUnchecked(x, y);
if ( color == getModuleUnchecked(x + 1, y) &&
color == getModuleUnchecked(x, y + 1) &&
color == getModuleUnchecked(x + 1, y + 1))
result += PENALTY_N2; result += PENALTY_N2;
} }
}
// Finder-like pattern in rows // Finder-like pattern
for (int y = 0; y < size; y++) { if (x >= 10 && (bits == 0b00001011101 || bits == 0b10111010000))
for (int x = 0, bits = 0; x < size; x++) {
bits = ((bits << 1) & 0x7FF) | getModuleUnchecked(x, y);
if (x >= 10 && (bits == 0x05D || bits == 0x5D0)) // Needs 11 bits accumulated
result += PENALTY_N3; result += PENALTY_N3;
} }
} }
// Finder-like pattern in columns
// Iterate over single columns
for (int x = 0; x < size; x++) { for (int x = 0; x < size; x++) {
for (int y = 0, bits = 0; y < size; y++) { int bits = 0;
bits = ((bits << 1) & 0x7FF) | getModuleUnchecked(x, y); int runColor = 0;
if (y >= 10 && (bits == 0x05D || bits == 0x5D0)) // Needs 11 bits accumulated int runLen = 0;
for (int y = 0, index = x; y < size; y++, index += size) {
// Adjacent modules having same color
int bit = (modules[index >>> 5] >>> index) & 1;
if (bit != runColor) {
runColor = bit;
runLen = 1;
} else {
runLen++;
if (runLen == 5)
result += PENALTY_N1;
else if (runLen > 5)
result++;
}
// Finder-like pattern
bits = ((bits & 0b1111111111) << 1) | bit;
if (y >= 10 && (bits == 0b00001011101 || bits == 0b10111010000))
result += PENALTY_N3; result += PENALTY_N3;
} }
} }
// Balance of black and white modules // Balance of black and white modules
int black = 0;
for (int x : modules)
black += Integer.bitCount(x);
int total = size * size; int total = size * size;
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)%
for (int k = 0; black*20 < (9-k)*total || black*20 > (11+k)*total; k++) for (int k = 0; black*20 < (9-k)*total || black*20 > (11+k)*total; k++)

Loading…
Cancel
Save