├── .github └── auto-comment.yml ├── README.md ├── LICENSE ├── lv_qrcode.h ├── lv_qrcode.c ├── qrcodegen.h └── qrcodegen.c /.github/auto-comment.yml: -------------------------------------------------------------------------------- 1 | # Comment to a new issue. 2 | pullRequestOpened: | 3 | Thank you for raising your pull request. 4 | 5 | To ensure that all licensing criteria is met all repositories of the LVGL project apply a process called DCO (Developer's Certificate of Origin). 6 | 7 | The text of DCO can be read here: https://developercertificate.org/ 8 | For a more detailed description see the [Documentation](https://docs.lvgl.io/latest/en/html/contributing/index.html#developer-certification-of-origin-dco) site. 9 | 10 | By contributing to any repositories of the LVGL project you state that your contribution corresponds with the DCO. 11 | 12 | No further action is required if your contribution fulfills the DCO. If you are not sure about it feel free to ask us in a comment. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QR code library for LVGL 2 | 3 | **This repository is merged into the lvgl repository. See https://docs.lvgl.io/master/libs/qrcode.html** 4 | 5 | 6 | QR code generation with LVGL. Uses [QR-Code-generator](https://github.com/nayuki/QR-Code-generator) by [nayuki](https://github.com/nayuki). 7 | 8 | ## Get started 9 | - Download or clone this repository 10 | - [Download](https://github.com/littlevgl/lv_lib_qrcode.git) from GitHub 11 | - Clone: git clone https://github.com/littlevgl/lv_lib_qrcode.git 12 | - Include the library: `#include "lv_lib_qrcode/lv_qrcode.h"` 13 | - Test with the following code: 14 | ```c 15 | const char * data = "Hello world"; 16 | 17 | /*Create a 100x100 QR code*/ 18 | lv_obj_t * qr = lv_qrcode_create(lv_scr_act(), 100, lv_color_hex3(0x33f), lv_color_hex3(0xeef)); 19 | 20 | /*Set data*/ 21 | lv_qrcode_update(qr, data, strlen(data)); 22 | ``` 23 | 24 | ## Notes 25 | - QR codes with less data are smaller but they scaled by an integer numbers number to best fit to the given size 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 LittlevGL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lv_qrcode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_qrcode 3 | * 4 | */ 5 | 6 | #ifndef LV_QRCODE_H 7 | #define LV_QRCODE_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 17 | #include "lvgl.h" 18 | #else 19 | #include "lvgl/lvgl.h" 20 | #endif 21 | /********************* 22 | * DEFINES 23 | *********************/ 24 | 25 | /********************** 26 | * TYPEDEFS 27 | **********************/ 28 | 29 | /********************** 30 | * GLOBAL PROTOTYPES 31 | **********************/ 32 | 33 | /** 34 | * Create an empty QR code (an `lv_canvas`) object. 35 | * @param parent point to an object where to create the QR code 36 | * @param size width and height of the QR code 37 | * @param dark_color dark color of the QR code 38 | * @param light_color light color of the QR code 39 | * @return pointer to the created QR code object 40 | */ 41 | lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color); 42 | 43 | /** 44 | * Set the data of a QR code object 45 | * @param qrcode pointer to aQ code object 46 | * @param data data to display 47 | * @param data_len length of data in bytes 48 | * @return LV_RES_OK: if no error; LV_RES_INV: on error 49 | */ 50 | lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len); 51 | 52 | /** 53 | * Delete a QR code object 54 | * @param qrcode pointer to a QR code object 55 | */ 56 | void lv_qrcode_delete(lv_obj_t * qrcode); 57 | 58 | /********************** 59 | * MACROS 60 | **********************/ 61 | 62 | 63 | #ifdef __cplusplus 64 | } /* extern "C" */ 65 | #endif 66 | 67 | #endif /*LV_QRCODE_H*/ 68 | -------------------------------------------------------------------------------- /lv_qrcode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_qrcode.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "lv_qrcode.h" 10 | #include "qrcodegen.h" 11 | 12 | /********************* 13 | * DEFINES 14 | *********************/ 15 | #define QR_SIZE 140 16 | 17 | /********************** 18 | * TYPEDEFS 19 | **********************/ 20 | 21 | /********************** 22 | * STATIC PROTOTYPES 23 | **********************/ 24 | 25 | /********************** 26 | * STATIC VARIABLES 27 | **********************/ 28 | 29 | /********************** 30 | * MACROS 31 | **********************/ 32 | 33 | /********************** 34 | * GLOBAL FUNCTIONS 35 | **********************/ 36 | 37 | /** 38 | * Create an empty QR code (an `lv_canvas`) object. 39 | * @param parent point to an object where to create the QR code 40 | * @param size width and height of the QR code 41 | * @param dark_color dark color of the QR code 42 | * @param light_color light color of the QR code 43 | * @return pointer to the created QR code object 44 | */ 45 | lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color) 46 | { 47 | uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size, size); 48 | uint8_t * buf = lv_mem_alloc(buf_size); 49 | LV_ASSERT_MALLOC(buf); 50 | if(buf == NULL) return NULL; 51 | 52 | lv_obj_t * canvas = lv_canvas_create(parent); 53 | if(canvas == NULL) return NULL; 54 | 55 | lv_canvas_set_buffer(canvas, buf, size, size, LV_IMG_CF_INDEXED_1BIT); 56 | lv_canvas_set_palette(canvas, 0, dark_color); 57 | lv_canvas_set_palette(canvas, 1, light_color); 58 | 59 | return canvas; 60 | 61 | } 62 | 63 | /** 64 | * Set the data of a QR code object 65 | * @param qrcode pointer to aQ code object 66 | * @param data data to display 67 | * @param data_len length of data in bytes 68 | * @return LV_RES_OK: if no error; LV_RES_INV: on error 69 | */ 70 | lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len) 71 | { 72 | lv_color_t c; 73 | c.full = 1; 74 | lv_canvas_fill_bg(qrcode, c, LV_OPA_COVER); 75 | 76 | if(data_len > qrcodegen_BUFFER_LEN_MAX) return LV_RES_INV; 77 | 78 | uint8_t qr0[qrcodegen_BUFFER_LEN_MAX]; 79 | uint8_t data_tmp[qrcodegen_BUFFER_LEN_MAX]; 80 | memcpy(data_tmp, data, data_len); 81 | 82 | bool ok = qrcodegen_encodeBinary(data_tmp, data_len, 83 | qr0, qrcodegen_Ecc_MEDIUM, 84 | qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, 85 | qrcodegen_Mask_AUTO, true); 86 | 87 | if (!ok) return LV_RES_INV; 88 | 89 | 90 | lv_img_dsc_t * imgdsc = lv_canvas_get_img(qrcode); 91 | lv_coord_t obj_w = imgdsc->header.w; 92 | int qr_size = qrcodegen_getSize(qr0); 93 | int scale = obj_w / qr_size; 94 | int scaled = qr_size * scale; 95 | int margin = (obj_w - scaled) / 2; 96 | uint8_t * buf_u8 = (uint8_t *)imgdsc->data + 8; /*+8 skip the palette*/ 97 | 98 | /* Copy the qr code canvas: 99 | * A simple `lv_canvas_set_px` would work but it's slow for so many pixels. 100 | * So buffer 1 byte (8 px) from the qr code and set it in the canvas image */ 101 | uint32_t row_byte_cnt = (imgdsc->header.w + 7) >> 3; 102 | int y; 103 | for (y = margin; y < scaled + margin; y+=scale) { 104 | uint8_t b = 0; 105 | uint8_t p = 0; 106 | bool aligned = false; 107 | int x; 108 | for (x = margin; x < scaled + margin; x++) { 109 | bool a = qrcodegen_getModule(qr0, (x - margin) / scale, (y - margin) / scale); 110 | 111 | if(aligned == false && (x & 0x7) == 0) aligned = true; 112 | 113 | if(aligned == false) { 114 | c.full = a ? 0 : 1; 115 | lv_canvas_set_px(qrcode, x, y, c); 116 | } else { 117 | if(!a) b |= (1 << (7 - p)); 118 | p++; 119 | if(p == 8) { 120 | uint32_t px = row_byte_cnt * y + (x >> 3); 121 | buf_u8[px] = b; 122 | b = 0; 123 | p = 0; 124 | } 125 | } 126 | } 127 | 128 | /*Process the last byte of the row*/ 129 | if(p) { 130 | /*Make the rest of the bits white*/ 131 | b |= (1 << (8 - p)) - 1; 132 | 133 | uint32_t px = row_byte_cnt * y + (x >> 3); 134 | buf_u8[px] = b; 135 | } 136 | 137 | /*The Qr is probably scaled so simply to the repeated rows*/ 138 | int s; 139 | const uint8_t * row_ori = buf_u8 + row_byte_cnt * y; 140 | for(s = 1; s < scale; s++) { 141 | memcpy((uint8_t*)buf_u8 + row_byte_cnt * (y + s), row_ori, row_byte_cnt); 142 | } 143 | } 144 | 145 | return LV_RES_OK; 146 | } 147 | 148 | /** 149 | * Delete a QR code object 150 | * @param qrcode pointer to a QR code obejct 151 | */ 152 | void lv_qrcode_delete(lv_obj_t * qrcode) 153 | { 154 | lv_img_dsc_t * img = lv_canvas_get_img(qrcode); 155 | lv_img_cache_invalidate_src(img); 156 | lv_mem_free(img->data); 157 | lv_obj_del(qrcode); 158 | } 159 | 160 | /********************** 161 | * STATIC FUNCTIONS 162 | **********************/ 163 | 164 | -------------------------------------------------------------------------------- /qrcodegen.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C) 3 | * 4 | * Copyright (c) Project Nayuki. (MIT License) 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * - The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * - The Software is provided "as is", without warranty of any kind, express or 16 | * implied, including but not limited to the warranties of merchantability, 17 | * fitness for a particular purpose and noninfringement. In no event shall the 18 | * authors or copyright holders be liable for any claim, damages or other 19 | * liability, whether in an action of contract, tort or otherwise, arising from, 20 | * out of or in connection with the Software or the use or other dealings in the 21 | * Software. 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | 36 | /* 37 | * This library creates QR Code symbols, which is a type of two-dimension barcode. 38 | * Invented by Denso Wave and described in the ISO/IEC 18004 standard. 39 | * A QR Code structure is an immutable square grid of black and white cells. 40 | * The library provides functions to create a QR Code from text or binary data. 41 | * The library covers the QR Code Model 2 specification, supporting all versions (sizes) 42 | * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. 43 | * 44 | * Ways to create a QR Code object: 45 | * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). 46 | * - Low level: Custom-make the list of segments and call 47 | * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). 48 | * (Note that all ways require supplying the desired error correction level and various byte buffers.) 49 | */ 50 | 51 | 52 | /*---- Enum and struct types----*/ 53 | 54 | /* 55 | * The error correction level in a QR Code symbol. 56 | */ 57 | enum qrcodegen_Ecc { 58 | // Must be declared in ascending order of error protection 59 | // so that an internal qrcodegen function works properly 60 | qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords 61 | qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords 62 | qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords 63 | qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords 64 | }; 65 | 66 | 67 | /* 68 | * The mask pattern used in a QR Code symbol. 69 | */ 70 | enum qrcodegen_Mask { 71 | // A special value to tell the QR Code encoder to 72 | // automatically select an appropriate mask pattern 73 | qrcodegen_Mask_AUTO = -1, 74 | // The eight actual mask patterns 75 | qrcodegen_Mask_0 = 0, 76 | qrcodegen_Mask_1, 77 | qrcodegen_Mask_2, 78 | qrcodegen_Mask_3, 79 | qrcodegen_Mask_4, 80 | qrcodegen_Mask_5, 81 | qrcodegen_Mask_6, 82 | qrcodegen_Mask_7, 83 | }; 84 | 85 | 86 | /* 87 | * Describes how a segment's data bits are interpreted. 88 | */ 89 | enum qrcodegen_Mode { 90 | qrcodegen_Mode_NUMERIC = 0x1, 91 | qrcodegen_Mode_ALPHANUMERIC = 0x2, 92 | qrcodegen_Mode_BYTE = 0x4, 93 | qrcodegen_Mode_KANJI = 0x8, 94 | qrcodegen_Mode_ECI = 0x7, 95 | }; 96 | 97 | 98 | /* 99 | * A segment of character/binary/control data in a QR Code symbol. 100 | * The mid-level way to create a segment is to take the payload data 101 | * and call a factory function such as qrcodegen_makeNumeric(). 102 | * The low-level way to create a segment is to custom-make the bit buffer 103 | * and initialize a qrcodegen_Segment struct with appropriate values. 104 | * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. 105 | * Any segment longer than this is meaningless for the purpose of generating QR Codes. 106 | * Moreover, the maximum allowed bit length is 32767 because 107 | * the largest QR Code (version 40) has 31329 modules. 108 | */ 109 | struct qrcodegen_Segment { 110 | // The mode indicator of this segment. 111 | enum qrcodegen_Mode mode; 112 | 113 | // The length of this segment's unencoded data. Measured in characters for 114 | // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. 115 | // Always zero or positive. Not the same as the data's bit length. 116 | int numChars; 117 | 118 | // The data bits of this segment, packed in bitwise big endian. 119 | // Can be null if the bit length is zero. 120 | uint8_t *data; 121 | 122 | // The number of valid data bits used in the buffer. Requires 123 | // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. 124 | // The character count (numChars) must agree with the mode and the bit buffer length. 125 | int bitLength; 126 | }; 127 | 128 | 129 | 130 | /*---- Macro constants and functions ----*/ 131 | 132 | #define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard 133 | #define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard 134 | 135 | // Calculates the number of bytes needed to store any QR Code up to and including the given version number, 136 | // as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' 137 | // can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). 138 | // Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. 139 | #define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) 140 | 141 | // The worst-case number of bytes needed to store one QR Code, up to and including 142 | // version 40. This value equals 3918, which is just under 4 kilobytes. 143 | // Use this more convenient value to avoid calculating tighter memory bounds for buffers. 144 | #define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) 145 | 146 | 147 | 148 | /*---- Functions (high level) to generate QR Codes ----*/ 149 | 150 | /* 151 | * Encodes the given text string to a QR Code, returning true if encoding succeeded. 152 | * If the data is too long to fit in any version in the given range 153 | * at the given ECC level, then false is returned. 154 | * - The input text must be encoded in UTF-8 and contain no NULs. 155 | * - The variables ecl and mask must correspond to enum constant values. 156 | * - Requires 1 <= minVersion <= maxVersion <= 40. 157 | * - The arrays tempBuffer and qrcode must each have a length 158 | * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). 159 | * - After the function returns, tempBuffer contains no useful data. 160 | * - If successful, the resulting QR Code may use numeric, 161 | * alphanumeric, or byte mode to encode the text. 162 | * - In the most optimistic case, a QR Code at version 40 with low ECC 163 | * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string 164 | * up to 4296 characters, or any digit string up to 7089 characters. 165 | * These numbers represent the hard upper limit of the QR Code standard. 166 | * - Please consult the QR Code specification for information on 167 | * data capacities per version, ECC level, and text encoding mode. 168 | */ 169 | bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], 170 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); 171 | 172 | 173 | /* 174 | * Encodes the given binary data to a QR Code, returning true if encoding succeeded. 175 | * If the data is too long to fit in any version in the given range 176 | * at the given ECC level, then false is returned. 177 | * - The input array range dataAndTemp[0 : dataLen] should normally be 178 | * valid UTF-8 text, but is not required by the QR Code standard. 179 | * - The variables ecl and mask must correspond to enum constant values. 180 | * - Requires 1 <= minVersion <= maxVersion <= 40. 181 | * - The arrays dataAndTemp and qrcode must each have a length 182 | * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). 183 | * - After the function returns, the contents of dataAndTemp may have changed, 184 | * and does not represent useful data anymore. 185 | * - If successful, the resulting QR Code will use byte mode to encode the data. 186 | * - In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte 187 | * sequence up to length 2953. This is the hard upper limit of the QR Code standard. 188 | * - Please consult the QR Code specification for information on 189 | * data capacities per version, ECC level, and text encoding mode. 190 | */ 191 | bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], 192 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); 193 | 194 | 195 | /*---- Functions (low level) to generate QR Codes ----*/ 196 | 197 | /* 198 | * Renders a QR Code representing the given segments at the given error correction level. 199 | * The smallest possible QR Code version is automatically chosen for the output. Returns true if 200 | * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level 201 | * of the result may be higher than the ecl argument if it can be done without increasing the version. 202 | * This function allows the user to create a custom sequence of segments that switches 203 | * between modes (such as alphanumeric and byte) to encode text in less space. 204 | * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). 205 | * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will 206 | * result in them being clobbered, but the QR Code output will still be correct. 207 | * But the qrcode array must not overlap tempBuffer or any segment's data buffer. 208 | */ 209 | bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, 210 | enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); 211 | 212 | 213 | /* 214 | * Renders a QR Code representing the given segments with the given encoding parameters. 215 | * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions. 216 | * The smallest possible QR Code version within the given range is automatically 217 | * chosen for the output. Iff boostEcl is true, then the ECC level of the result 218 | * may be higher than the ecl argument if it can be done without increasing the 219 | * version. The mask number is either between 0 to 7 (inclusive) to force that 220 | * mask, or -1 to automatically choose an appropriate mask (which may be slow). 221 | * This function allows the user to create a custom sequence of segments that switches 222 | * between modes (such as alphanumeric and byte) to encode text in less space. 223 | * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). 224 | * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will 225 | * result in them being clobbered, but the QR Code output will still be correct. 226 | * But the qrcode array must not overlap tempBuffer or any segment's data buffer. 227 | */ 228 | bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, 229 | int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); 230 | 231 | 232 | /* 233 | * Tests whether the given string can be encoded as a segment in alphanumeric mode. 234 | * A string is encodable iff each character is in the following set: 0 to 9, A to Z 235 | * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. 236 | */ 237 | bool qrcodegen_isAlphanumeric(const char *text); 238 | 239 | 240 | /* 241 | * Tests whether the given string can be encoded as a segment in numeric mode. 242 | * A string is encodable iff each character is in the range 0 to 9. 243 | */ 244 | bool qrcodegen_isNumeric(const char *text); 245 | 246 | 247 | /* 248 | * Returns the number of bytes (uint8_t) needed for the data buffer of a segment 249 | * containing the given number of characters using the given mode. Notes: 250 | * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or 251 | * the number of needed bits exceeds INT16_MAX (i.e. 32767). 252 | * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. 253 | * - It is okay for the user to allocate more bytes for the buffer than needed. 254 | * - For byte mode, numChars measures the number of bytes, not Unicode code points. 255 | * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. 256 | * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. 257 | */ 258 | size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); 259 | 260 | 261 | /* 262 | * Returns a segment representing the given binary data encoded in 263 | * byte mode. All input byte arrays are acceptable. Any text string 264 | * can be converted to UTF-8 bytes and encoded as a byte mode segment. 265 | */ 266 | struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); 267 | 268 | 269 | /* 270 | * Returns a segment representing the given string of decimal digits encoded in numeric mode. 271 | */ 272 | struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); 273 | 274 | 275 | /* 276 | * Returns a segment representing the given text string encoded in alphanumeric mode. 277 | * The characters allowed are: 0 to 9, A to Z (uppercase only), space, 278 | * dollar, percent, asterisk, plus, hyphen, period, slash, colon. 279 | */ 280 | struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); 281 | 282 | 283 | /* 284 | * Returns a segment representing an Extended Channel Interpretation 285 | * (ECI) designator with the given assignment value. 286 | */ 287 | struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); 288 | 289 | 290 | /*---- Functions to extract raw data from QR Codes ----*/ 291 | 292 | /* 293 | * Returns the side length of the given QR Code, assuming that encoding succeeded. 294 | * The result is in the range [21, 177]. Note that the length of the array buffer 295 | * is related to the side length - every 'uint8_t qrcode[]' must have length at least 296 | * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1). 297 | */ 298 | int qrcodegen_getSize(const uint8_t qrcode[]); 299 | 300 | 301 | /* 302 | * Returns the color of the module (pixel) at the given coordinates, which is false 303 | * for white or true for black. The top left corner has the coordinates (x=0, y=0). 304 | * If the given coordinates are out of bounds, then false (white) is returned. 305 | */ 306 | bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); 307 | 308 | 309 | #ifdef __cplusplus 310 | } 311 | #endif 312 | -------------------------------------------------------------------------------- /qrcodegen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C) 3 | * 4 | * Copyright (c) Project Nayuki. (MIT License) 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * - The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * - The Software is provided "as is", without warranty of any kind, express or 16 | * implied, including but not limited to the warranties of merchantability, 17 | * fitness for a particular purpose and noninfringement. In no event shall the 18 | * authors or copyright holders be liable for any claim, damages or other 19 | * liability, whether in an action of contract, tort or otherwise, arising from, 20 | * out of or in connection with the Software or the use or other dealings in the 21 | * Software. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "qrcodegen.h" 29 | 30 | #ifndef QRCODEGEN_TEST 31 | #define testable static // Keep functions private 32 | #else 33 | #define testable // Expose private functions 34 | #endif 35 | 36 | 37 | /*---- Forward declarations for private functions ----*/ 38 | 39 | // Regarding all public and private functions defined in this source file: 40 | // - They require all pointer/array arguments to be not null unless the array length is zero. 41 | // - They only read input scalar/array arguments, write to output pointer/array 42 | // arguments, and return scalar values; they are "pure" functions. 43 | // - They don't read mutable global variables or write to any global variables. 44 | // - They don't perform I/O, read the clock, print to console, etc. 45 | // - They allocate a small and constant amount of stack memory. 46 | // - They don't allocate or free any memory on the heap. 47 | // - They don't recurse or mutually recurse. All the code 48 | // could be inlined into the top-level public functions. 49 | // - They run in at most quadratic time with respect to input arguments. 50 | // Most functions run in linear time, and some in constant time. 51 | // There are no unbounded loops or non-obvious termination conditions. 52 | // - They are completely thread-safe if the caller does not give the 53 | // same writable buffer to concurrent calls to these functions. 54 | 55 | testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); 56 | 57 | testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); 58 | testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); 59 | testable int getNumRawDataModules(int ver); 60 | 61 | testable void calcReedSolomonGenerator(int degree, uint8_t result[]); 62 | testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, 63 | const uint8_t generator[], int degree, uint8_t result[]); 64 | testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y); 65 | 66 | testable void initializeFunctionModules(int version, uint8_t qrcode[]); 67 | static void drawWhiteFunctionModules(uint8_t qrcode[], int version); 68 | static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); 69 | testable int getAlignmentPatternPositions(int version, uint8_t result[7]); 70 | static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); 71 | 72 | static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); 73 | static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); 74 | static long getPenaltyScore(const uint8_t qrcode[]); 75 | static void addRunToHistory(unsigned char run, unsigned char history[7]); 76 | static bool hasFinderLikePattern(const unsigned char runHistory[7]); 77 | 78 | testable bool getModule(const uint8_t qrcode[], int x, int y); 79 | testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack); 80 | testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack); 81 | static bool getBit(int x, int i); 82 | 83 | testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); 84 | testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); 85 | static int numCharCountBits(enum qrcodegen_Mode mode, int version); 86 | 87 | 88 | 89 | /*---- Private tables of constants ----*/ 90 | 91 | // The set of all legal characters in alphanumeric mode, where each character 92 | // value maps to the index in the string. For checking text and encoding segments. 93 | static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; 94 | 95 | // For generating error correction codes. 96 | testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { 97 | // Version: (note that index 0 is for padding, and is set to an illegal value) 98 | //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level 99 | {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low 100 | {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium 101 | {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile 102 | {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High 103 | }; 104 | 105 | #define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above 106 | 107 | // For generating error correction codes. 108 | testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { 109 | // Version: (note that index 0 is for padding, and is set to an illegal value) 110 | //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level 111 | {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low 112 | {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium 113 | {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile 114 | {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High 115 | }; 116 | 117 | // For automatic mask pattern selection. 118 | static const int PENALTY_N1 = 3; 119 | static const int PENALTY_N2 = 3; 120 | static const int PENALTY_N3 = 40; 121 | static const int PENALTY_N4 = 10; 122 | 123 | 124 | 125 | /*---- High-level QR Code encoding functions ----*/ 126 | 127 | // Public function - see documentation comment in header file. 128 | bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], 129 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { 130 | 131 | size_t textLen = strlen(text); 132 | if (textLen == 0) 133 | return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); 134 | size_t bufLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); 135 | 136 | struct qrcodegen_Segment seg; 137 | if (qrcodegen_isNumeric(text)) { 138 | if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) 139 | goto fail; 140 | seg = qrcodegen_makeNumeric(text, tempBuffer); 141 | } else if (qrcodegen_isAlphanumeric(text)) { 142 | if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) 143 | goto fail; 144 | seg = qrcodegen_makeAlphanumeric(text, tempBuffer); 145 | } else { 146 | if (textLen > bufLen) 147 | goto fail; 148 | for (size_t i = 0; i < textLen; i++) 149 | tempBuffer[i] = (uint8_t)text[i]; 150 | seg.mode = qrcodegen_Mode_BYTE; 151 | seg.bitLength = calcSegmentBitLength(seg.mode, textLen); 152 | if (seg.bitLength == -1) 153 | goto fail; 154 | seg.numChars = (int)textLen; 155 | seg.data = tempBuffer; 156 | } 157 | return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); 158 | 159 | fail: 160 | qrcode[0] = 0; // Set size to invalid value for safety 161 | return false; 162 | } 163 | 164 | 165 | // Public function - see documentation comment in header file. 166 | bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], 167 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { 168 | 169 | struct qrcodegen_Segment seg; 170 | seg.mode = qrcodegen_Mode_BYTE; 171 | seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); 172 | if (seg.bitLength == -1) { 173 | qrcode[0] = 0; // Set size to invalid value for safety 174 | return false; 175 | } 176 | seg.numChars = (int)dataLen; 177 | seg.data = dataAndTemp; 178 | return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); 179 | } 180 | 181 | 182 | // Appends the given number of low-order bits of the given value to the given byte-based 183 | // bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. 184 | testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) { 185 | assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); 186 | for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) 187 | buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); 188 | } 189 | 190 | 191 | 192 | /*---- Low-level QR Code encoding functions ----*/ 193 | 194 | // Public function - see documentation comment in header file. 195 | bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, 196 | enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) { 197 | return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, 198 | qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, -1, true, tempBuffer, qrcode); 199 | } 200 | 201 | 202 | // Public function - see documentation comment in header file. 203 | bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, 204 | int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) { 205 | assert(segs != NULL || len == 0); 206 | assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); 207 | assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); 208 | 209 | // Find the minimal version number to use 210 | int version, dataUsedBits; 211 | for (version = minVersion; ; version++) { 212 | int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available 213 | dataUsedBits = getTotalBits(segs, len, version); 214 | if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) 215 | break; // This version number is found to be suitable 216 | if (version >= maxVersion) { // All versions in the range could not fit the given data 217 | qrcode[0] = 0; // Set size to invalid value for safety 218 | return false; 219 | } 220 | } 221 | assert(dataUsedBits != -1); 222 | 223 | // Increase the error correction level while the data still fits in the current version number 224 | for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high 225 | if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) 226 | ecl = (enum qrcodegen_Ecc)i; 227 | } 228 | 229 | // Concatenate all segments to create the data bit string 230 | memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); 231 | int bitLen = 0; 232 | for (size_t i = 0; i < len; i++) { 233 | const struct qrcodegen_Segment *seg = &segs[i]; 234 | appendBitsToBuffer((int)seg->mode, 4, qrcode, &bitLen); 235 | appendBitsToBuffer(seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); 236 | for (int j = 0; j < seg->bitLength; j++) 237 | appendBitsToBuffer((seg->data[j >> 3] >> (7 - (j & 7))) & 1, 1, qrcode, &bitLen); 238 | } 239 | assert(bitLen == dataUsedBits); 240 | 241 | // Add terminator and pad up to a byte if applicable 242 | int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; 243 | assert(bitLen <= dataCapacityBits); 244 | int terminatorBits = dataCapacityBits - bitLen; 245 | if (terminatorBits > 4) 246 | terminatorBits = 4; 247 | appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); 248 | appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); 249 | assert(bitLen % 8 == 0); 250 | 251 | // Pad with alternating bytes until data capacity is reached 252 | for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) 253 | appendBitsToBuffer(padByte, 8, qrcode, &bitLen); 254 | 255 | // Draw function and data codeword modules 256 | addEccAndInterleave(qrcode, version, ecl, tempBuffer); 257 | initializeFunctionModules(version, qrcode); 258 | drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); 259 | drawWhiteFunctionModules(qrcode, version); 260 | initializeFunctionModules(version, tempBuffer); 261 | 262 | // Handle masking 263 | if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask 264 | long minPenalty = LONG_MAX; 265 | for (int i = 0; i < 8; i++) { 266 | enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; 267 | applyMask(tempBuffer, qrcode, msk); 268 | drawFormatBits(ecl, msk, qrcode); 269 | long penalty = getPenaltyScore(qrcode); 270 | if (penalty < minPenalty) { 271 | mask = msk; 272 | minPenalty = penalty; 273 | } 274 | applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR 275 | } 276 | } 277 | assert(0 <= (int)mask && (int)mask <= 7); 278 | applyMask(tempBuffer, qrcode, mask); 279 | drawFormatBits(ecl, mask, qrcode); 280 | return true; 281 | } 282 | 283 | 284 | 285 | /*---- Error correction code generation functions ----*/ 286 | 287 | // Appends error correction bytes to each block of the given data array, then interleaves 288 | // bytes from the blocks and stores them in the result array. data[0 : dataLen] contains 289 | // the input data. data[dataLen : rawCodewords] is used as a temporary work area and will 290 | // be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. 291 | testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { 292 | // Calculate parameter numbers 293 | assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); 294 | int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; 295 | int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; 296 | int rawCodewords = getNumRawDataModules(version) / 8; 297 | int dataLen = getNumDataCodewords(version, ecl); 298 | int numShortBlocks = numBlocks - rawCodewords % numBlocks; 299 | int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; 300 | 301 | // Split data into blocks, calculate ECC, and interleave 302 | // (not concatenate) the bytes into a single sequence 303 | uint8_t generator[qrcodegen_REED_SOLOMON_DEGREE_MAX]; 304 | calcReedSolomonGenerator(blockEccLen, generator); 305 | const uint8_t *dat = data; 306 | for (int i = 0; i < numBlocks; i++) { 307 | int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); 308 | uint8_t *ecc = &data[dataLen]; // Temporary storage 309 | calcReedSolomonRemainder(dat, datLen, generator, blockEccLen, ecc); 310 | for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data 311 | if (j == shortBlockDataLen) 312 | k -= numShortBlocks; 313 | result[k] = dat[j]; 314 | } 315 | for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC 316 | result[k] = ecc[j]; 317 | dat += datLen; 318 | } 319 | } 320 | 321 | 322 | // Returns the number of 8-bit codewords that can be used for storing data (not ECC), 323 | // for the given version number and error correction level. The result is in the range [9, 2956]. 324 | testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) { 325 | int v = version, e = (int)ecl; 326 | assert(0 <= e && e < 4); 327 | return getNumRawDataModules(v) / 8 328 | - ECC_CODEWORDS_PER_BLOCK [e][v] 329 | * NUM_ERROR_CORRECTION_BLOCKS[e][v]; 330 | } 331 | 332 | 333 | // Returns the number of data bits that can be stored in a QR Code of the given version number, after 334 | // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. 335 | // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. 336 | testable int getNumRawDataModules(int ver) { 337 | assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); 338 | int result = (16 * ver + 128) * ver + 64; 339 | if (ver >= 2) { 340 | int numAlign = ver / 7 + 2; 341 | result -= (25 * numAlign - 10) * numAlign - 55; 342 | if (ver >= 7) 343 | result -= 36; 344 | } 345 | return result; 346 | } 347 | 348 | 349 | 350 | /*---- Reed-Solomon ECC generator functions ----*/ 351 | 352 | // Calculates the Reed-Solomon generator polynomial of the given degree, storing in result[0 : degree]. 353 | testable void calcReedSolomonGenerator(int degree, uint8_t result[]) { 354 | // Start with the monomial x^0 355 | assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); 356 | memset(result, 0, degree * sizeof(result[0])); 357 | result[degree - 1] = 1; 358 | 359 | // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), 360 | // drop the highest term, and store the rest of the coefficients in order of descending powers. 361 | // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). 362 | uint8_t root = 1; 363 | for (int i = 0; i < degree; i++) { 364 | // Multiply the current product by (x - r^i) 365 | for (int j = 0; j < degree; j++) { 366 | result[j] = finiteFieldMultiply(result[j], root); 367 | if (j + 1 < degree) 368 | result[j] ^= result[j + 1]; 369 | } 370 | root = finiteFieldMultiply(root, 0x02); 371 | } 372 | } 373 | 374 | 375 | // Calculates the remainder of the polynomial data[0 : dataLen] when divided by the generator[0 : degree], where all 376 | // polynomials are in big endian and the generator has an implicit leading 1 term, storing the result in result[0 : degree]. 377 | testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, 378 | const uint8_t generator[], int degree, uint8_t result[]) { 379 | 380 | // Perform polynomial division 381 | assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); 382 | memset(result, 0, degree * sizeof(result[0])); 383 | for (int i = 0; i < dataLen; i++) { 384 | uint8_t factor = data[i] ^ result[0]; 385 | memmove(&result[0], &result[1], (degree - 1) * sizeof(result[0])); 386 | result[degree - 1] = 0; 387 | for (int j = 0; j < degree; j++) 388 | result[j] ^= finiteFieldMultiply(generator[j], factor); 389 | } 390 | } 391 | 392 | #undef qrcodegen_REED_SOLOMON_DEGREE_MAX 393 | 394 | 395 | // Returns the product of the two given field elements modulo GF(2^8/0x11D). 396 | // All inputs are valid. This could be implemented as a 256*256 lookup table. 397 | testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y) { 398 | // Russian peasant multiplication 399 | uint8_t z = 0; 400 | for (int i = 7; i >= 0; i--) { 401 | z = (z << 1) ^ ((z >> 7) * 0x11D); 402 | z ^= ((y >> i) & 1) * x; 403 | } 404 | return z; 405 | } 406 | 407 | 408 | 409 | /*---- Drawing function modules ----*/ 410 | 411 | // Clears the given QR Code grid with white modules for the given 412 | // version's size, then marks every function module as black. 413 | testable void initializeFunctionModules(int version, uint8_t qrcode[]) { 414 | // Initialize QR Code 415 | int qrsize = version * 4 + 17; 416 | memset(qrcode, 0, ((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); 417 | qrcode[0] = (uint8_t)qrsize; 418 | 419 | // Fill horizontal and vertical timing patterns 420 | fillRectangle(6, 0, 1, qrsize, qrcode); 421 | fillRectangle(0, 6, qrsize, 1, qrcode); 422 | 423 | // Fill 3 finder patterns (all corners except bottom right) and format bits 424 | fillRectangle(0, 0, 9, 9, qrcode); 425 | fillRectangle(qrsize - 8, 0, 8, 9, qrcode); 426 | fillRectangle(0, qrsize - 8, 9, 8, qrcode); 427 | 428 | // Fill numerous alignment patterns 429 | uint8_t alignPatPos[7]; 430 | int numAlign = getAlignmentPatternPositions(version, alignPatPos); 431 | for (int i = 0; i < numAlign; i++) { 432 | for (int j = 0; j < numAlign; j++) { 433 | // Don't draw on the three finder corners 434 | if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) 435 | fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); 436 | } 437 | } 438 | 439 | // Fill version blocks 440 | if (version >= 7) { 441 | fillRectangle(qrsize - 11, 0, 3, 6, qrcode); 442 | fillRectangle(0, qrsize - 11, 6, 3, qrcode); 443 | } 444 | } 445 | 446 | 447 | // Draws white function modules and possibly some black modules onto the given QR Code, without changing 448 | // non-function modules. This does not draw the format bits. This requires all function modules to be previously 449 | // marked black (namely by initializeFunctionModules()), because this may skip redrawing black function modules. 450 | static void drawWhiteFunctionModules(uint8_t qrcode[], int version) { 451 | // Draw horizontal and vertical timing patterns 452 | int qrsize = qrcodegen_getSize(qrcode); 453 | for (int i = 7; i < qrsize - 7; i += 2) { 454 | setModule(qrcode, 6, i, false); 455 | setModule(qrcode, i, 6, false); 456 | } 457 | 458 | // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) 459 | for (int dy = -4; dy <= 4; dy++) { 460 | for (int dx = -4; dx <= 4; dx++) { 461 | int dist = abs(dx); 462 | if (abs(dy) > dist) 463 | dist = abs(dy); 464 | if (dist == 2 || dist == 4) { 465 | setModuleBounded(qrcode, 3 + dx, 3 + dy, false); 466 | setModuleBounded(qrcode, qrsize - 4 + dx, 3 + dy, false); 467 | setModuleBounded(qrcode, 3 + dx, qrsize - 4 + dy, false); 468 | } 469 | } 470 | } 471 | 472 | // Draw numerous alignment patterns 473 | uint8_t alignPatPos[7]; 474 | int numAlign = getAlignmentPatternPositions(version, alignPatPos); 475 | for (int i = 0; i < numAlign; i++) { 476 | for (int j = 0; j < numAlign; j++) { 477 | if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) 478 | continue; // Don't draw on the three finder corners 479 | for (int dy = -1; dy <= 1; dy++) { 480 | for (int dx = -1; dx <= 1; dx++) 481 | setModule(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); 482 | } 483 | } 484 | } 485 | 486 | // Draw version blocks 487 | if (version >= 7) { 488 | // Calculate error correction code and pack bits 489 | int rem = version; // version is uint6, in the range [7, 40] 490 | for (int i = 0; i < 12; i++) 491 | rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); 492 | long bits = (long)version << 12 | rem; // uint18 493 | assert(bits >> 18 == 0); 494 | 495 | // Draw two copies 496 | for (int i = 0; i < 6; i++) { 497 | for (int j = 0; j < 3; j++) { 498 | int k = qrsize - 11 + j; 499 | setModule(qrcode, k, i, (bits & 1) != 0); 500 | setModule(qrcode, i, k, (bits & 1) != 0); 501 | bits >>= 1; 502 | } 503 | } 504 | } 505 | } 506 | 507 | 508 | // Draws two copies of the format bits (with its own error correction code) based 509 | // on the given mask and error correction level. This always draws all modules of 510 | // the format bits, unlike drawWhiteFunctionModules() which might skip black modules. 511 | static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) { 512 | // Calculate error correction code and pack bits 513 | assert(0 <= (int)mask && (int)mask <= 7); 514 | static const int table[] = {1, 0, 3, 2}; 515 | int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 516 | int rem = data; 517 | for (int i = 0; i < 10; i++) 518 | rem = (rem << 1) ^ ((rem >> 9) * 0x537); 519 | int bits = (data << 10 | rem) ^ 0x5412; // uint15 520 | assert(bits >> 15 == 0); 521 | 522 | // Draw first copy 523 | for (int i = 0; i <= 5; i++) 524 | setModule(qrcode, 8, i, getBit(bits, i)); 525 | setModule(qrcode, 8, 7, getBit(bits, 6)); 526 | setModule(qrcode, 8, 8, getBit(bits, 7)); 527 | setModule(qrcode, 7, 8, getBit(bits, 8)); 528 | for (int i = 9; i < 15; i++) 529 | setModule(qrcode, 14 - i, 8, getBit(bits, i)); 530 | 531 | // Draw second copy 532 | int qrsize = qrcodegen_getSize(qrcode); 533 | for (int i = 0; i < 8; i++) 534 | setModule(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); 535 | for (int i = 8; i < 15; i++) 536 | setModule(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); 537 | setModule(qrcode, 8, qrsize - 8, true); // Always black 538 | } 539 | 540 | 541 | // Calculates and stores an ascending list of positions of alignment patterns 542 | // for this version number, returning the length of the list (in the range [0,7]). 543 | // Each position is in the range [0,177), and are used on both the x and y axes. 544 | // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. 545 | testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { 546 | if (version == 1) 547 | return 0; 548 | int numAlign = version / 7 + 2; 549 | int step = (version == 32) ? 26 : 550 | (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; 551 | for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) 552 | result[i] = pos; 553 | result[0] = 6; 554 | return numAlign; 555 | } 556 | 557 | 558 | // Sets every pixel in the range [left : left + width] * [top : top + height] to black. 559 | static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) { 560 | for (int dy = 0; dy < height; dy++) { 561 | for (int dx = 0; dx < width; dx++) 562 | setModule(qrcode, left + dx, top + dy, true); 563 | } 564 | } 565 | 566 | 567 | 568 | /*---- Drawing data modules and masking ----*/ 569 | 570 | // Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of 571 | // the QR Code to be black at function modules and white at codeword modules (including unused remainder bits). 572 | static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) { 573 | int qrsize = qrcodegen_getSize(qrcode); 574 | int i = 0; // Bit index into the data 575 | // Do the funny zigzag scan 576 | for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair 577 | if (right == 6) 578 | right = 5; 579 | for (int vert = 0; vert < qrsize; vert++) { // Vertical counter 580 | for (int j = 0; j < 2; j++) { 581 | int x = right - j; // Actual x coordinate 582 | bool upward = ((right + 1) & 2) == 0; 583 | int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate 584 | if (!getModule(qrcode, x, y) && i < dataLen * 8) { 585 | bool black = getBit(data[i >> 3], 7 - (i & 7)); 586 | setModule(qrcode, x, y, black); 587 | i++; 588 | } 589 | // If this QR Code has any remainder bits (0 to 7), they were assigned as 590 | // 0/false/white by the constructor and are left unchanged by this method 591 | } 592 | } 593 | } 594 | assert(i == dataLen * 8); 595 | } 596 | 597 | 598 | // XORs the codeword modules in this QR Code with the given mask pattern. 599 | // The function modules must be marked and the codeword bits must be drawn 600 | // before masking. Due to the arithmetic of XOR, calling applyMask() with 601 | // the same mask value a second time will undo the mask. A final well-formed 602 | // QR Code needs exactly one (not zero, two, etc.) mask applied. 603 | static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) { 604 | assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO 605 | int qrsize = qrcodegen_getSize(qrcode); 606 | for (int y = 0; y < qrsize; y++) { 607 | for (int x = 0; x < qrsize; x++) { 608 | if (getModule(functionModules, x, y)) 609 | continue; 610 | bool invert; 611 | switch ((int)mask) { 612 | case 0: invert = (x + y) % 2 == 0; break; 613 | case 1: invert = y % 2 == 0; break; 614 | case 2: invert = x % 3 == 0; break; 615 | case 3: invert = (x + y) % 3 == 0; break; 616 | case 4: invert = (x / 3 + y / 2) % 2 == 0; break; 617 | case 5: invert = x * y % 2 + x * y % 3 == 0; break; 618 | case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; 619 | case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; 620 | default: assert(false); return; 621 | } 622 | bool val = getModule(qrcode, x, y); 623 | setModule(qrcode, x, y, val ^ invert); 624 | } 625 | } 626 | } 627 | 628 | 629 | // Calculates and returns the penalty score based on state of the given QR Code's current modules. 630 | // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. 631 | static long getPenaltyScore(const uint8_t qrcode[]) { 632 | int qrsize = qrcodegen_getSize(qrcode); 633 | long result = 0; 634 | 635 | // Adjacent modules in row having same color, and finder-like patterns 636 | for (int y = 0; y < qrsize; y++) { 637 | unsigned char runHistory[7] = {0}; 638 | bool color = false; 639 | unsigned char runX = 0; 640 | for (int x = 0; x < qrsize; x++) { 641 | if (getModule(qrcode, x, y) == color) { 642 | runX++; 643 | if (runX == 5) 644 | result += PENALTY_N1; 645 | else if (runX > 5) 646 | result++; 647 | } else { 648 | addRunToHistory(runX, runHistory); 649 | if (!color && hasFinderLikePattern(runHistory)) 650 | result += PENALTY_N3; 651 | color = getModule(qrcode, x, y); 652 | runX = 1; 653 | } 654 | } 655 | addRunToHistory(runX, runHistory); 656 | if (color) 657 | addRunToHistory(0, runHistory); // Dummy run of white 658 | if (hasFinderLikePattern(runHistory)) 659 | result += PENALTY_N3; 660 | } 661 | // Adjacent modules in column having same color, and finder-like patterns 662 | for (int x = 0; x < qrsize; x++) { 663 | unsigned char runHistory[7] = {0}; 664 | bool color = false; 665 | unsigned char runY = 0; 666 | for (int y = 0; y < qrsize; y++) { 667 | if (getModule(qrcode, x, y) == color) { 668 | runY++; 669 | if (runY == 5) 670 | result += PENALTY_N1; 671 | else if (runY > 5) 672 | result++; 673 | } else { 674 | addRunToHistory(runY, runHistory); 675 | if (!color && hasFinderLikePattern(runHistory)) 676 | result += PENALTY_N3; 677 | color = getModule(qrcode, x, y); 678 | runY = 1; 679 | } 680 | } 681 | addRunToHistory(runY, runHistory); 682 | if (color) 683 | addRunToHistory(0, runHistory); // Dummy run of white 684 | if (hasFinderLikePattern(runHistory)) 685 | result += PENALTY_N3; 686 | } 687 | 688 | // 2*2 blocks of modules having same color 689 | for (int y = 0; y < qrsize - 1; y++) { 690 | for (int x = 0; x < qrsize - 1; x++) { 691 | bool color = getModule(qrcode, x, y); 692 | if ( color == getModule(qrcode, x + 1, y) && 693 | color == getModule(qrcode, x, y + 1) && 694 | color == getModule(qrcode, x + 1, y + 1)) 695 | result += PENALTY_N2; 696 | } 697 | } 698 | 699 | // Balance of black and white modules 700 | int black = 0; 701 | for (int y = 0; y < qrsize; y++) { 702 | for (int x = 0; x < qrsize; x++) { 703 | if (getModule(qrcode, x, y)) 704 | black++; 705 | } 706 | } 707 | int total = qrsize * qrsize; // Note that size is odd, so black/total != 1/2 708 | // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% 709 | int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1; 710 | result += k * PENALTY_N4; 711 | return result; 712 | } 713 | 714 | 715 | // Inserts the given value to the front of the given array, which shifts over the 716 | // existing values and deletes the last value. A helper function for getPenaltyScore(). 717 | static void addRunToHistory(unsigned char run, unsigned char history[7]) { 718 | memmove(&history[1], &history[0], 6 * sizeof(history[0])); 719 | history[0] = run; 720 | } 721 | 722 | 723 | // Tests whether the given run history has the pattern of ratio 1:1:3:1:1 in the middle, and 724 | // surrounded by at least 4 on either or both ends. A helper function for getPenaltyScore(). 725 | // Must only be called immediately after a run of white modules has ended. 726 | static bool hasFinderLikePattern(const unsigned char runHistory[7]) { 727 | unsigned char n = runHistory[1]; 728 | // The maximum QR Code size is 177, hence the run length n <= 177. 729 | // Arithmetic is promoted to int, so n*4 will not overflow. 730 | return n > 0 && runHistory[2] == n && runHistory[4] == n && runHistory[5] == n 731 | && runHistory[3] == n * 3 && (runHistory[0] >= n * 4 || runHistory[6] >= n * 4); 732 | } 733 | 734 | 735 | 736 | /*---- Basic QR Code information ----*/ 737 | 738 | // Public function - see documentation comment in header file. 739 | int qrcodegen_getSize(const uint8_t qrcode[]) { 740 | assert(qrcode != NULL); 741 | int result = qrcode[0]; 742 | assert((qrcodegen_VERSION_MIN * 4 + 17) <= result 743 | && result <= (qrcodegen_VERSION_MAX * 4 + 17)); 744 | return result; 745 | } 746 | 747 | 748 | // Public function - see documentation comment in header file. 749 | bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) { 750 | assert(qrcode != NULL); 751 | int qrsize = qrcode[0]; 752 | return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModule(qrcode, x, y); 753 | } 754 | 755 | 756 | // Gets the module at the given coordinates, which must be in bounds. 757 | testable bool getModule(const uint8_t qrcode[], int x, int y) { 758 | int qrsize = qrcode[0]; 759 | assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); 760 | int index = y * qrsize + x; 761 | return getBit(qrcode[(index >> 3) + 1], index & 7); 762 | } 763 | 764 | 765 | // Sets the module at the given coordinates, which must be in bounds. 766 | testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack) { 767 | int qrsize = qrcode[0]; 768 | assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); 769 | int index = y * qrsize + x; 770 | int bitIndex = index & 7; 771 | int byteIndex = (index >> 3) + 1; 772 | if (isBlack) 773 | qrcode[byteIndex] |= 1 << bitIndex; 774 | else 775 | qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; 776 | } 777 | 778 | 779 | // Sets the module at the given coordinates, doing nothing if out of bounds. 780 | testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack) { 781 | int qrsize = qrcode[0]; 782 | if (0 <= x && x < qrsize && 0 <= y && y < qrsize) 783 | setModule(qrcode, x, y, isBlack); 784 | } 785 | 786 | 787 | // Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. 788 | static bool getBit(int x, int i) { 789 | return ((x >> i) & 1) != 0; 790 | } 791 | 792 | 793 | 794 | /*---- Segment handling ----*/ 795 | 796 | // Public function - see documentation comment in header file. 797 | bool qrcodegen_isAlphanumeric(const char *text) { 798 | assert(text != NULL); 799 | for (; *text != '\0'; text++) { 800 | if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) 801 | return false; 802 | } 803 | return true; 804 | } 805 | 806 | 807 | // Public function - see documentation comment in header file. 808 | bool qrcodegen_isNumeric(const char *text) { 809 | assert(text != NULL); 810 | for (; *text != '\0'; text++) { 811 | if (*text < '0' || *text > '9') 812 | return false; 813 | } 814 | return true; 815 | } 816 | 817 | 818 | // Public function - see documentation comment in header file. 819 | size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) { 820 | int temp = calcSegmentBitLength(mode, numChars); 821 | if (temp == -1) 822 | return SIZE_MAX; 823 | assert(0 <= temp && temp <= INT16_MAX); 824 | return ((size_t)temp + 7) / 8; 825 | } 826 | 827 | 828 | // Returns the number of data bits needed to represent a segment 829 | // containing the given number of characters using the given mode. Notes: 830 | // - Returns -1 on failure, i.e. numChars > INT16_MAX or 831 | // the number of needed bits exceeds INT16_MAX (i.e. 32767). 832 | // - Otherwise, all valid results are in the range [0, INT16_MAX]. 833 | // - For byte mode, numChars measures the number of bytes, not Unicode code points. 834 | // - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. 835 | // An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. 836 | testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { 837 | // All calculations are designed to avoid overflow on all platforms 838 | if (numChars > (unsigned int)INT16_MAX) 839 | return -1; 840 | long result = (long)numChars; 841 | if (mode == qrcodegen_Mode_NUMERIC) 842 | result = (result * 10 + 2) / 3; // ceil(10/3 * n) 843 | else if (mode == qrcodegen_Mode_ALPHANUMERIC) 844 | result = (result * 11 + 1) / 2; // ceil(11/2 * n) 845 | else if (mode == qrcodegen_Mode_BYTE) 846 | result *= 8; 847 | else if (mode == qrcodegen_Mode_KANJI) 848 | result *= 13; 849 | else if (mode == qrcodegen_Mode_ECI && numChars == 0) 850 | result = 3 * 8; 851 | else { // Invalid argument 852 | assert(false); 853 | return -1; 854 | } 855 | assert(result >= 0); 856 | if (result > (unsigned int)INT16_MAX) 857 | return -1; 858 | return (int)result; 859 | } 860 | 861 | 862 | // Public function - see documentation comment in header file. 863 | struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { 864 | assert(data != NULL || len == 0); 865 | struct qrcodegen_Segment result; 866 | result.mode = qrcodegen_Mode_BYTE; 867 | result.bitLength = calcSegmentBitLength(result.mode, len); 868 | assert(result.bitLength != -1); 869 | result.numChars = (int)len; 870 | if (len > 0) 871 | memcpy(buf, data, len * sizeof(buf[0])); 872 | result.data = buf; 873 | return result; 874 | } 875 | 876 | 877 | // Public function - see documentation comment in header file. 878 | struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) { 879 | assert(digits != NULL); 880 | struct qrcodegen_Segment result; 881 | size_t len = strlen(digits); 882 | result.mode = qrcodegen_Mode_NUMERIC; 883 | int bitLen = calcSegmentBitLength(result.mode, len); 884 | assert(bitLen != -1); 885 | result.numChars = (int)len; 886 | if (bitLen > 0) 887 | memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); 888 | result.bitLength = 0; 889 | 890 | unsigned int accumData = 0; 891 | int accumCount = 0; 892 | for (; *digits != '\0'; digits++) { 893 | char c = *digits; 894 | assert('0' <= c && c <= '9'); 895 | accumData = accumData * 10 + (unsigned int)(c - '0'); 896 | accumCount++; 897 | if (accumCount == 3) { 898 | appendBitsToBuffer(accumData, 10, buf, &result.bitLength); 899 | accumData = 0; 900 | accumCount = 0; 901 | } 902 | } 903 | if (accumCount > 0) // 1 or 2 digits remaining 904 | appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); 905 | assert(result.bitLength == bitLen); 906 | result.data = buf; 907 | return result; 908 | } 909 | 910 | 911 | // Public function - see documentation comment in header file. 912 | struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) { 913 | assert(text != NULL); 914 | struct qrcodegen_Segment result; 915 | size_t len = strlen(text); 916 | result.mode = qrcodegen_Mode_ALPHANUMERIC; 917 | int bitLen = calcSegmentBitLength(result.mode, len); 918 | assert(bitLen != -1); 919 | result.numChars = (int)len; 920 | if (bitLen > 0) 921 | memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); 922 | result.bitLength = 0; 923 | 924 | unsigned int accumData = 0; 925 | int accumCount = 0; 926 | for (; *text != '\0'; text++) { 927 | const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); 928 | assert(temp != NULL); 929 | accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); 930 | accumCount++; 931 | if (accumCount == 2) { 932 | appendBitsToBuffer(accumData, 11, buf, &result.bitLength); 933 | accumData = 0; 934 | accumCount = 0; 935 | } 936 | } 937 | if (accumCount > 0) // 1 character remaining 938 | appendBitsToBuffer(accumData, 6, buf, &result.bitLength); 939 | assert(result.bitLength == bitLen); 940 | result.data = buf; 941 | return result; 942 | } 943 | 944 | 945 | // Public function - see documentation comment in header file. 946 | struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { 947 | struct qrcodegen_Segment result; 948 | result.mode = qrcodegen_Mode_ECI; 949 | result.numChars = 0; 950 | result.bitLength = 0; 951 | if (assignVal < 0) 952 | assert(false); 953 | else if (assignVal < (1 << 7)) { 954 | memset(buf, 0, 1 * sizeof(buf[0])); 955 | appendBitsToBuffer(assignVal, 8, buf, &result.bitLength); 956 | } else if (assignVal < (1 << 14)) { 957 | memset(buf, 0, 2 * sizeof(buf[0])); 958 | appendBitsToBuffer(2, 2, buf, &result.bitLength); 959 | appendBitsToBuffer(assignVal, 14, buf, &result.bitLength); 960 | } else if (assignVal < 1000000L) { 961 | memset(buf, 0, 3 * sizeof(buf[0])); 962 | appendBitsToBuffer(6, 3, buf, &result.bitLength); 963 | appendBitsToBuffer(assignVal >> 10, 11, buf, &result.bitLength); 964 | appendBitsToBuffer(assignVal & 0x3FF, 10, buf, &result.bitLength); 965 | } else 966 | assert(false); 967 | result.data = buf; 968 | return result; 969 | } 970 | 971 | 972 | // Calculates the number of bits needed to encode the given segments at the given version. 973 | // Returns a non-negative number if successful. Otherwise returns -1 if a segment has too 974 | // many characters to fit its length field, or the total bits exceeds INT16_MAX. 975 | testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { 976 | assert(segs != NULL || len == 0); 977 | long result = 0; 978 | for (size_t i = 0; i < len; i++) { 979 | int numChars = segs[i].numChars; 980 | int bitLength = segs[i].bitLength; 981 | assert(0 <= numChars && numChars <= INT16_MAX); 982 | assert(0 <= bitLength && bitLength <= INT16_MAX); 983 | int ccbits = numCharCountBits(segs[i].mode, version); 984 | assert(0 <= ccbits && ccbits <= 16); 985 | if (numChars >= (1L << ccbits)) 986 | return -1; // The segment's length doesn't fit the field's bit width 987 | result += 4L + ccbits + bitLength; 988 | if (result > INT16_MAX) 989 | return -1; // The sum might overflow an int type 990 | } 991 | assert(0 <= result && result <= INT16_MAX); 992 | return (int)result; 993 | } 994 | 995 | 996 | // Returns the bit width of the character count field for a segment in the given mode 997 | // in a QR Code at the given version number. The result is in the range [0, 16]. 998 | static int numCharCountBits(enum qrcodegen_Mode mode, int version) { 999 | assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); 1000 | int i = (version + 7) / 17; 1001 | switch (mode) { 1002 | case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; } 1003 | case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; } 1004 | case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; } 1005 | case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; } 1006 | case qrcodegen_Mode_ECI : return 0; 1007 | default: assert(false); return -1; // Dummy value 1008 | } 1009 | } 1010 | --------------------------------------------------------------------------------