Somewhat simplified black/white balance penalty calculation in all language versions.

This commit is contained in:
Project Nayuki 2018-08-26 03:20:12 +00:00
parent 7d7a9b4820
commit 5073db4487
7 changed files with 28 additions and 26 deletions

View File

@ -619,10 +619,11 @@ static long getPenaltyScore(const uint8_t qrcode[]) {
black++; black++;
} }
} }
// Note that size is odd, so black/total != 1/2
int total = qrsize * qrsize; int total = qrsize * qrsize;
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
for (int k = 0; black*20L < (9L-k)*total || black*20L > (11L+k)*total; k++) int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1;
result += PENALTY_N4; result += k * PENALTY_N4;
return result; return result;
} }

View File

@ -485,10 +485,11 @@ long QrCode::getPenaltyScore() const {
black++; black++;
} }
} }
// Note that size is odd, so black/total != 1/2
int total = size * size; int total = size * size;
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
for (int k = 0; black*20L < (9L-k)*total || black*20L > (11L+k)*total; k++) int k = static_cast<int>((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1;
result += PENALTY_N4; result += k * PENALTY_N4;
return result; return result;
} }

View File

@ -632,10 +632,11 @@ public final class QrCode {
black++; black++;
} }
} }
// Note that size is odd, so black/total != 1/2
int total = size * size; int total = size * size;
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
for (int k = 0; black*20 < (9-k)*total || black*20 > (11+k)*total; k++) int k = (Math.abs(black * 20 - total * 10) + total - 1) / total - 1;
result += PENALTY_N4; result += k * PENALTY_N4;
return result; return result;
} }

View File

@ -480,10 +480,11 @@ var qrcodegen = new function() {
black++; black++;
}); });
}); });
// Note that size is odd, so black/total != 1/2
var total = size * size; var total = size * size;
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
for (var k = 0; black*20 < (9-k)*total || black*20 > (11+k)*total; k++) var k = Math.ceil(Math.abs(black * 20 - total * 10) / total) - 1;
result += QrCode.PENALTY_N4; result += k * QrCode.PENALTY_N4;
return result; return result;
} }

View File

@ -476,12 +476,11 @@ class QrCode(object):
# Balance of black and white modules # Balance of black and white modules
black = sum((1 if cell else 0) for row in modules for cell in row) black = sum((1 if cell else 0) for row in modules for cell in row)
# Note that size is odd, so black/total != 1/2
total = size**2 total = size**2
# Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% # Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
for k in itertools.count(): k = (abs(black * 20 - total * 10) + total - 1) // total - 1
if (9-k)*total <= black*20 <= (11+k)*total: result += k * QrCode._PENALTY_N4
break
result += QrCode._PENALTY_N4
return result return result

View File

@ -609,13 +609,11 @@ impl QrCode {
for color in &self.modules { for color in &self.modules {
black += *color as i32; black += *color as i32;
} }
// Note that size is odd, so black/total != 1/2
let total: i32 = size * size; let total: i32 = size * size;
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
let mut k: i32 = 0; let k: i32 = ((black * 20 - total * 10).abs() + total - 1) / total - 1;
while black*20 < (9-k)*total || black*20 > (11+k)*total { result += k * PENALTY_N4;
result += PENALTY_N4;
k += 1;
}
result result
} }

View File

@ -548,10 +548,11 @@ namespace qrcodegen {
black++; black++;
}); });
}); });
// Note that size is odd, so black/total != 1/2
let total: int = this.size * this.size; let total: int = this.size * this.size;
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
for (let k = 0; black*20 < (9-k)*total || black*20 > (11+k)*total; k++) let k: int = Math.ceil(Math.abs(black * 20 - total * 10) / total) - 1;
result += QrCode.PENALTY_N4; result += k * QrCode.PENALTY_N4;
return result; return result;
} }