From 5073db448757c760b3944ab846cd527f373bcf9f Mon Sep 17 00:00:00 2001 From: Project Nayuki Date: Sun, 26 Aug 2018 03:20:12 +0000 Subject: [PATCH] Somewhat simplified black/white balance penalty calculation in all language versions. --- c/qrcodegen.c | 7 ++++--- cpp/QrCode.cpp | 7 ++++--- java/io/nayuki/qrcodegen/QrCode.java | 7 ++++--- javascript/qrcodegen.js | 7 ++++--- python/qrcodegen.py | 9 ++++----- rust/src/lib.rs | 10 ++++------ typescript/qrcodegen.ts | 7 ++++--- 7 files changed, 28 insertions(+), 26 deletions(-) diff --git a/c/qrcodegen.c b/c/qrcodegen.c index eac0a21..44c041a 100644 --- a/c/qrcodegen.c +++ b/c/qrcodegen.c @@ -619,10 +619,11 @@ static long getPenaltyScore(const uint8_t qrcode[]) { black++; } } + // Note that size is odd, so black/total != 1/2 int total = qrsize * qrsize; - // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% - for (int k = 0; black*20L < (9L-k)*total || black*20L > (11L+k)*total; k++) - result += PENALTY_N4; + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1; + result += k * PENALTY_N4; return result; } diff --git a/cpp/QrCode.cpp b/cpp/QrCode.cpp index 3c6046a..61d583b 100644 --- a/cpp/QrCode.cpp +++ b/cpp/QrCode.cpp @@ -485,10 +485,11 @@ long QrCode::getPenaltyScore() const { black++; } } + // Note that size is odd, so black/total != 1/2 int total = size * size; - // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% - for (int k = 0; black*20L < (9L-k)*total || black*20L > (11L+k)*total; k++) - result += PENALTY_N4; + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + int k = static_cast((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1; + result += k * PENALTY_N4; return result; } diff --git a/java/io/nayuki/qrcodegen/QrCode.java b/java/io/nayuki/qrcodegen/QrCode.java index 6b20b7f..80a4ee9 100644 --- a/java/io/nayuki/qrcodegen/QrCode.java +++ b/java/io/nayuki/qrcodegen/QrCode.java @@ -632,10 +632,11 @@ public final class QrCode { black++; } } + // Note that size is odd, so black/total != 1/2 int total = size * size; - // 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++) - result += PENALTY_N4; + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + int k = (Math.abs(black * 20 - total * 10) + total - 1) / total - 1; + result += k * PENALTY_N4; return result; } diff --git a/javascript/qrcodegen.js b/javascript/qrcodegen.js index dfb768a..0288aaa 100644 --- a/javascript/qrcodegen.js +++ b/javascript/qrcodegen.js @@ -480,10 +480,11 @@ var qrcodegen = new function() { black++; }); }); + // Note that size is odd, so black/total != 1/2 var total = size * size; - // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% - for (var k = 0; black*20 < (9-k)*total || black*20 > (11+k)*total; k++) - result += QrCode.PENALTY_N4; + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + var k = Math.ceil(Math.abs(black * 20 - total * 10) / total) - 1; + result += k * QrCode.PENALTY_N4; return result; } diff --git a/python/qrcodegen.py b/python/qrcodegen.py index 1c0cda5..22c2252 100644 --- a/python/qrcodegen.py +++ b/python/qrcodegen.py @@ -476,12 +476,11 @@ class QrCode(object): # Balance of black and white modules 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 - # Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% - for k in itertools.count(): - if (9-k)*total <= black*20 <= (11+k)*total: - break - result += QrCode._PENALTY_N4 + # Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + k = (abs(black * 20 - total * 10) + total - 1) // total - 1 + result += k * QrCode._PENALTY_N4 return result diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 5654b0a..ee24836 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -609,13 +609,11 @@ impl QrCode { for color in &self.modules { black += *color as i32; } + // Note that size is odd, so black/total != 1/2 let total: i32 = size * size; - // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% - let mut k: i32 = 0; - while black*20 < (9-k)*total || black*20 > (11+k)*total { - result += PENALTY_N4; - k += 1; - } + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + let k: i32 = ((black * 20 - total * 10).abs() + total - 1) / total - 1; + result += k * PENALTY_N4; result } diff --git a/typescript/qrcodegen.ts b/typescript/qrcodegen.ts index 3ae9bc7..52b2a4f 100644 --- a/typescript/qrcodegen.ts +++ b/typescript/qrcodegen.ts @@ -548,10 +548,11 @@ namespace qrcodegen { black++; }); }); + // Note that size is odd, so black/total != 1/2 let total: int = this.size * this.size; - // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% - for (let k = 0; black*20 < (9-k)*total || black*20 > (11+k)*total; k++) - result += QrCode.PENALTY_N4; + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + let k: int = Math.ceil(Math.abs(black * 20 - total * 10) / total) - 1; + result += k * QrCode.PENALTY_N4; return result; }