Simplified QrCode.getPenalty() in all language versions except Rust, related to commit 1439e8e4a5.

pull/84/head
Project Nayuki 5 years ago
parent ae22a368bb
commit 13a25580a3

@ -74,7 +74,7 @@ static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qr
static long getPenaltyScore(const uint8_t qrcode[]);
static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize);
static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize);
static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7]);
static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize);
testable bool getModule(const uint8_t qrcode[], int x, int y);
testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack);
@ -642,7 +642,6 @@ static long getPenaltyScore(const uint8_t qrcode[]) {
bool runColor = false;
int runX = 0;
int runHistory[7] = {0};
int padRun = qrsize; // Add white border to initial run
for (int x = 0; x < qrsize; x++) {
if (getModule(qrcode, x, y) == runColor) {
runX++;
@ -651,22 +650,20 @@ static long getPenaltyScore(const uint8_t qrcode[]) {
else if (runX > 5)
result++;
} else {
finderPenaltyAddHistory(runX + padRun, runHistory);
padRun = 0;
finderPenaltyAddHistory(runX, runHistory, qrsize);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3;
runColor = getModule(qrcode, x, y);
runX = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runX + padRun, runHistory, qrsize) * PENALTY_N3;
result += finderPenaltyTerminateAndCount(runColor, runX, runHistory, qrsize) * PENALTY_N3;
}
// Adjacent modules in column having same color, and finder-like patterns
for (int x = 0; x < qrsize; x++) {
bool runColor = false;
int runY = 0;
int runHistory[7] = {0};
int padRun = qrsize; // Add white border to initial run
for (int y = 0; y < qrsize; y++) {
if (getModule(qrcode, x, y) == runColor) {
runY++;
@ -675,15 +672,14 @@ static long getPenaltyScore(const uint8_t qrcode[]) {
else if (runY > 5)
result++;
} else {
finderPenaltyAddHistory(runY + padRun, runHistory);
padRun = 0;
finderPenaltyAddHistory(runY, runHistory, qrsize);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3;
runColor = getModule(qrcode, x, y);
runY = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runY + padRun, runHistory, qrsize) * PENALTY_N3;
result += finderPenaltyTerminateAndCount(runColor, runY, runHistory, qrsize) * PENALTY_N3;
}
// 2*2 blocks of modules having same color
@ -729,17 +725,19 @@ static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize) {
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize) {
if (currentRunColor) { // Terminate black run
finderPenaltyAddHistory(currentRunLength, runHistory);
finderPenaltyAddHistory(currentRunLength, runHistory, qrsize);
currentRunLength = 0;
}
currentRunLength += qrsize; // Add white border to final run
finderPenaltyAddHistory(currentRunLength, runHistory);
finderPenaltyAddHistory(currentRunLength, runHistory, qrsize);
return finderPenaltyCountPatterns(runHistory, qrsize);
}
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7]) {
static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize) {
if (runHistory[0] == 0)
currentRunLength += qrsize; // Add white border to initial run
memmove(&runHistory[1], &runHistory[0], 6 * sizeof(runHistory[0]));
runHistory[0] = currentRunLength;
}

@ -625,7 +625,6 @@ long QrCode::getPenaltyScore() const {
bool runColor = false;
int runX = 0;
std::array<int,7> runHistory = {};
int padRun = size; // Add white border to initial run
for (int x = 0; x < size; x++) {
if (module(x, y) == runColor) {
runX++;
@ -634,22 +633,20 @@ long QrCode::getPenaltyScore() const {
else if (runX > 5)
result++;
} else {
finderPenaltyAddHistory(runX + padRun, runHistory);
padRun = 0;
finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = module(x, y);
runX = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runX + padRun, runHistory) * PENALTY_N3;
result += finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;
}
// Adjacent modules in column having same color, and finder-like patterns
for (int x = 0; x < size; x++) {
bool runColor = false;
int runY = 0;
std::array<int,7> runHistory = {};
int padRun = size; // Add white border to initial run
for (int y = 0; y < size; y++) {
if (module(x, y) == runColor) {
runY++;
@ -658,15 +655,14 @@ long QrCode::getPenaltyScore() const {
else if (runY > 5)
result++;
} else {
finderPenaltyAddHistory(runY + padRun, runHistory);
padRun = 0;
finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = module(x, y);
runY = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runY + padRun, runHistory) * PENALTY_N3;
result += finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3;
}
// 2*2 blocks of modules having same color
@ -807,7 +803,9 @@ int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunL
}
void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) {
void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const {
if (runHistory.at(0) == 0)
currentRunLength += size; // Add white border to initial run
std::copy_backward(runHistory.cbegin(), runHistory.cend() - 1, runHistory.end());
runHistory.at(0) = currentRunLength;
}

@ -482,7 +482,7 @@ class QrCode final {
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
private: static void finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory);
private: void finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const;
// Returns true iff the i'th bit of x is set to 1.

@ -600,7 +600,6 @@ public final class QrCode {
boolean runColor = false;
int runX = 0;
int[] runHistory = new int[7];
int padRun = size; // Add white border to initial run
for (int x = 0; x < size; x++) {
if (modules[y][x] == runColor) {
runX++;
@ -609,22 +608,20 @@ public final class QrCode {
else if (runX > 5)
result++;
} else {
finderPenaltyAddHistory(runX + padRun, runHistory);
padRun = 0;
finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = modules[y][x];
runX = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runX + padRun, runHistory) * PENALTY_N3;
result += finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;
}
// Adjacent modules in column having same color, and finder-like patterns
for (int x = 0; x < size; x++) {
boolean runColor = false;
int runY = 0;
int[] runHistory = new int[7];
int padRun = size; // Add white border to initial run
for (int y = 0; y < size; y++) {
if (modules[y][x] == runColor) {
runY++;
@ -633,15 +630,14 @@ public final class QrCode {
else if (runY > 5)
result++;
} else {
finderPenaltyAddHistory(runY + padRun, runHistory);
padRun = 0;
finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = modules[y][x];
runY = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runY + padRun, runHistory) * PENALTY_N3;
result += finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3;
}
// 2*2 blocks of modules having same color
@ -814,7 +810,9 @@ public final class QrCode {
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
private static void finderPenaltyAddHistory(int currentRunLength, int[] runHistory) {
private void finderPenaltyAddHistory(int currentRunLength, int[] runHistory) {
if (runHistory[0] == 0)
currentRunLength += size; // Add white border to initial run
System.arraycopy(runHistory, 0, runHistory, 1, runHistory.length - 1);
runHistory[0] = currentRunLength;
}

@ -467,7 +467,6 @@ class QrCode(object):
runcolor = False
runx = 0
runhistory = collections.deque([0] * 7, 7)
padrun = size # Add white border to initial run
for x in range(size):
if modules[y][x] == runcolor:
runx += 1
@ -476,19 +475,17 @@ class QrCode(object):
elif runx > 5:
result += 1
else:
runhistory.appendleft(runx + padrun)
padrun = 0
self._finder_penalty_add_history(runx, runhistory)
if not runcolor:
result += self._finder_penalty_count_patterns(runhistory) * QrCode._PENALTY_N3
runcolor = modules[y][x]
runx = 1
result += self._finder_penalty_terminate_and_count(runcolor, runx + padrun, runhistory) * QrCode._PENALTY_N3
result += self._finder_penalty_terminate_and_count(runcolor, runx, runhistory) * QrCode._PENALTY_N3
# Adjacent modules in column having same color, and finder-like patterns
for x in range(size):
runcolor = False
runy = 0
runhistory = collections.deque([0] * 7, 7)
padrun = size # Add white border to initial run
for y in range(size):
if modules[y][x] == runcolor:
runy += 1
@ -497,13 +494,12 @@ class QrCode(object):
elif runy > 5:
result += 1
else:
runhistory.appendleft(runy + padrun)
padrun = 0
self._finder_penalty_add_history(runy, runhistory)
if not runcolor:
result += self._finder_penalty_count_patterns(runhistory) * QrCode._PENALTY_N3
runcolor = modules[y][x]
runy = 1
result += self._finder_penalty_terminate_and_count(runcolor, runy + padrun, runhistory) * QrCode._PENALTY_N3
result += self._finder_penalty_terminate_and_count(runcolor, runy, runhistory) * QrCode._PENALTY_N3
# 2*2 blocks of modules having same color
for y in range(size - 1):
@ -628,13 +624,19 @@ class QrCode(object):
def _finder_penalty_terminate_and_count(self, currentruncolor, currentrunlength, runhistory):
"""Must be called at the end of a line (row or column) of modules. A helper function for _get_penalty_score()."""
if currentruncolor: # Terminate black run
runhistory.appendleft(currentrunlength)
self._finder_penalty_add_history(currentrunlength, runhistory)
currentrunlength = 0
currentrunlength += self._size # Add white border to final run
runhistory.appendleft(currentrunlength)
self._finder_penalty_add_history(currentrunlength, runhistory)
return self._finder_penalty_count_patterns(runhistory)
def _finder_penalty_add_history(self, currentrunlength, runhistory):
if runhistory[0] == 0:
currentrunlength += self._size # Add white border to initial run
runhistory.appendleft(currentrunlength)
# ---- Constants and tables ----
MIN_VERSION = 1 # The minimum version number supported in the QR Code Model 2 standard

@ -515,7 +515,6 @@ namespace qrcodegen {
let runColor = false;
let runX = 0;
let runHistory = [0,0,0,0,0,0,0];
let padRun = this.size;
for (let x = 0; x < this.size; x++) {
if (this.modules[y][x] == runColor) {
runX++;
@ -524,22 +523,20 @@ namespace qrcodegen {
else if (runX > 5)
result++;
} else {
QrCode.finderPenaltyAddHistory(runX + padRun, runHistory);
padRun = 0;
this.finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
runColor = this.modules[y][x];
runX = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runX + padRun, runHistory) * QrCode.PENALTY_N3;
result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * QrCode.PENALTY_N3;
}
// Adjacent modules in column having same color, and finder-like patterns
for (let x = 0; x < this.size; x++) {
let runColor = false;
let runY = 0;
let runHistory = [0,0,0,0,0,0,0];
let padRun = this.size;
for (let y = 0; y < this.size; y++) {
if (this.modules[y][x] == runColor) {
runY++;
@ -548,15 +545,14 @@ namespace qrcodegen {
else if (runY > 5)
result++;
} else {
QrCode.finderPenaltyAddHistory(runY + padRun, runHistory);
padRun = 0;
this.finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
runColor = this.modules[y][x];
runY = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runY + padRun, runHistory) * QrCode.PENALTY_N3;
result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * QrCode.PENALTY_N3;
}
// 2*2 blocks of modules having same color
@ -705,17 +701,19 @@ namespace qrcodegen {
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
private finderPenaltyTerminateAndCount(currentRunColor: boolean, currentRunLength: int, runHistory: Array<int>): int {
if (currentRunColor) { // Terminate black run
QrCode.finderPenaltyAddHistory(currentRunLength, runHistory);
this.finderPenaltyAddHistory(currentRunLength, runHistory);
currentRunLength = 0;
}
currentRunLength += this.size; // Add white border to final run
QrCode.finderPenaltyAddHistory(currentRunLength, runHistory);
this.finderPenaltyAddHistory(currentRunLength, runHistory);
return this.finderPenaltyCountPatterns(runHistory);
}
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
private static finderPenaltyAddHistory(currentRunLength: int, runHistory: Array<int>): void {
private finderPenaltyAddHistory(currentRunLength: int, runHistory: Array<int>): void {
if (runHistory[0] == 0)
currentRunLength += this.size; // Add white border to initial run
runHistory.pop();
runHistory.unshift(currentRunLength);
}

Loading…
Cancel
Save