Added comments and renamed variables in QrCode.appendErrorCorrection() in all language versions.

This commit is contained in:
Nayuki Minase 2016-04-21 01:57:58 +00:00
parent 1fb0283189
commit 4fcf02d1f9
4 changed files with 45 additions and 25 deletions

View File

@ -301,19 +301,22 @@ void qrcodegen::QrCode::setFunctionModule(int x, int y, bool isBlack) {
std::vector<uint8_t> qrcodegen::QrCode::appendErrorCorrection(const std::vector<uint8_t> &data) const {
if (data.size() != static_cast<unsigned int>(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<std::vector<uint8_t>> blocks;
const ReedSolomonGenerator rs(eccLen);
const ReedSolomonGenerator rs(blockEccLen);
for (int i = 0, k = 0; i < numBlocks; i++) {
std::vector<uint8_t> 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<uint8_t> ecc(rs.getRemainder(dat));
if (i < numShortBlocks)
@ -322,10 +325,12 @@ std::vector<uint8_t> qrcodegen::QrCode::appendErrorCorrection(const std::vector<
blocks.push_back(dat);
}
// Interleave (not concatenate) the bytes from every block into a single sequence
std::vector<uint8_t> result;
for (int i = 0; static_cast<unsigned int>(i) < blocks.at(0).size(); i++) {
for (int j = 0; static_cast<unsigned int>(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));
}
}

View File

@ -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++;
}

View File

@ -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]);
}
}

View File

@ -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