Simplified and renamed addEccAndInterleave(), based on the slow QR library C version algorithm.

pull/134/head
Project Nayuki 6 years ago
parent ccd7f3e9e8
commit f8e59274f6

@ -140,7 +140,7 @@ public final class QrCode {
modules = tpl.template.clone(); modules = tpl.template.clone();
// Draw function patterns, draw all codewords, do masking // Draw function patterns, draw all codewords, do masking
byte[] allCodewords = appendErrorCorrection(dataCodewords); byte[] allCodewords = addEccAndInterleave(dataCodewords);
drawCodewords(tpl.dataOutputBitIndexes, allCodewords); drawCodewords(tpl.dataOutputBitIndexes, allCodewords);
this.mask = handleConstructorMasking(tpl.masks, mask); this.mask = handleConstructorMasking(tpl.masks, mask);
} }
@ -279,7 +279,7 @@ public final class QrCode {
// Returns a new byte string representing the given data with the appropriate error correction // Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level. // codewords appended to it, based on this object's version and error correction level.
private byte[] appendErrorCorrection(byte[] data) { private byte[] addEccAndInterleave(byte[] data) {
if (data.length != getNumDataCodewords(version, errorCorrectionLevel)) if (data.length != getNumDataCodewords(version, errorCorrectionLevel))
throw new IllegalArgumentException(); throw new IllegalArgumentException();
@ -288,28 +288,23 @@ public final class QrCode {
int blockEccLen = ECC_CODEWORDS_PER_BLOCK[errorCorrectionLevel.ordinal()][version]; int blockEccLen = ECC_CODEWORDS_PER_BLOCK[errorCorrectionLevel.ordinal()][version];
int rawCodewords = QrTemplate.getNumRawDataModules(version) / 8; int rawCodewords = QrTemplate.getNumRawDataModules(version) / 8;
int numShortBlocks = numBlocks - rawCodewords % numBlocks; int numShortBlocks = numBlocks - rawCodewords % numBlocks;
int shortBlockLen = rawCodewords / numBlocks; int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen;
// Split data into blocks and append ECC to each block // Split data into blocks, calculate ECC, and interleave
byte[][] blocks = new byte[numBlocks][shortBlockLen + 1]; // (not concatenate) the bytes into a single sequence
byte[] result = new byte[rawCodewords];
ReedSolomonGenerator rs = ReedSolomonGenerator.getInstance(blockEccLen); ReedSolomonGenerator rs = ReedSolomonGenerator.getInstance(blockEccLen);
byte[] ecc = new byte[blockEccLen]; // Temporary storage per iteration
for (int i = 0, k = 0; i < numBlocks; i++) { for (int i = 0, k = 0; i < numBlocks; i++) {
int datLen = shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1); int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1);
System.arraycopy(data, k, blocks[i], 0, datLen); rs.getRemainder(data, k, datLen, ecc, 0);
rs.getRemainder(data, k, datLen, blocks[i], shortBlockLen + 1 - blockEccLen); for (int j = 0, l = i; j < datLen; j++, k++, l += numBlocks) { // Copy data
k += datLen; if (j == shortBlockDataLen)
} l -= numShortBlocks;
result[l] = data[k];
// Interleave (not concatenate) the bytes from every block into a single sequence }
byte[] result = new byte[rawCodewords]; for (int j = 0, l = data.length + i; j < blockEccLen; j++, l += numBlocks) // Copy ECC
for (int i = 0, k = 0; i < blocks[0].length; i++) { result[l] = ecc[j];
for (int j = 0; j < blocks.length; j++) {
// Skip the padding byte in short blocks
if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) {
result[k] = blocks[j][i];
k++;
}
}
} }
return result; return result;
} }

Loading…
Cancel
Save