From 261d57607b7f3b3fedd1143919f601207666c92c Mon Sep 17 00:00:00 2001 From: Project Nayuki Date: Mon, 17 Apr 2017 18:26:29 +0000 Subject: [PATCH] Continued implementing C library by adding functions to fill QR Code function patterns. --- c/qrcodegen.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/c/qrcodegen.c b/c/qrcodegen.c index b5ddb82..7a1c052 100644 --- a/c/qrcodegen.c +++ b/c/qrcodegen.c @@ -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