Continued implementing C library by adding functions to fill QR Code function patterns.

This commit is contained in:
Project Nayuki 2017-04-17 18:26:29 +00:00
parent f18ababe0d
commit 261d57607b
1 changed files with 82 additions and 0 deletions

View File

@ -34,6 +34,9 @@ static bool getModule(const uint8_t qrcode[], int size, int x, int y);
static void setModule(uint8_t qrcode[], int size, int x, int y, bool isBlack);
static void setModuleBounded(uint8_t qrcode[], int size, int x, int y, bool isBlack);
static void initializeFunctionalModules(int version, uint8_t qrcode[]);
static int getAlignmentPatternPositions(int version, uint8_t result[7]);
static void calcReedSolomonGenerator(int degree, uint8_t result[]);
static void calcReedSolomonRemainder(const uint8_t data[], int dataLen, const uint8_t generator[], int degree, uint8_t result[]);
static uint8_t finiteFieldMultiply(uint8_t x, uint8_t y);
@ -121,6 +124,85 @@ static void setModuleBounded(uint8_t qrcode[], int size, int x, int y, bool isBl
}
// Fills the given QR Code grid with white modules for the given version's size,
// then marks every function module in the QR Code as black.
static void initializeFunctionalModules(int version, uint8_t qrcode[]) {
// Initialize QR Code
int size = qrcodegen_getSize(version);
memset(qrcode, 0, (size * size + 7) / 8 * sizeof(qrcode[0]));
// Fill horizontal and vertical timing patterns
for (int i = 0; i < size; i++) {
setModule(qrcode, size, 6, i, true);
setModule(qrcode, size, i, 6, true);
}
// Fill 3 finder patterns (all corners except bottom right)
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
setModule(qrcode, size, j, i, true);
setModule(qrcode, size, size - 1 - j, i, true);
setModule(qrcode, size, j, size - 1 - i, true);
}
}
// Fill numerous alignment patterns
uint8_t alignPatPos[7] = {};
int numAlign = getAlignmentPatternPositions(version, alignPatPos);
for (int i = 0; i < numAlign; i++) {
for (int j = 0; j < numAlign; j++) {
if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))
continue; // Skip the three finder corners
else {
for (int k = -2; k <= 2; k++) {
for (int l = -2; l <= 2; l++)
setModule(qrcode, size, alignPatPos[i] + l, alignPatPos[j] + k, true);
}
}
}
}
// Fill format bits
for (int i = 0; i < 8; i++) {
setModule(qrcode, size, i, 8, true);
setModule(qrcode, size, 8, i, true);
setModule(qrcode, size, size - 1 - i, 8, true);
setModule(qrcode, size, 8, size - 1 - i, true);
}
setModule(qrcode, size, 8, 8, true);
// Fill version
if (version >= 7) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 6; j++) {
int k = size - 11 + i;
setModule(qrcode, size, k, j, true);
setModule(qrcode, size, j, k, true);
}
}
}
}
// Calculates the positions of alignment patterns in ascending order for the given version number,
// storing them to the given array and returning an array length in the range [0, 7].
static int getAlignmentPatternPositions(int version, uint8_t result[7]) {
if (version == 1)
return 0;
int size = qrcodegen_getSize(version);
int numAlign = version / 7 + 2;
int step;
if (version != 32)
step = (version * 4 + numAlign * 2 + 1) / (2 * numAlign - 2) * 2; // ceil((size - 13) / (2*numAlign - 2)) * 2
else // C-C-C-Combo breaker!
step = 26;
for (int i = numAlign - 1, pos = size - 7; i >= 1; i--, pos -= step)
result[i] = pos;
result[0] = 6;
return numAlign;
}
// Calculates the Reed-Solomon generator polynomial of the given degree, storing in result[0 : degree].
static void calcReedSolomonGenerator(int degree, uint8_t result[]) {
// Start with the monomial x^0