Continued implementing C library by adding functions to draw codewords and apply masking.

pull/11/head
Project Nayuki 8 years ago
parent a0033275e3
commit 3f6916d43e

@ -39,6 +39,9 @@ static void drawWhiteFunctionModules(uint8_t qrcode[], int version);
static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[], int size);
static int getAlignmentPatternPositions(int version, uint8_t result[7]);
static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[], int version);
static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], int size, int mask);
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);
@ -309,6 +312,64 @@ static int getAlignmentPatternPositions(int version, uint8_t result[7]) {
}
// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of
// the QR Code to be black at function modules and white at codeword modules (including unused remainder bits).
static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[], int version) {
int size = qrcodegen_getSize(version);
int i = 0; // Bit index into the data
// Do the funny zigzag scan
for (int right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair
if (right == 6)
right = 5;
for (int vert = 0; vert < size; vert++) { // Vertical counter
for (int j = 0; j < 2; j++) {
int x = right - j; // Actual x coordinate
bool upwards = ((right & 2) == 0) ^ (x < 6);
int y = upwards ? size - 1 - vert : vert; // Actual y coordinate
if (!getModule(qrcode, size, x, y) && i < dataLen * 8) {
bool black = ((data[i >> 3] >> (7 - (i & 7))) & 1) != 0;
setModule(qrcode, size, x, y, black);
i++;
}
// If there are any remainder bits (0 to 7), they are already
// set to 0/false/white when the grid of modules was initialized
}
}
}
assert(i == dataLen * 8);
}
// XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical
// properties, calling applyMask(m) twice with the same value is equivalent to no change at all.
// This means it is possible to apply a mask, undo it, and try another mask. Note that a final
// well-formed QR Code symbol needs exactly one mask applied (not zero, not two, etc.).
static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], int size, int mask) {
assert(0 <= mask && mask <= 7);
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (getModule(functionModules, size, x, y))
continue;
bool invert;
switch (mask) {
case 0: invert = (x + y) % 2 == 0; break;
case 1: invert = y % 2 == 0; break;
case 2: invert = x % 3 == 0; break;
case 3: invert = (x + y) % 3 == 0; break;
case 4: invert = (x / 3 + y / 2) % 2 == 0; break;
case 5: invert = x * y % 2 + x * y % 3 == 0; break;
case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break;
case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break;
default: assert(false);
}
bool val = getModule(qrcode, size, x, y);
setModule(qrcode, size, x, y, val ^ invert);
}
}
}
// 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

Loading…
Cancel
Save