From f18ababe0d1db647d70e79733f0af409d721bf48 Mon Sep 17 00:00:00 2001 From: Project Nayuki Date: Mon, 17 Apr 2017 18:02:14 +0000 Subject: [PATCH] Continued implementing C library by adding low-level QR Code get/set functions. --- c/qrcodegen.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ c/qrcodegen.h | 16 ++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/c/qrcodegen.c b/c/qrcodegen.c index c7df95d..b5ddb82 100644 --- a/c/qrcodegen.c +++ b/c/qrcodegen.c @@ -30,6 +30,10 @@ /*---- Forward declarations for private functions ----*/ +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 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); @@ -73,6 +77,50 @@ bool qrcodegen_isNumeric(const char *text) { } +// Public function - see documentation comment in header file. +int qrcodegen_getSize(int version) { + assert(1 <= version && version <= 40); + return version * 4 + 17; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_getModule(const uint8_t qrcode[], int version, int x, int y) { + int size = qrcodegen_getSize(version); + return (0 <= x && x < size && 0 <= y && y < size) && getModule(qrcode, size, x, y); +} + + +// Gets the module at the given coordinates, which must be in bounds. +static bool getModule(const uint8_t qrcode[], int size, int x, int y) { + assert(21 <= size && size <= 177 && 0 <= x && x < size && 0 <= y && y < size); + int index = y * size + x; + int bitIndex = index & 7; + int byteIndex = index >> 3; + return ((qrcode[byteIndex] >> bitIndex) & 1) != 0; +} + + +// Sets the module at the given coordinates, which must be in bounds. +static void setModule(uint8_t qrcode[], int size, int x, int y, bool isBlack) { + assert(21 <= size && size <= 177 && 0 <= x && x < size && 0 <= y && y < size); + int index = y * size + x; + int bitIndex = index & 7; + int byteIndex = index >> 3; + if (isBlack) + qrcode[byteIndex] |= 1 << bitIndex; + else + qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; +} + + +// Sets the module at the given coordinates, doing nothing if out of bounds. +static void setModuleBounded(uint8_t qrcode[], int size, int x, int y, bool isBlack) { + if (0 <= x && x < size && 0 <= y && y < size) + setModule(qrcode, size, x, y, isBlack); +} + + // 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 diff --git a/c/qrcodegen.h b/c/qrcodegen.h index c85765f..1d6448c 100644 --- a/c/qrcodegen.h +++ b/c/qrcodegen.h @@ -37,3 +37,19 @@ bool qrcodegen_isAlphanumeric(const char *text); * Tests whether the given string can be encoded in numeric mode. */ bool qrcodegen_isNumeric(const char *text); + + +/* + * Returns the side length of any QR Code of the given version. + * The version must be in the range [1, 40]. The result is in the range [21, 177]. + * Note that the length of any QR Code byte buffer must be at least ceil(size^2 / 8). + */ +int qrcodegen_getSize(int version); + + +/* + * Returns the color of the module (pixel) at the given coordinates, which is either + * true for white or false for black. The top left corner has the coordinates (x=0, y=0). + * If the given coordinates are out of bounds, then false (white) is returned. + */ +bool qrcodegen_getModule(const uint8_t qrcode[], int version, int x, int y);