@TODO: Return error if data is too big.
| 768 | |
| 769 | // @TODO: Return error if data is too big. |
| 770 | int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length) { |
| 771 | uint8_t size = version * 4 + 17; |
| 772 | qrcode->version = version; |
| 773 | qrcode->size = size; |
| 774 | qrcode->ecc = ecc; |
| 775 | qrcode->modules = modules; |
| 776 | |
| 777 | uint8_t eccFormatBits = (ECC_FORMAT_BITS >> (2 * ecc)) & 0x03; |
| 778 | |
| 779 | #if LOCK_VERSION == 0 |
| 780 | uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1]; |
| 781 | uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits][version - 1]; |
| 782 | #else |
| 783 | version = LOCK_VERSION; |
| 784 | uint16_t moduleCount = NUM_RAW_DATA_MODULES; |
| 785 | uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits]; |
| 786 | #endif |
| 787 | |
| 788 | struct BitBucket codewords; |
| 789 | uint8_t codewordBytes[bb_getBufferSizeBytes(moduleCount)]; |
| 790 | bb_initBuffer(&codewords, codewordBytes, (int32_t)sizeof(codewordBytes)); |
| 791 | |
| 792 | // Place the data code words into the buffer |
| 793 | int8_t mode = encodeDataCodewords(&codewords, data, length, version); |
| 794 | |
| 795 | if (mode < 0) { return -1; } |
| 796 | qrcode->mode = mode; |
| 797 | |
| 798 | // Add terminator and pad up to a byte if applicable |
| 799 | uint32_t padding = (dataCapacity * 8) - codewords.bitOffsetOrWidth; |
| 800 | if (padding > 4) { padding = 4; } |
| 801 | bb_appendBits(&codewords, 0, padding); |
| 802 | bb_appendBits(&codewords, 0, (8 - codewords.bitOffsetOrWidth % 8) % 8); |
| 803 | |
| 804 | // Pad with alternate bytes until data capacity is reached |
| 805 | for (uint8_t padByte = 0xEC; codewords.bitOffsetOrWidth < (dataCapacity * 8); padByte ^= 0xEC ^ 0x11) { |
| 806 | bb_appendBits(&codewords, padByte, 8); |
| 807 | } |
| 808 | |
| 809 | BitBucket modulesGrid; |
| 810 | bb_initGrid(&modulesGrid, modules, size); |
| 811 | |
| 812 | BitBucket isFunctionGrid; |
| 813 | uint8_t isFunctionGridBytes[bb_getGridSizeBytes(size)]; |
| 814 | bb_initGrid(&isFunctionGrid, isFunctionGridBytes, size); |
| 815 | |
| 816 | // Draw function patterns, draw all codewords, do masking |
| 817 | drawFunctionPatterns(&modulesGrid, &isFunctionGrid, version, eccFormatBits); |
| 818 | performErrorCorrection(version, eccFormatBits, &codewords); |
| 819 | drawCodewords(&modulesGrid, &isFunctionGrid, &codewords); |
| 820 | |
| 821 | // Find the best (lowest penalty) mask |
| 822 | uint8_t mask = 0; |
| 823 | int32_t minPenalty = INT32_MAX; |
| 824 | for (uint8_t i = 0; i < 8; i++) { |
| 825 | drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, i); |
| 826 | applyMask(&modulesGrid, &isFunctionGrid, i); |
| 827 | int penalty = getPenaltyScore(&modulesGrid); |
no test coverage detected