From 4fcf02d1f953f511ad70f81dddb14090f52d25d5 Mon Sep 17 00:00:00 2001 From: Nayuki Minase Date: Thu, 21 Apr 2016 01:57:58 +0000 Subject: [PATCH] Added comments and renamed variables in QrCode.appendErrorCorrection() in all language versions. --- cpp/QrCode.cpp | 17 +++++++++++------ java/io/nayuki/qrcodegen/QrCode.java | 19 ++++++++++++------- javascript/qrcodegen.js | 17 +++++++++++------ python/qrcodegen.py | 17 +++++++++++------ 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/cpp/QrCode.cpp b/cpp/QrCode.cpp index 0bfbd35..ec701a7 100644 --- a/cpp/QrCode.cpp +++ b/cpp/QrCode.cpp @@ -301,19 +301,22 @@ void qrcodegen::QrCode::setFunctionModule(int x, int y, bool isBlack) { std::vector qrcodegen::QrCode::appendErrorCorrection(const std::vector &data) const { if (data.size() != static_cast(getNumDataCodewords(version, errorCorrectionLevel))) throw "Invalid argument"; + + // Calculate parameter numbers int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[errorCorrectionLevel.ordinal][version]; - int numEcc = NUM_ERROR_CORRECTION_CODEWORDS[errorCorrectionLevel.ordinal][version]; - if (numEcc % numBlocks != 0) + int totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[errorCorrectionLevel.ordinal][version]; + if (totalEcc % numBlocks != 0) throw "Assertion error"; - int eccLen = numEcc / numBlocks; + int blockEccLen = totalEcc / numBlocks; int numShortBlocks = numBlocks - getNumRawDataModules(version) / 8 % numBlocks; int shortBlockLen = getNumRawDataModules(version) / 8 / numBlocks; + // Split data into blocks and append ECC to each block std::vector> blocks; - const ReedSolomonGenerator rs(eccLen); + const ReedSolomonGenerator rs(blockEccLen); for (int i = 0, k = 0; i < numBlocks; i++) { std::vector dat; - dat.insert(dat.begin(), data.begin() + k, data.begin() + (k + shortBlockLen - eccLen + (i < numShortBlocks ? 0 : 1))); + dat.insert(dat.begin(), data.begin() + k, data.begin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1))); k += dat.size(); const std::vector ecc(rs.getRemainder(dat)); if (i < numShortBlocks) @@ -322,10 +325,12 @@ std::vector qrcodegen::QrCode::appendErrorCorrection(const std::vector< blocks.push_back(dat); } + // Interleave (not concatenate) the bytes from every block into a single sequence std::vector result; for (int i = 0; static_cast(i) < blocks.at(0).size(); i++) { for (int j = 0; static_cast(j) < blocks.size(); j++) { - if (i != shortBlockLen - eccLen || j >= numShortBlocks) + // Skip the padding byte in short blocks + if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) result.push_back(blocks.at(j).at(i)); } } diff --git a/java/io/nayuki/qrcodegen/QrCode.java b/java/io/nayuki/qrcodegen/QrCode.java index e610ce3..7fbbdc2 100644 --- a/java/io/nayuki/qrcodegen/QrCode.java +++ b/java/io/nayuki/qrcodegen/QrCode.java @@ -455,29 +455,34 @@ public final class QrCode { private byte[] appendErrorCorrection(byte[] data) { if (data.length != getNumDataCodewords(version, errorCorrectionLevel)) throw new IllegalArgumentException(); + + // Calculate parameter numbers int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[errorCorrectionLevel.ordinal()][version]; - int numEcc = NUM_ERROR_CORRECTION_CODEWORDS[errorCorrectionLevel.ordinal()][version]; - if (numEcc % numBlocks != 0) + int totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[errorCorrectionLevel.ordinal()][version]; + if (totalEcc % numBlocks != 0) throw new AssertionError(); - int eccLen = numEcc / numBlocks; + int blockEccLen = totalEcc / numBlocks; int numShortBlocks = numBlocks - getNumRawDataModules(version) / 8 % numBlocks; int shortBlockLen = getNumRawDataModules(version) / 8 / numBlocks; + // Split data into blocks and append ECC to each block byte[][] blocks = new byte[numBlocks][]; - ReedSolomonGenerator rs = new ReedSolomonGenerator(eccLen); + ReedSolomonGenerator rs = new ReedSolomonGenerator(blockEccLen); for (int i = 0, k = 0; i < numBlocks; i++) { - byte[] dat = Arrays.copyOfRange(data, k, k + shortBlockLen - eccLen + (i < numShortBlocks ? 0 : 1)); + byte[] dat = Arrays.copyOfRange(data, k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)); byte[] block = Arrays.copyOf(dat, shortBlockLen + 1); k += dat.length; byte[] ecc = rs.getRemainder(dat); - System.arraycopy(ecc, 0, block, block.length - eccLen, ecc.length); + System.arraycopy(ecc, 0, block, block.length - blockEccLen, ecc.length); blocks[i] = block; } + // Interleave (not concatenate) the bytes from every block into a single sequence byte[] result = new byte[getNumRawDataModules(version) / 8]; for (int i = 0, k = 0; i < blocks[0].length; i++) { for (int j = 0; j < blocks.length; j++) { - if (i != shortBlockLen - eccLen || j >= numShortBlocks) { + // Skip the padding byte in short blocks + if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) { result[k] = blocks[j][i]; k++; } diff --git a/javascript/qrcodegen.js b/javascript/qrcodegen.js index ceea27c..5a40e4e 100644 --- a/javascript/qrcodegen.js +++ b/javascript/qrcodegen.js @@ -337,18 +337,21 @@ var qrcodegen = new function() { function appendErrorCorrection(data) { if (data.length != QrCode.getNumDataCodewords(version, errCorLvl)) throw "Invalid argument"; + + // Calculate parameter numbers var numBlocks = QrCode.NUM_ERROR_CORRECTION_BLOCKS[errCorLvl.ordinal][version]; - var numEcc = QrCode.NUM_ERROR_CORRECTION_CODEWORDS[errCorLvl.ordinal][version]; - if (numEcc % numBlocks != 0) + var totalEcc = QrCode.NUM_ERROR_CORRECTION_CODEWORDS[errCorLvl.ordinal][version]; + if (totalEcc % numBlocks != 0) throw "Assertion error"; - var eccLen = Math.floor(numEcc / numBlocks); + var blockEccLen = Math.floor(totalEcc / numBlocks); var numShortBlocks = numBlocks - Math.floor(QrCode.getNumRawDataModules(version) / 8) % numBlocks; var shortBlockLen = Math.floor(QrCode.getNumRawDataModules(version) / (numBlocks * 8)); + // Split data into blocks and append ECC to each block var blocks = []; - var rs = new ReedSolomonGenerator(eccLen); + var rs = new ReedSolomonGenerator(blockEccLen); for (var i = 0, k = 0; i < numBlocks; i++) { - var dat = data.slice(k, k + shortBlockLen - eccLen + (i < numShortBlocks ? 0 : 1)); + var dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)); k += dat.length; var ecc = rs.getRemainder(dat); if (i < numShortBlocks) @@ -359,10 +362,12 @@ var qrcodegen = new function() { blocks.push(dat); } + // Interleave (not concatenate) the bytes from every block into a single sequence var result = []; for (var i = 0; i < blocks[0].length; i++) { for (var j = 0; j < blocks.length; j++) { - if (i != shortBlockLen - eccLen || j >= numShortBlocks) + // Skip the padding byte in short blocks + if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) result.push(blocks[j][i]); } } diff --git a/python/qrcodegen.py b/python/qrcodegen.py index 8dd0616..7fbdde9 100644 --- a/python/qrcodegen.py +++ b/python/qrcodegen.py @@ -357,18 +357,21 @@ class QrCode(object): codewords appended to it, based on this object's version and error correction level.""" version = self._version assert len(data) == QrCode._get_num_data_codewords(version, self._errcorlvl) + + # Calculate parameter numbers numblocks = QrCode._NUM_ERROR_CORRECTION_BLOCKS[self._errcorlvl.ordinal][version] - numecc = QrCode._NUM_ERROR_CORRECTION_CODEWORDS[self._errcorlvl.ordinal][version] - assert numecc % numblocks == 0 - ecclen = numecc // numblocks + totalecc = QrCode._NUM_ERROR_CORRECTION_CODEWORDS[self._errcorlvl.ordinal][version] + assert totalecc % numblocks == 0 + blockecclen = totalecc // numblocks numshortblocks = numblocks - QrCode._get_num_raw_data_modules(version) // 8 % numblocks shortblocklen = self._get_num_raw_data_modules(version) // 8 // numblocks + # Split data into blocks and append ECC to each block blocks = [] - rs = _ReedSolomonGenerator(ecclen) + rs = _ReedSolomonGenerator(blockecclen) k = 0 for i in range(numblocks): - dat = data[k : k + shortblocklen - ecclen + (0 if i < numshortblocks else 1)] + dat = data[k : k + shortblocklen - blockecclen + (0 if i < numshortblocks else 1)] k += len(dat) ecc = rs.get_remainder(dat) if i < numshortblocks: @@ -377,10 +380,12 @@ class QrCode(object): blocks.append(dat) assert k == len(data) + # Interleave (not concatenate) the bytes from every block into a single sequence result = [] for i in range(len(blocks[0])): for (j, blk) in enumerate(blocks): - if i != shortblocklen - ecclen or j >= numshortblocks: + # Skip the padding byte in short blocks + if i != shortblocklen - blockecclen or j >= numshortblocks: result.append(blk[i]) assert len(result) == QrCode._get_num_raw_data_modules(version) // 8 return result