Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/qr.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* qr.c Handles QR Code, Micro QR Code, UPNQR and rMQR */ | |
| 2 /* | |
| 3 libzint - the open source barcode library | |
| 4 Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com> | |
| 5 | |
| 6 Redistribution and use in source and binary forms, with or without | |
| 7 modification, are permitted provided that the following conditions | |
| 8 are met: | |
| 9 | |
| 10 1. Redistributions of source code must retain the above copyright | |
| 11 notice, this list of conditions and the following disclaimer. | |
| 12 2. Redistributions in binary form must reproduce the above copyright | |
| 13 notice, this list of conditions and the following disclaimer in the | |
| 14 documentation and/or other materials provided with the distribution. | |
| 15 3. Neither the name of the project nor the names of its contributors | |
| 16 may be used to endorse or promote products derived from this software | |
| 17 without specific prior written permission. | |
| 18 | |
| 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
| 20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE | |
| 23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 29 SUCH DAMAGE. | |
| 30 */ | |
| 31 /* SPDX-License-Identifier: BSD-3-Clause */ | |
| 32 | |
| 33 #include <assert.h> | |
| 34 #include <math.h> | |
| 35 #include <stdio.h> | |
| 36 #include "common.h" | |
| 37 #include "eci.h" | |
| 38 #include "qr.h" | |
| 39 #include "reedsol.h" | |
| 40 | |
| 41 #define QR_ALPHA (IS_NUM_F | IS_UPR_F | IS_SPC_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SIL_F | IS_CLI_F) | |
| 42 | |
| 43 #define QR_LEVEL_L 0 | |
| 44 #define QR_LEVEL_M 1 | |
| 45 #define QR_LEVEL_Q 2 | |
| 46 #define QR_LEVEL_H 3 | |
| 47 | |
| 48 static const char qr_ecc_level_names[] = { 'L', 'M', 'Q', 'H' }; | |
| 49 | |
| 50 #define QR_PERCENT 38 /* Alphanumeric mode % */ | |
| 51 | |
| 52 #define RMQR_VERSION 41 | |
| 53 #define MICROQR_VERSION 73 | |
| 54 | |
| 55 /* Returns true if input glyph is in the Alphanumeric set or is GS1 FNC1 */ | |
| 56 static int qr_is_alpha(const unsigned int glyph, const int gs1) { | |
| 57 if (is_chr(QR_ALPHA, glyph)) { | |
| 58 return 1; | |
| 59 } | |
| 60 if (gs1 && glyph == '\x1D') { | |
| 61 return 1; | |
| 62 } | |
| 63 return 0; | |
| 64 } | |
| 65 | |
| 66 /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ | |
| 67 #define QR_MULT 6 | |
| 68 | |
| 69 /* Whether in numeric or not. If in numeric, *p_end is set to position after numeric, and *p_cost is set to | |
| 70 * per-numeric cost */ | |
| 71 static int qr_in_numeric(const unsigned int ddata[], const int length, const int in_posn, | |
| 72 unsigned int *p_end, unsigned int *p_cost) { | |
| 73 int i, digit_cnt; | |
| 74 | |
| 75 if (in_posn < (int) *p_end) { | |
| 76 return 1; | |
| 77 } | |
| 78 | |
| 79 /* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times QR_MULT) */ | |
| 80 for (i = in_posn; i < length && i < in_posn + 3 && z_isdigit(ddata[i]); i++); | |
| 81 | |
| 82 digit_cnt = i - in_posn; | |
| 83 | |
| 84 if (digit_cnt == 0) { | |
| 85 *p_end = 0; | |
| 86 return 0; | |
| 87 } | |
| 88 *p_end = i; | |
| 89 *p_cost = digit_cnt == 1 | |
| 90 ? 24 /* 4 * QR_MULT */ : digit_cnt == 2 ? 21 /* (7 / 2) * QR_MULT */ : 20 /* (10 / 3) * QR_MULT) */; | |
| 91 return 1; | |
| 92 } | |
| 93 | |
| 94 /* Whether in alpha or not. If in alpha, *p_end is set to position after alpha, and *p_cost is set to per-alpha cost. | |
| 95 * For GS1, *p_pcent set if 2nd char percent */ | |
| 96 static int qr_in_alpha(const unsigned int ddata[], const int length, const int in_posn, | |
| 97 unsigned int *p_end, unsigned int *p_cost, unsigned int *p_pcent, unsigned int *p_pccnt, | |
| 98 unsigned int gs1) { | |
| 99 const int last = in_posn + 1 == length; | |
| 100 int two_alphas; | |
| 101 | |
| 102 /* Attempt to calculate the average 'cost' of using alphanumeric mode in number of bits (times QR_MULT) */ | |
| 103 if (in_posn < (int) *p_end) { | |
| 104 if (gs1) { | |
| 105 if (*p_pcent) { | |
| 106 /* Previous 2nd char was a percent, so allow for second half of doubled-up percent here */ | |
| 107 two_alphas = !last && qr_is_alpha(ddata[in_posn + 1], gs1); | |
| 108 /* Uneven percents means this will fit evenly in alpha pair */ | |
| 109 *p_cost = two_alphas || !(*p_pccnt & 1) ? 66 /* 11 * QR_MULT */ : 69 /* (11 / 2 + 6) * QR_MULT */; | |
| 110 *p_pcent = 0; | |
| 111 } else { | |
| 112 /* As above, uneven percents means will fit in alpha pair */ | |
| 113 *p_cost = !last || !(*p_pccnt & 1) ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; | |
| 114 } | |
| 115 } else { | |
| 116 *p_cost = !last ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; | |
| 117 } | |
| 118 return 1; | |
| 119 } | |
| 120 | |
| 121 if (!qr_is_alpha(ddata[in_posn], gs1)) { | |
| 122 *p_end = 0; | |
| 123 *p_pcent = 0; | |
| 124 *p_pccnt = 0; | |
| 125 return 0; | |
| 126 } | |
| 127 | |
| 128 two_alphas = !last && qr_is_alpha(ddata[in_posn + 1], gs1); | |
| 129 | |
| 130 if (gs1 && ddata[in_posn] == '%') { /* Must double-up so counts as 2 chars */ | |
| 131 *p_end = in_posn + 1; | |
| 132 *p_pcent = 0; | |
| 133 (*p_pccnt)++; | |
| 134 /* Uneven percents means will fit in alpha pair */ | |
| 135 *p_cost = two_alphas || !(*p_pccnt & 1) ? 66 /* 11 * QR_MULT */ : 69 /* (11 / 2 + 6) * QR_MULT */; | |
| 136 return 1; | |
| 137 } | |
| 138 | |
| 139 *p_end = two_alphas ? in_posn + 2 : in_posn + 1; | |
| 140 if (gs1) { | |
| 141 *p_pcent = two_alphas && ddata[in_posn + 1] == '%'; /* 2nd char is percent */ | |
| 142 *p_pccnt += *p_pcent; | |
| 143 /* Uneven percents means will fit in alpha pair */ | |
| 144 *p_cost = two_alphas || !(*p_pccnt & 1) ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; | |
| 145 } else { | |
| 146 *p_cost = two_alphas ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; | |
| 147 } | |
| 148 return 1; | |
| 149 } | |
| 150 | |
| 151 #if 0 | |
| 152 #define QR_DEBUG_DEFINE_MODE /* For debugging costings */ | |
| 153 #endif | |
| 154 | |
| 155 /* Indexes into qr_mode_types array (and state array) */ | |
| 156 #define QR_N 0 /* Numeric */ | |
| 157 #define QR_A 1 /* Alphanumeric */ | |
| 158 #define QR_B 2 /* Byte */ | |
| 159 #define QR_K 3 /* Kanji */ | |
| 160 | |
| 161 static const char qr_mode_types[] = { 'N', 'A', 'B', 'K', '\0' }; /* Must be in same order as QR_N etc */ | |
| 162 | |
| 163 #define QR_NUM_MODES 4 | |
| 164 | |
| 165 /* Indexes into state array (0..3 head costs) */ | |
| 166 #define QR_VER 4 /* Version */ | |
| 167 #define QR_N_END 5 /* Numeric end index */ | |
| 168 #define QR_N_COST 6 /* Numeric cost */ | |
| 169 #define QR_A_END 7 /* Alpha end index */ | |
| 170 #define QR_A_COST 8 /* Alpha cost */ | |
| 171 #define QR_A_PCENT 9 /* Alpha 2nd char percent (GS1-specific) */ | |
| 172 #define QR_A_PCCNT 10 /* Alpha total percent count (GS1-specific) */ | |
| 173 | |
| 174 /* Costs set to this for invalid MICROQR modes for versions M1 and M2. | |
| 175 * 128 is the max number of data bits for M4-L (ISO/IEC 18004:2015 Table 7) */ | |
| 176 #define QR_MICROQR_MAX 774 /* (128 + 1) * QR_MULT */ | |
| 177 | |
| 178 /* Initial mode costs */ | |
| 179 static unsigned int *qr_head_costs(unsigned int state[11]) { | |
| 180 static const unsigned int head_costs[7][QR_NUM_MODES] = { | |
| 181 /* N A B K */ | |
| 182 { (10 + 4) * QR_MULT, (9 + 4) * QR_MULT, (8 + 4) * QR_MULT, (8 + 4) * QR_MULT, }, /* QR */ | |
| 183 { (12 + 4) * QR_MULT, (11 + 4) * QR_MULT, (16 + 4) * QR_MULT, (10 + 4) * QR_MULT, }, | |
| 184 { (14 + 4) * QR_MULT, (13 + 4) * QR_MULT, (16 + 4) * QR_MULT, (12 + 4) * QR_MULT, }, | |
| 185 { 3 * QR_MULT, QR_MICROQR_MAX, QR_MICROQR_MAX, QR_MICROQR_MAX, }, /* MICROQR */ | |
| 186 { (4 + 1) * QR_MULT, (3 + 1) * QR_MULT, QR_MICROQR_MAX, QR_MICROQR_MAX, }, | |
| 187 { (5 + 2) * QR_MULT, (4 + 2) * QR_MULT, (4 + 2) * QR_MULT, (3 + 2) * QR_MULT, }, | |
| 188 { (6 + 3) * QR_MULT, (5 + 3) * QR_MULT, (5 + 3) * QR_MULT, (4 + 3) * QR_MULT, } | |
| 189 }; | |
| 190 int version; | |
| 191 | |
| 192 /* Head costs kept in states 0..3 */ | |
| 193 | |
| 194 version = state[QR_VER]; | |
| 195 | |
| 196 if (version < RMQR_VERSION) { /* QRCODE */ | |
| 197 if (version < 10) { | |
| 198 memcpy(state, head_costs[0], QR_NUM_MODES * sizeof(unsigned int)); | |
| 199 } else if (version < 27) { | |
| 200 memcpy(state, head_costs[1], QR_NUM_MODES * sizeof(unsigned int)); | |
| 201 } else { | |
| 202 memcpy(state, head_costs[2], QR_NUM_MODES * sizeof(unsigned int)); | |
| 203 } | |
| 204 } else if (version < MICROQR_VERSION) { /* RMQR */ | |
| 205 version -= RMQR_VERSION; | |
| 206 state[QR_N] = (rmqr_numeric_cci[version] + 3) * QR_MULT; | |
| 207 state[QR_A] = (rmqr_alphanum_cci[version] + 3) * QR_MULT; | |
| 208 state[QR_B] = (rmqr_byte_cci[version] + 3) * QR_MULT; | |
| 209 state[QR_K] = (rmqr_kanji_cci[version] + 3) * QR_MULT; | |
| 210 } else { /* MICROQR */ | |
| 211 memcpy(state, head_costs[3 + (version - MICROQR_VERSION)], QR_NUM_MODES * sizeof(unsigned int)); | |
| 212 } | |
| 213 | |
| 214 return state; | |
| 215 } | |
| 216 | |
| 217 /* Calculate optimized encoding modes. Adapted from Project Nayuki */ | |
| 218 static void qr_define_mode(char mode[], const unsigned int ddata[], const int length, const int gs1, | |
| 219 const int version, const int debug_print) { | |
| 220 /* | |
| 221 * Copyright (c) Project Nayuki. (MIT License) | |
| 222 * https://www.nayuki.io/page/qr-code-generator-library | |
| 223 * | |
| 224 * Permission is hereby granted, free of charge, to any person obtaining a copy of | |
| 225 * this software and associated documentation files (the "Software"), to deal in | |
| 226 * the Software without restriction, including without limitation the rights to | |
| 227 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |
| 228 * the Software, and to permit persons to whom the Software is furnished to do so, | |
| 229 * subject to the following conditions: | |
| 230 * - The above copyright notice and this permission notice shall be included in | |
| 231 * all copies or substantial portions of the Software. | |
| 232 */ | |
| 233 unsigned int state[11] = { | |
| 234 0 /*N*/, 0 /*A*/, 0 /*B*/, 0 /*K*/, /* Head/switch costs */ | |
| 235 0 /*version*/, | |
| 236 0 /*numeric_end*/, 0 /*numeric_cost*/, 0 /*alpha_end*/, 0 /*alpha_cost*/, 0 /*alpha_pcent*/, 0 /*alpha_pccnt*/ | |
| 237 }; | |
| 238 int m1, m2; | |
| 239 | |
| 240 int i, j, k; | |
| 241 unsigned int min_cost; | |
| 242 char cur_mode; | |
| 243 unsigned int prev_costs[QR_NUM_MODES]; | |
| 244 unsigned int cur_costs[QR_NUM_MODES]; | |
| 245 char (*char_modes)[QR_NUM_MODES] = (char (*)[QR_NUM_MODES]) z_alloca(QR_NUM_MODES * length); | |
| 246 | |
| 247 state[QR_VER] = (unsigned int) version; | |
| 248 | |
| 249 /* char_modes[i][j] represents the mode to encode the code point at index i such that the final segment | |
| 250 ends in qr_mode_types[j] and the total number of bits is minimized over all possible choices */ | |
| 251 memset(char_modes, 0, QR_NUM_MODES * length); | |
| 252 | |
| 253 /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/QR_MULT) | |
| 254 * bits needed to encode the entire string prefix of length i, and end in qr_mode_types[j] */ | |
| 255 memcpy(prev_costs, qr_head_costs(state), QR_NUM_MODES * sizeof(unsigned int)); | |
| 256 | |
| 257 #ifdef QR_DEBUG_DEFINE_MODE | |
| 258 printf(" head"); | |
| 259 for (j = 0; j < QR_NUM_MODES; j++) { | |
| 260 printf(" %c(%c)=%d", qr_mode_types[j], char_modes[0][j], prev_costs[j]); | |
| 261 } | |
| 262 printf("\n"); | |
| 263 #endif | |
| 264 | |
| 265 /* Calculate costs using dynamic programming */ | |
| 266 for (i = 0; i < length; i++) { | |
| 267 memset(cur_costs, 0, QR_NUM_MODES * sizeof(unsigned int)); | |
| 268 | |
| 269 m1 = version == MICROQR_VERSION; | |
| 270 m2 = version == MICROQR_VERSION + 1; | |
| 271 | |
| 272 if (ddata[i] > 0xFF) { | |
| 273 cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 96); /* 16 * QR_MULT */ | |
| 274 char_modes[i][QR_B] = 'B'; | |
| 275 cur_costs[QR_K] = prev_costs[QR_K] + ((m1 || m2) ? QR_MICROQR_MAX : 78); /* 13 * QR_MULT */ | |
| 276 char_modes[i][QR_K] = 'K'; | |
| 277 } else { | |
| 278 if (qr_in_numeric(ddata, length, i, &state[QR_N_END], &state[QR_N_COST])) { | |
| 279 cur_costs[QR_N] = prev_costs[QR_N] + state[QR_N_COST]; | |
| 280 char_modes[i][QR_N] = 'N'; | |
| 281 } | |
| 282 if (qr_in_alpha(ddata, length, i, &state[QR_A_END], &state[QR_A_COST], &state[QR_A_PCENT], | |
| 283 &state[QR_A_PCCNT], gs1)) { | |
| 284 cur_costs[QR_A] = prev_costs[QR_A] + (m1 ? QR_MICROQR_MAX : state[QR_A_COST]); | |
| 285 char_modes[i][QR_A] = 'A'; | |
| 286 } | |
| 287 cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 48); /* 8 * QR_MULT */ | |
| 288 char_modes[i][QR_B] = 'B'; | |
| 289 } | |
| 290 | |
| 291 /* Start new segment at the end to switch modes */ | |
| 292 for (j = 0; j < QR_NUM_MODES; j++) { /* To mode */ | |
| 293 for (k = 0; k < QR_NUM_MODES; k++) { /* From mode */ | |
| 294 if (j != k && char_modes[i][k]) { | |
| 295 const unsigned int new_cost = cur_costs[k] + state[j]; /* Switch costs same as head costs */ | |
| 296 if (!char_modes[i][j] || new_cost < cur_costs[j]) { | |
| 297 cur_costs[j] = new_cost; | |
| 298 char_modes[i][j] = qr_mode_types[k]; | |
| 299 } | |
| 300 } | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 #ifdef QR_DEBUG_DEFINE_MODE | |
| 305 { | |
| 306 int min_j = 0; | |
| 307 printf(" % 4d: curr", i); | |
| 308 for (j = 0; j < QR_NUM_MODES; j++) { | |
| 309 printf(" %c(%c)=%d", qr_mode_types[j], char_modes[i][j], cur_costs[j]); | |
| 310 if (cur_costs[j] < cur_costs[min_j]) min_j = j; | |
| 311 } | |
| 312 printf(" min %c(%c)=%d\n", qr_mode_types[min_j], char_modes[i][min_j], cur_costs[min_j]); | |
| 313 } | |
| 314 #endif | |
| 315 memcpy(prev_costs, cur_costs, QR_NUM_MODES * sizeof(unsigned int)); | |
| 316 } | |
| 317 | |
| 318 /* Find optimal ending mode */ | |
| 319 min_cost = prev_costs[0]; | |
| 320 cur_mode = qr_mode_types[0]; | |
| 321 for (i = 1; i < QR_NUM_MODES; i++) { | |
| 322 if (prev_costs[i] < min_cost) { | |
| 323 min_cost = prev_costs[i]; | |
| 324 cur_mode = qr_mode_types[i]; | |
| 325 } | |
| 326 } | |
| 327 | |
| 328 /* Get optimal mode for each code point by tracing backwards */ | |
| 329 for (i = length - 1; i >= 0; i--) { | |
| 330 j = posn(qr_mode_types, cur_mode); | |
| 331 cur_mode = char_modes[i][j]; | |
| 332 mode[i] = cur_mode; | |
| 333 } | |
| 334 | |
| 335 if (debug_print) { | |
| 336 printf(" Mode: %.*s\n", length, mode); | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 /* Returns mode indicator based on version and mode */ | |
| 341 static int qr_mode_indicator(const int version, const int mode) { | |
| 342 static const char mode_indicators[6][QR_NUM_MODES] = { | |
| 343 /*N A B K */ | |
| 344 { 1, 2, 4, 8, }, /* QRCODE */ | |
| 345 { 1, 2, 3, 4, }, /* RMQR */ | |
| 346 { 0, 0, 0, 0, }, /* MICROQR */ | |
| 347 { 0, 1, 0, 0, }, | |
| 348 { 0, 1, 2, 3, }, | |
| 349 { 0, 1, 2, 3, }, | |
| 350 }; | |
| 351 | |
| 352 int mode_index = posn(qr_mode_types, (const char) mode); | |
| 353 | |
| 354 if (version < RMQR_VERSION) { | |
| 355 return mode_indicators[0][mode_index]; /* QRCODE */ | |
| 356 } | |
| 357 if (version < MICROQR_VERSION) { | |
| 358 return mode_indicators[1][mode_index] /* RMQR */; | |
| 359 } | |
| 360 return mode_indicators[2 + version - MICROQR_VERSION][mode_index]; /* MICROQR */ | |
| 361 } | |
| 362 | |
| 363 /* Return mode indicator bits based on version */ | |
| 364 static int qr_mode_bits(const int version) { | |
| 365 if (version < RMQR_VERSION) { | |
| 366 return 4; /* QRCODE */ | |
| 367 } | |
| 368 if (version < MICROQR_VERSION) { | |
| 369 return 3; /* RMQR */ | |
| 370 } | |
| 371 return version - MICROQR_VERSION; /* MICROQR */ | |
| 372 } | |
| 373 | |
| 374 /* Return character count indicator bits based on version and mode */ | |
| 375 static int qr_cci_bits(const int version, const int mode) { | |
| 376 static const char cci_bits[7][QR_NUM_MODES] = { | |
| 377 /* N A B K */ | |
| 378 { 10, 9, 8, 8, }, /* QRCODE */ | |
| 379 { 12, 11, 16, 10, }, | |
| 380 { 14, 13, 16, 12, }, | |
| 381 { 3, 0, 0, 0, }, /* MICROQR */ | |
| 382 { 4, 3, 0, 0, }, | |
| 383 { 5, 4, 4, 3, }, | |
| 384 { 6, 5, 5, 4, } | |
| 385 }; | |
| 386 static const unsigned char *const rmqr_ccis[QR_NUM_MODES] = { | |
| 387 rmqr_numeric_cci, rmqr_alphanum_cci, rmqr_byte_cci, rmqr_kanji_cci, | |
| 388 }; | |
| 389 int mode_index = posn(qr_mode_types, (const char) mode); | |
| 390 | |
| 391 if (version < RMQR_VERSION) { /* QRCODE */ | |
| 392 if (version < 10) { | |
| 393 return cci_bits[0][mode_index]; | |
| 394 } | |
| 395 if (version < 27) { | |
| 396 return cci_bits[1][mode_index]; | |
| 397 } | |
| 398 return cci_bits[2][mode_index]; | |
| 399 } | |
| 400 if (version < MICROQR_VERSION) { /* RMQR */ | |
| 401 return rmqr_ccis[mode_index][version - RMQR_VERSION]; | |
| 402 } | |
| 403 return cci_bits[3 + (version - MICROQR_VERSION)][mode_index]; /* MICROQR */ | |
| 404 } | |
| 405 | |
| 406 /* Returns terminator bits based on version */ | |
| 407 static int qr_terminator_bits(const int version) { | |
| 408 if (version < RMQR_VERSION) { | |
| 409 return 4; /* QRCODE */ | |
| 410 } | |
| 411 if (version < MICROQR_VERSION) { | |
| 412 return 3; /* RMQR */ | |
| 413 } | |
| 414 return 3 + (version - MICROQR_VERSION) * 2; /* MICROQR */ | |
| 415 } | |
| 416 | |
| 417 /* Convert input data to a binary stream and add padding */ | |
| 418 static int qr_binary(char binary[], int bp, const int version, const char mode[], | |
| 419 const unsigned int ddata[], const int length, const int gs1, | |
| 420 const int eci, const int debug_print) { | |
| 421 int position = 0; | |
| 422 int i; | |
| 423 int modebits; | |
| 424 int percent = 0; | |
| 425 int percent_count; | |
| 426 | |
| 427 if (eci != 0) { /* Not applicable to MICROQR */ | |
| 428 bp = bin_append_posn(7, version < RMQR_VERSION ? 4 : 3, binary, bp); /* ECI (Table 4) */ | |
| 429 if (eci <= 127) { | |
| 430 bp = bin_append_posn(eci, 8, binary, bp); /* 000000 to 000127 */ | |
| 431 } else if (eci <= 16383) { | |
| 432 bp = bin_append_posn(0x8000 + eci, 16, binary, bp); /* 000128 to 016383 */ | |
| 433 } else { | |
| 434 bp = bin_append_posn(0xC00000 + eci, 24, binary, bp); /* 016384 to 999999 */ | |
| 435 } | |
| 436 } | |
| 437 | |
| 438 modebits = qr_mode_bits(version); | |
| 439 | |
| 440 do { | |
| 441 char data_block = mode[position]; | |
| 442 int short_data_block_length = 0; | |
| 443 int double_byte = 0; | |
| 444 do { | |
| 445 if (data_block == 'B' && ddata[position + short_data_block_length] > 0xFF) { | |
| 446 double_byte++; | |
| 447 } | |
| 448 short_data_block_length++; | |
| 449 } while (((short_data_block_length + position) < length) | |
| 450 && (mode[position + short_data_block_length] == data_block)); | |
| 451 | |
| 452 /* Mode indicator */ | |
| 453 if (modebits) { | |
| 454 bp = bin_append_posn(qr_mode_indicator(version, data_block), modebits, binary, bp); | |
| 455 } | |
| 456 | |
| 457 switch (data_block) { | |
| 458 case 'K': | |
| 459 /* Kanji mode */ | |
| 460 | |
| 461 /* Character count indicator */ | |
| 462 bp = bin_append_posn(short_data_block_length, qr_cci_bits(version, data_block), binary, bp); | |
| 463 | |
| 464 if (debug_print) { | |
| 465 printf("Kanji block (length %d)\n\t", short_data_block_length); | |
| 466 } | |
| 467 | |
| 468 /* Character representation */ | |
| 469 for (i = 0; i < short_data_block_length; i++) { | |
| 470 unsigned int jis = ddata[position + i]; | |
| 471 int prod; | |
| 472 | |
| 473 if (jis >= 0x8140 && jis <= 0x9ffc) | |
| 474 jis -= 0x8140; | |
| 475 | |
| 476 else if (jis >= 0xe040 && jis <= 0xebbf) | |
| 477 jis -= 0xc140; | |
| 478 | |
| 479 prod = ((jis >> 8) * 0xc0) + (jis & 0xff); | |
| 480 | |
| 481 bp = bin_append_posn(prod, 13, binary, bp); | |
| 482 | |
| 483 if (debug_print) { | |
| 484 printf("0x%04X ", prod); | |
| 485 } | |
| 486 } | |
| 487 | |
| 488 if (debug_print) { | |
| 489 fputc('\n', stdout); | |
| 490 } | |
| 491 | |
| 492 break; | |
| 493 case 'B': | |
| 494 /* Byte mode */ | |
| 495 | |
| 496 /* Character count indicator */ | |
| 497 bp = bin_append_posn(short_data_block_length + double_byte, qr_cci_bits(version, data_block), binary, | |
| 498 bp); | |
| 499 | |
| 500 if (debug_print) { | |
| 501 printf("Byte block (length %d)\n\t", short_data_block_length + double_byte); | |
| 502 } | |
| 503 | |
| 504 /* Character representation */ | |
| 505 for (i = 0; i < short_data_block_length; i++) { | |
| 506 unsigned int byte = ddata[position + i]; | |
| 507 | |
| 508 bp = bin_append_posn(byte, byte > 0xFF ? 16 : 8, binary, bp); | |
| 509 | |
| 510 if (debug_print) { | |
| 511 printf("0x%02X(%d) ", byte, (int) byte); | |
| 512 } | |
| 513 } | |
| 514 | |
| 515 if (debug_print) { | |
| 516 fputc('\n', stdout); | |
| 517 } | |
| 518 | |
| 519 break; | |
| 520 case 'A': | |
| 521 /* Alphanumeric mode */ | |
| 522 | |
| 523 percent_count = 0; | |
| 524 if (gs1) { | |
| 525 for (i = 0; i < short_data_block_length; i++) { | |
| 526 if (ddata[position + i] == '%') { | |
| 527 percent_count++; | |
| 528 } | |
| 529 } | |
| 530 } | |
| 531 | |
| 532 /* Character count indicator */ | |
| 533 bp = bin_append_posn(short_data_block_length + percent_count, qr_cci_bits(version, data_block), | |
| 534 binary, bp); | |
| 535 | |
| 536 if (debug_print) { | |
| 537 printf("Alpha block (length %d)\n\t", short_data_block_length + percent_count); | |
| 538 } | |
| 539 | |
| 540 /* Character representation */ | |
| 541 i = 0; | |
| 542 while (i < short_data_block_length) { | |
| 543 int count; | |
| 544 int first = 0, second = 0, prod; | |
| 545 | |
| 546 if (percent == 0) { | |
| 547 if (gs1 && (ddata[position + i] == '%')) { | |
| 548 first = QR_PERCENT; | |
| 549 second = QR_PERCENT; | |
| 550 count = 2; | |
| 551 prod = (first * 45) + second; | |
| 552 i++; | |
| 553 } else { | |
| 554 if (gs1 && ddata[position + i] == '\x1D') { | |
| 555 first = QR_PERCENT; /* FNC1 */ | |
| 556 } else { | |
| 557 first = qr_alphanumeric[ddata[position + i] - 32]; | |
| 558 } | |
| 559 count = 1; | |
| 560 i++; | |
| 561 prod = first; | |
| 562 | |
| 563 if (i < short_data_block_length && mode[position + i] == 'A') { | |
| 564 if (gs1 && (ddata[position + i] == '%')) { | |
| 565 second = QR_PERCENT; | |
| 566 count = 2; | |
| 567 prod = (first * 45) + second; | |
| 568 percent = 1; | |
| 569 } else { | |
| 570 if (gs1 && ddata[position + i] == '\x1D') { | |
| 571 second = QR_PERCENT; /* FNC1 */ | |
| 572 } else { | |
| 573 second = qr_alphanumeric[ddata[position + i] - 32]; | |
| 574 } | |
| 575 count = 2; | |
| 576 i++; | |
| 577 prod = (first * 45) + second; | |
| 578 } | |
| 579 } | |
| 580 } | |
| 581 } else { | |
| 582 first = QR_PERCENT; | |
| 583 count = 1; | |
| 584 i++; | |
| 585 prod = first; | |
| 586 percent = 0; | |
| 587 | |
| 588 if (i < short_data_block_length && mode[position + i] == 'A') { | |
| 589 if (gs1 && (ddata[position + i] == '%')) { | |
| 590 second = QR_PERCENT; | |
| 591 count = 2; | |
| 592 prod = (first * 45) + second; | |
| 593 percent = 1; | |
| 594 } else { | |
| 595 if (gs1 && ddata[position + i] == '\x1D') { | |
| 596 second = QR_PERCENT; /* FNC1 */ | |
| 597 } else { | |
| 598 second = qr_alphanumeric[ddata[position + i] - 32]; | |
| 599 } | |
| 600 count = 2; | |
| 601 i++; | |
| 602 prod = (first * 45) + second; | |
| 603 } | |
| 604 } | |
| 605 } | |
| 606 | |
| 607 bp = bin_append_posn(prod, 1 + (5 * count), binary, bp); | |
| 608 | |
| 609 if (debug_print) { | |
| 610 printf("0x%X ", prod); | |
| 611 } | |
| 612 } | |
| 613 | |
| 614 if (debug_print) { | |
| 615 fputc('\n', stdout); | |
| 616 } | |
| 617 | |
| 618 break; | |
| 619 case 'N': | |
| 620 /* Numeric mode */ | |
| 621 | |
| 622 /* Character count indicator */ | |
| 623 bp = bin_append_posn(short_data_block_length, qr_cci_bits(version, data_block), binary, bp); | |
| 624 | |
| 625 if (debug_print) { | |
| 626 printf("Number block (length %d)\n\t", short_data_block_length); | |
| 627 } | |
| 628 | |
| 629 /* Character representation */ | |
| 630 i = 0; | |
| 631 while (i < short_data_block_length) { | |
| 632 int count; | |
| 633 int first = 0, prod; | |
| 634 | |
| 635 first = ctoi((const char) ddata[position + i]); | |
| 636 count = 1; | |
| 637 prod = first; | |
| 638 | |
| 639 if (i + 1 < short_data_block_length && mode[position + i + 1] == 'N') { | |
| 640 int second = ctoi((const char) ddata[position + i + 1]); | |
| 641 count = 2; | |
| 642 prod = (prod * 10) + second; | |
| 643 | |
| 644 if (i + 2 < short_data_block_length && mode[position + i + 2] == 'N') { | |
| 645 int third = ctoi((const char) ddata[position + i + 2]); | |
| 646 count = 3; | |
| 647 prod = (prod * 10) + third; | |
| 648 } | |
| 649 } | |
| 650 | |
| 651 bp = bin_append_posn(prod, 1 + (3 * count), binary, bp); | |
| 652 | |
| 653 if (debug_print) { | |
| 654 printf("0x%X(%d) ", prod, prod); | |
| 655 } | |
| 656 | |
| 657 i += count; | |
| 658 }; | |
| 659 | |
| 660 if (debug_print) { | |
| 661 fputc('\n', stdout); | |
| 662 } | |
| 663 | |
| 664 break; | |
| 665 } | |
| 666 | |
| 667 position += short_data_block_length; | |
| 668 } while (position < length); | |
| 669 | |
| 670 return bp; | |
| 671 } | |
| 672 | |
| 673 /* Call `qr_binary()` for each segment, dealing with Structured Append and GS1 beforehand and padding afterwards */ | |
| 674 static int qr_binary_segs(unsigned char datastream[], const int version, const int target_codewords, | |
| 675 const char mode[], const unsigned int ddata[], const struct zint_seg segs[], const int seg_count, | |
| 676 const struct zint_structapp *p_structapp, const int gs1, const int est_binlen, const int debug_print) { | |
| 677 int i, j; | |
| 678 const unsigned int *dd = ddata; | |
| 679 const char *m = mode; | |
| 680 int bp = 0; | |
| 681 int termbits, padbits; | |
| 682 int current_bytes; | |
| 683 int toggle; | |
| 684 char *binary = (char *) z_alloca(est_binlen + 12); | |
| 685 | |
| 686 *binary = '\0'; | |
| 687 | |
| 688 if (p_structapp) { | |
| 689 bp = bin_append_posn(3, 4, binary, bp); /* Structured Append indicator */ | |
| 690 bp = bin_append_posn(p_structapp->index - 1, 4, binary, bp); | |
| 691 bp = bin_append_posn(p_structapp->count - 1, 4, binary, bp); | |
| 692 bp = bin_append_posn(to_int((const unsigned char *) p_structapp->id, (int) strlen(p_structapp->id)), 8, | |
| 693 binary, bp); /* Parity */ | |
| 694 } | |
| 695 | |
| 696 if (gs1) { /* Not applicable to MICROQR */ | |
| 697 if (version < RMQR_VERSION) { | |
| 698 bp = bin_append_posn(5, 4, binary, bp); /* FNC1 */ | |
| 699 } else { | |
| 700 bp = bin_append_posn(5, 3, binary, bp); | |
| 701 } | |
| 702 } | |
| 703 | |
| 704 for (i = 0; i < seg_count; i++) { | |
| 705 bp = qr_binary(binary, bp, version, m, dd, segs[i].length, gs1, segs[i].eci, debug_print); | |
| 706 m += segs[i].length; | |
| 707 dd += segs[i].length; | |
| 708 } | |
| 709 | |
| 710 if (version >= MICROQR_VERSION && version < MICROQR_VERSION + 4) { | |
| 711 /* MICROQR does its own terminating/padding */ | |
| 712 memcpy(datastream, binary, bp); | |
| 713 return bp; | |
| 714 } | |
| 715 | |
| 716 /* Terminator */ | |
| 717 termbits = 8 - bp % 8; | |
| 718 if (termbits == 8) { | |
| 719 termbits = 0; | |
| 720 } | |
| 721 current_bytes = (bp + termbits) / 8; | |
| 722 if (termbits || current_bytes < target_codewords) { | |
| 723 int max_termbits = qr_terminator_bits(version); | |
| 724 termbits = termbits < max_termbits && current_bytes == target_codewords ? termbits : max_termbits; | |
| 725 bp = bin_append_posn(0, termbits, binary, bp); | |
| 726 } | |
| 727 | |
| 728 /* Padding bits */ | |
| 729 padbits = 8 - bp % 8; | |
| 730 if (padbits == 8) { | |
| 731 padbits = 0; | |
| 732 } | |
| 733 if (padbits) { | |
| 734 current_bytes = (bp + padbits) / 8; | |
| 735 (void) bin_append_posn(0, padbits, binary, bp); /* Last use so not setting bp */ | |
| 736 } | |
| 737 | |
| 738 if (debug_print) printf("Terminated binary (%d): %.*s (padbits %d)\n", bp, bp, binary, padbits); | |
| 739 | |
| 740 /* Put data into 8-bit codewords */ | |
| 741 for (i = 0; i < current_bytes; i++) { | |
| 742 int p; | |
| 743 j = i * 8; | |
| 744 datastream[i] = 0x00; | |
| 745 for (p = 0; p < 8; p++) { | |
| 746 if (binary[j + p] == '1') { | |
| 747 datastream[i] |= (0x80 >> p); | |
| 748 } | |
| 749 } | |
| 750 } | |
| 751 | |
| 752 /* Add pad codewords */ | |
| 753 toggle = 0; | |
| 754 for (i = current_bytes; i < target_codewords; i++) { | |
| 755 if (toggle == 0) { | |
| 756 datastream[i] = 0xec; | |
| 757 toggle = 1; | |
| 758 } else { | |
| 759 datastream[i] = 0x11; | |
| 760 toggle = 0; | |
| 761 } | |
| 762 } | |
| 763 | |
| 764 if (debug_print) { | |
| 765 printf("Resulting codewords (%d):\n\t", target_codewords); | |
| 766 for (i = 0; i < target_codewords; i++) { | |
| 767 printf("0x%02X ", datastream[i]); | |
| 768 } | |
| 769 fputc('\n', stdout); | |
| 770 } | |
| 771 | |
| 772 return 0; /* Not used */ | |
| 773 } | |
| 774 | |
| 775 /* Split data into blocks, add error correction and then interleave the blocks and error correction data */ | |
| 776 static void qr_add_ecc(unsigned char fullstream[], const unsigned char datastream[], const int version, | |
| 777 const int data_cw, const int blocks, const int debug_print) { | |
| 778 int ecc_cw; | |
| 779 int short_data_block_length; | |
| 780 int qty_long_blocks; | |
| 781 int qty_short_blocks; | |
| 782 int ecc_block_length; | |
| 783 int i, j, length_this_block, in_posn; | |
| 784 rs_t rs; | |
| 785 unsigned char *data_block; | |
| 786 unsigned char *ecc_block; | |
| 787 unsigned char *interleaved_data; | |
| 788 unsigned char *interleaved_ecc; | |
| 789 | |
| 790 if (version < RMQR_VERSION) { | |
| 791 ecc_cw = qr_total_codewords[version - 1] - data_cw; | |
| 792 } else { | |
| 793 ecc_cw = rmqr_total_codewords[version - RMQR_VERSION] - data_cw; | |
| 794 } | |
| 795 | |
| 796 /* Suppress some clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.Assign warnings */ | |
| 797 assert(blocks > 0); | |
| 798 | |
| 799 short_data_block_length = data_cw / blocks; | |
| 800 qty_long_blocks = data_cw % blocks; | |
| 801 qty_short_blocks = blocks - qty_long_blocks; | |
| 802 ecc_block_length = ecc_cw / blocks; | |
| 803 | |
| 804 /* Suppress some clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.Assign warnings */ | |
| 805 assert(short_data_block_length > 0); | |
| 806 assert(qty_long_blocks || qty_short_blocks); | |
| 807 | |
| 808 data_block = (unsigned char *) z_alloca(short_data_block_length + 1); | |
| 809 ecc_block = (unsigned char *) z_alloca(ecc_block_length); | |
| 810 interleaved_data = (unsigned char *) z_alloca(data_cw); | |
| 811 interleaved_ecc = (unsigned char *) z_alloca(ecc_cw); | |
| 812 | |
| 813 rs_init_gf(&rs, 0x11d); | |
| 814 rs_init_code(&rs, ecc_block_length, 0); | |
| 815 | |
| 816 in_posn = 0; | |
| 817 | |
| 818 for (i = 0; i < blocks; i++) { | |
| 819 if (i < qty_short_blocks) { | |
| 820 length_this_block = short_data_block_length; | |
| 821 } else { | |
| 822 length_this_block = short_data_block_length + 1; | |
| 823 } | |
| 824 | |
| 825 for (j = 0; j < length_this_block; j++) { | |
| 826 /* This false-positive popped up with clang-tidy 14.0.1 */ | |
| 827 data_block[j] = datastream[in_posn + j]; /* NOLINT(clang-analyzer-core.uninitialized.Assign) */ | |
| 828 } | |
| 829 | |
| 830 rs_encode(&rs, length_this_block, data_block, ecc_block); | |
| 831 | |
| 832 if (debug_print) { | |
| 833 printf("Block %d: ", i + 1); | |
| 834 for (j = 0; j < length_this_block; j++) { | |
| 835 printf("%2X ", data_block[j]); | |
| 836 } | |
| 837 if (i < qty_short_blocks) { | |
| 838 fputs(" ", stdout); | |
| 839 } | |
| 840 fputs(" // ", stdout); | |
| 841 for (j = 0; j < ecc_block_length; j++) { | |
| 842 printf("%2X ", ecc_block[j]); | |
| 843 } | |
| 844 fputc('\n', stdout); | |
| 845 } | |
| 846 | |
| 847 for (j = 0; j < short_data_block_length; j++) { | |
| 848 /* And another with clang-tidy 14.0.6 */ | |
| 849 interleaved_data[(j * blocks) + i] = data_block[j]; /* NOLINT(clang-analyzer-core.uninitialized.Assign) */ | |
| 850 } | |
| 851 | |
| 852 if (i >= qty_short_blocks) { | |
| 853 interleaved_data[(short_data_block_length * blocks) + (i - qty_short_blocks)] | |
| 854 = data_block[short_data_block_length]; | |
| 855 } | |
| 856 | |
| 857 for (j = 0; j < ecc_block_length; j++) { | |
| 858 interleaved_ecc[(j * blocks) + i] = ecc_block[j]; | |
| 859 } | |
| 860 | |
| 861 in_posn += length_this_block; | |
| 862 } | |
| 863 | |
| 864 for (j = 0; j < data_cw; j++) { | |
| 865 fullstream[j] = interleaved_data[j]; | |
| 866 } | |
| 867 for (j = 0; j < ecc_cw; j++) { | |
| 868 fullstream[j + data_cw] = interleaved_ecc[j]; | |
| 869 } | |
| 870 | |
| 871 if (debug_print) { | |
| 872 printf("\nData Stream (%d): \n", data_cw + ecc_cw); | |
| 873 for (j = 0; j < (data_cw + ecc_cw); j++) { | |
| 874 printf("%2X ", fullstream[j]); | |
| 875 } | |
| 876 fputc('\n', stdout); | |
| 877 } | |
| 878 } | |
| 879 | |
| 880 static void qr_place_finder(unsigned char grid[], const int size, const int x, const int y) { | |
| 881 int xp, yp; | |
| 882 char finder[] = {0x7F, 0x41, 0x5D, 0x5D, 0x5D, 0x41, 0x7F}; | |
| 883 | |
| 884 for (xp = 0; xp < 7; xp++) { | |
| 885 for (yp = 0; yp < 7; yp++) { | |
| 886 if (finder[yp] & 0x40 >> xp) { | |
| 887 grid[((yp + y) * size) + (xp + x)] = 0x11; | |
| 888 } else { | |
| 889 grid[((yp + y) * size) + (xp + x)] = 0x10; | |
| 890 } | |
| 891 } | |
| 892 } | |
| 893 } | |
| 894 | |
| 895 static void qr_place_align(unsigned char grid[], const int size, int x, int y) { | |
| 896 int xp, yp; | |
| 897 char alignment[] = {0x1F, 0x11, 0x15, 0x11, 0x1F}; | |
| 898 | |
| 899 x -= 2; | |
| 900 y -= 2; /* Input values represent centre of pattern */ | |
| 901 | |
| 902 for (xp = 0; xp < 5; xp++) { | |
| 903 for (yp = 0; yp < 5; yp++) { | |
| 904 if (alignment[yp] & 0x10 >> xp) { | |
| 905 grid[((yp + y) * size) + (xp + x)] = 0x11; | |
| 906 } else { | |
| 907 grid[((yp + y) * size) + (xp + x)] = 0x10; | |
| 908 } | |
| 909 } | |
| 910 } | |
| 911 } | |
| 912 | |
| 913 static void qr_setup_grid(unsigned char *grid, const int size, const int version) { | |
| 914 int i, toggle = 1; | |
| 915 | |
| 916 /* Suppress false positive gcc >= 13 warning (when optimizing only) "writing 1 byte into a region of size 0" */ | |
| 917 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 13 | |
| 918 #pragma GCC diagnostic push | |
| 919 #pragma GCC diagnostic ignored "-Wstringop-overflow" | |
| 920 #endif | |
| 921 | |
| 922 /* Add timing patterns */ | |
| 923 for (i = 0; i < size; i++) { | |
| 924 if (toggle == 1) { | |
| 925 grid[(6 * size) + i] = 0x21; | |
| 926 grid[(i * size) + 6] = 0x21; | |
| 927 toggle = 0; | |
| 928 } else { | |
| 929 grid[(6 * size) + i] = 0x20; | |
| 930 grid[(i * size) + 6] = 0x20; | |
| 931 toggle = 1; | |
| 932 } | |
| 933 } | |
| 934 | |
| 935 /* Add finder patterns */ | |
| 936 qr_place_finder(grid, size, 0, 0); | |
| 937 qr_place_finder(grid, size, 0, size - 7); | |
| 938 qr_place_finder(grid, size, size - 7, 0); | |
| 939 | |
| 940 /* Add separators */ | |
| 941 for (i = 0; i < 7; i++) { | |
| 942 grid[(7 * size) + i] = 0x10; | |
| 943 grid[(i * size) + 7] = 0x10; | |
| 944 grid[(7 * size) + (size - 1 - i)] = 0x10; | |
| 945 grid[(i * size) + (size - 8)] = 0x10; | |
| 946 grid[((size - 8) * size) + i] = 0x10; | |
| 947 grid[((size - 1 - i) * size) + 7] = 0x10; | |
| 948 } | |
| 949 grid[(7 * size) + 7] = 0x10; | |
| 950 grid[(7 * size) + (size - 8)] = 0x10; | |
| 951 grid[((size - 8) * size) + 7] = 0x10; | |
| 952 | |
| 953 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 13 | |
| 954 #pragma GCC diagnostic pop | |
| 955 #endif | |
| 956 | |
| 957 /* Add alignment patterns */ | |
| 958 if (version != 1) { | |
| 959 /* Version 1 does not have alignment patterns */ | |
| 960 | |
| 961 int loopsize = qr_align_loopsize[version - 1]; | |
| 962 int x, y; | |
| 963 for (x = 0; x < loopsize; x++) { | |
| 964 for (y = 0; y < loopsize; y++) { | |
| 965 int xcoord = qr_table_e1[((version - 2) * 7) + x]; | |
| 966 int ycoord = qr_table_e1[((version - 2) * 7) + y]; | |
| 967 | |
| 968 if (!(grid[(ycoord * size) + xcoord] & 0x10)) { | |
| 969 qr_place_align(grid, size, xcoord, ycoord); | |
| 970 } | |
| 971 } | |
| 972 } | |
| 973 } | |
| 974 | |
| 975 /* Reserve space for format information */ | |
| 976 for (i = 0; i < 8; i++) { | |
| 977 grid[(8 * size) + i] |= 0x20; | |
| 978 grid[(i * size) + 8] |= 0x20; | |
| 979 grid[(8 * size) + (size - 1 - i)] = 0x20; | |
| 980 grid[((size - 1 - i) * size) + 8] = 0x20; | |
| 981 } | |
| 982 grid[(8 * size) + 8] |= 0x20; | |
| 983 grid[((size - 1 - 7) * size) + 8] = 0x21; /* Dark Module from Figure 25 */ | |
| 984 | |
| 985 /* Reserve space for version information */ | |
| 986 if (version >= 7) { | |
| 987 for (i = 0; i < 6; i++) { | |
| 988 grid[((size - 9) * size) + i] = 0x20; | |
| 989 grid[((size - 10) * size) + i] = 0x20; | |
| 990 grid[((size - 11) * size) + i] = 0x20; | |
| 991 grid[(i * size) + (size - 9)] = 0x20; | |
| 992 grid[(i * size) + (size - 10)] = 0x20; | |
| 993 grid[(i * size) + (size - 11)] = 0x20; | |
| 994 } | |
| 995 } | |
| 996 } | |
| 997 | |
| 998 static int qr_cwbit(const unsigned char *fullstream, const int i) { | |
| 999 | |
| 1000 if (fullstream[(i >> 3)] & (0x80 >> (i & 0x07))) { | |
| 1001 return 1; | |
| 1002 } | |
| 1003 | |
| 1004 return 0; | |
| 1005 } | |
| 1006 | |
| 1007 static void qr_populate_grid(unsigned char *grid, const int h_size, const int v_size, const unsigned char *fullstream, | |
| 1008 const int cw) { | |
| 1009 const int not_rmqr = v_size == h_size; | |
| 1010 const int x_start = h_size - (not_rmqr ? 2 : 3); /* For rMQR allow for righthand vertical timing pattern */ | |
| 1011 int direction = 1; /* up */ | |
| 1012 int row = 0; /* right hand side */ | |
| 1013 | |
| 1014 int i, n, y; | |
| 1015 | |
| 1016 n = cw * 8; | |
| 1017 y = v_size - 1; | |
| 1018 i = 0; | |
| 1019 while (i < n) { | |
| 1020 int x = x_start - (row * 2); | |
| 1021 int r = y * h_size; | |
| 1022 | |
| 1023 if ((x < 6) && (not_rmqr)) | |
| 1024 x--; /* skip over vertical timing pattern */ | |
| 1025 | |
| 1026 if (!(grid[r + (x + 1)] & 0xf0)) { | |
| 1027 grid[r + (x + 1)] = qr_cwbit(fullstream, i); | |
| 1028 i++; | |
| 1029 } | |
| 1030 | |
| 1031 if (i < n) { | |
| 1032 if (!(grid[r + x] & 0xf0)) { | |
| 1033 grid[r + x] = qr_cwbit(fullstream, i); | |
| 1034 i++; | |
| 1035 } | |
| 1036 } | |
| 1037 | |
| 1038 if (direction) { | |
| 1039 y--; | |
| 1040 if (y == -1) { | |
| 1041 /* reached the top */ | |
| 1042 row++; | |
| 1043 y = 0; | |
| 1044 direction = 0; | |
| 1045 } | |
| 1046 } else { | |
| 1047 y++; | |
| 1048 if (y == v_size) { | |
| 1049 /* reached the bottom */ | |
| 1050 row++; | |
| 1051 y = v_size - 1; | |
| 1052 direction = 1; | |
| 1053 } | |
| 1054 } | |
| 1055 } | |
| 1056 } | |
| 1057 | |
| 1058 #ifdef ZINTLOG | |
| 1059 static void append_log(const unsigned char log) { | |
| 1060 FILE *file; | |
| 1061 | |
| 1062 if ((file = fopen("zintlog.txt", "a+"))) { | |
| 1063 fprintf(file, "%02X", log); | |
| 1064 (void) fclose(file); | |
| 1065 } | |
| 1066 } | |
| 1067 | |
| 1068 static void write_log(const char log[]) { | |
| 1069 FILE *file; | |
| 1070 | |
| 1071 if ((file = fopen("zintlog.txt", "a+"))) { | |
| 1072 fprintf(file, "%s\n", log); /*writes*/ | |
| 1073 (void) fclose(file); | |
| 1074 } | |
| 1075 } | |
| 1076 #endif | |
| 1077 | |
| 1078 static int qr_evaluate(unsigned char *local, const int size) { | |
| 1079 static const unsigned char h1011101[7] = { 1, 0, 1, 1, 1, 0, 1 }; | |
| 1080 | |
| 1081 int x, y, r, k, block; | |
| 1082 int result = 0; | |
| 1083 char state; | |
| 1084 int dark_mods; | |
| 1085 double percentage; | |
| 1086 int a, b, afterCount, beforeCount; | |
| 1087 #ifdef ZINTLOG | |
| 1088 int result_b = 0; | |
| 1089 char str[15]; | |
| 1090 #endif | |
| 1091 | |
| 1092 /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warnings */ | |
| 1093 assert(size > 0); | |
| 1094 | |
| 1095 #ifdef ZINTLOG | |
| 1096 /* bitmask output */ | |
| 1097 for (y = 0; y < size; y++) { | |
| 1098 for (x = 0; x < size; x++) { | |
| 1099 append_log(local[(y * size) + x]); | |
| 1100 } | |
| 1101 write_log(""); | |
| 1102 } | |
| 1103 #endif | |
| 1104 | |
| 1105 /* Test 1: Adjacent modules in row/column in same colour */ | |
| 1106 /* Vertical */ | |
| 1107 for (x = 0; x < size; x++) { | |
| 1108 block = 0; | |
| 1109 state = 0; | |
| 1110 for (y = 0; y < size; y++) { | |
| 1111 if (local[(y * size) + x] == state) { | |
| 1112 block++; | |
| 1113 } else { | |
| 1114 if (block >= 5) { | |
| 1115 result += block - 2; | |
| 1116 } | |
| 1117 block = 1; | |
| 1118 state = local[(y * size) + x]; | |
| 1119 } | |
| 1120 } | |
| 1121 if (block >= 5) { | |
| 1122 result += block - 2; | |
| 1123 } | |
| 1124 } | |
| 1125 | |
| 1126 /* Horizontal */ | |
| 1127 dark_mods = 0; /* Count dark mods simultaneously (see Test 4 below) */ | |
| 1128 for (y = 0; y < size; y++) { | |
| 1129 r = y * size; | |
| 1130 block = 0; | |
| 1131 state = 0; | |
| 1132 for (x = 0; x < size; x++) { | |
| 1133 if (local[r + x] == state) { | |
| 1134 block++; | |
| 1135 } else { | |
| 1136 if (block >= 5) { | |
| 1137 result += block - 2; | |
| 1138 } | |
| 1139 block = 1; | |
| 1140 state = local[r + x]; | |
| 1141 } | |
| 1142 if (state) { | |
| 1143 dark_mods++; | |
| 1144 } | |
| 1145 } | |
| 1146 if (block >= 5) { | |
| 1147 result += block - 2; | |
| 1148 } | |
| 1149 } | |
| 1150 | |
| 1151 #ifdef ZINTLOG | |
| 1152 /* output Test 1 */ | |
| 1153 sprintf(str, "%d", result); | |
| 1154 result_b = result; | |
| 1155 write_log(str); | |
| 1156 #endif | |
| 1157 | |
| 1158 /* Test 2: Block of modules in same color */ | |
| 1159 for (x = 0; x < size - 1; x++) { | |
| 1160 for (y = 0; y < size - 1; y++) { | |
| 1161 k = local[(y * size) + x]; | |
| 1162 if (((k == local[((y + 1) * size) + x]) && | |
| 1163 (k == local[(y * size) + (x + 1)])) && | |
| 1164 (k == local[((y + 1) * size) + (x + 1)])) { | |
| 1165 result += 3; | |
| 1166 } | |
| 1167 } | |
| 1168 } | |
| 1169 | |
| 1170 #ifdef ZINTLOG | |
| 1171 /* output Test 2 */ | |
| 1172 sprintf(str, "%d", result - result_b); | |
| 1173 result_b = result; | |
| 1174 write_log(str); | |
| 1175 #endif | |
| 1176 | |
| 1177 /* Test 3: 1:1:3:1:1 ratio pattern in row/column */ | |
| 1178 /* Vertical */ | |
| 1179 for (x = 0; x < size; x++) { | |
| 1180 for (y = 0; y <= (size - 7); y++) { | |
| 1181 if (local[y * size + x] && !local[(y + 1) * size + x] && local[(y + 2) * size + x] && | |
| 1182 local[(y + 3) * size + x] && local[(y + 4) * size + x] && | |
| 1183 !local[(y + 5) * size + x] && local[(y + 6) * size + x]) { | |
| 1184 /* Pattern found, check before and after */ | |
| 1185 beforeCount = 0; | |
| 1186 for (b = (y - 1); b >= (y - 4); b--) { | |
| 1187 if (b < 0) { /* Count < edge as whitespace */ | |
| 1188 beforeCount = 4; | |
| 1189 break; | |
| 1190 } | |
| 1191 if (local[(b * size) + x]) { | |
| 1192 break; | |
| 1193 } | |
| 1194 beforeCount++; | |
| 1195 } | |
| 1196 if (beforeCount == 4) { | |
| 1197 /* Pattern is preceded by light area 4 modules wide */ | |
| 1198 result += 40; | |
| 1199 } else { | |
| 1200 afterCount = 0; | |
| 1201 for (a = (y + 7); a <= (y + 10); a++) { | |
| 1202 if (a >= size) { /* Count > edge as whitespace */ | |
| 1203 afterCount = 4; | |
| 1204 break; | |
| 1205 } | |
| 1206 if (local[(a * size) + x]) { | |
| 1207 break; | |
| 1208 } | |
| 1209 afterCount++; | |
| 1210 } | |
| 1211 if (afterCount == 4) { | |
| 1212 /* Pattern is followed by light area 4 modules wide */ | |
| 1213 result += 40; | |
| 1214 } | |
| 1215 } | |
| 1216 y += 3; /* Skip to next possible match */ | |
| 1217 } | |
| 1218 } | |
| 1219 } | |
| 1220 | |
| 1221 /* Horizontal */ | |
| 1222 for (y = 0; y < size; y++) { | |
| 1223 r = y * size; | |
| 1224 for (x = 0; x <= (size - 7); x++) { | |
| 1225 if (memcmp(local + r + x, h1011101, 7) == 0) { | |
| 1226 /* Pattern found, check before and after */ | |
| 1227 beforeCount = 0; | |
| 1228 for (b = (x - 1); b >= (x - 4); b--) { | |
| 1229 if (b < 0) { /* Count < edge as whitespace */ | |
| 1230 beforeCount = 4; | |
| 1231 break; | |
| 1232 } | |
| 1233 if (local[r + b]) { | |
| 1234 break; | |
| 1235 } | |
| 1236 beforeCount++; | |
| 1237 } | |
| 1238 | |
| 1239 if (beforeCount == 4) { | |
| 1240 /* Pattern is preceded by light area 4 modules wide */ | |
| 1241 result += 40; | |
| 1242 } else { | |
| 1243 afterCount = 0; | |
| 1244 for (a = (x + 7); a <= (x + 10); a++) { | |
| 1245 if (a >= size) { /* Count > edge as whitespace */ | |
| 1246 afterCount = 4; | |
| 1247 break; | |
| 1248 } | |
| 1249 if (local[r + a]) { | |
| 1250 break; | |
| 1251 } | |
| 1252 afterCount++; | |
| 1253 } | |
| 1254 if (afterCount == 4) { | |
| 1255 /* Pattern is followed by light area 4 modules wide */ | |
| 1256 result += 40; | |
| 1257 } | |
| 1258 } | |
| 1259 x += 3; /* Skip to next possible match */ | |
| 1260 } | |
| 1261 } | |
| 1262 } | |
| 1263 | |
| 1264 #ifdef ZINTLOG | |
| 1265 /* output Test 3 */ | |
| 1266 sprintf(str, "%d", result - result_b); | |
| 1267 result_b = result; | |
| 1268 write_log(str); | |
| 1269 #endif | |
| 1270 | |
| 1271 /* Test 4: Proportion of dark modules in entire symbol */ | |
| 1272 percentage = (100.0 * dark_mods) / (size * size); | |
| 1273 k = (int) (fabs(percentage - 50.0) / 5.0); | |
| 1274 | |
| 1275 result += 10 * k; | |
| 1276 | |
| 1277 #ifdef ZINTLOG | |
| 1278 /* output Test 4+summary */ | |
| 1279 sprintf(str, "%d", result - result_b); | |
| 1280 write_log(str); | |
| 1281 write_log("=========="); | |
| 1282 sprintf(str, "%d", result); | |
| 1283 write_log(str); | |
| 1284 #endif | |
| 1285 | |
| 1286 return result; | |
| 1287 } | |
| 1288 | |
| 1289 /* Add format information to grid */ | |
| 1290 static void qr_add_format_info(unsigned char *grid, const int size, const int ecc_level, const int pattern) { | |
| 1291 int format = pattern; | |
| 1292 unsigned int seq; | |
| 1293 int i; | |
| 1294 | |
| 1295 switch (ecc_level) { | |
| 1296 case QR_LEVEL_L: format |= 0x08; | |
| 1297 break; | |
| 1298 case QR_LEVEL_Q: format |= 0x18; | |
| 1299 break; | |
| 1300 case QR_LEVEL_H: format |= 0x10; | |
| 1301 break; | |
| 1302 } | |
| 1303 | |
| 1304 seq = qr_annex_c[format]; | |
| 1305 | |
| 1306 for (i = 0; i < 6; i++) { | |
| 1307 grid[(i * size) + 8] |= (seq >> i) & 0x01; | |
| 1308 } | |
| 1309 | |
| 1310 for (i = 0; i < 8; i++) { | |
| 1311 grid[(8 * size) + (size - i - 1)] |= (seq >> i) & 0x01; | |
| 1312 } | |
| 1313 | |
| 1314 for (i = 0; i < 6; i++) { | |
| 1315 grid[(8 * size) + (5 - i)] |= (seq >> (i + 9)) & 0x01; | |
| 1316 } | |
| 1317 | |
| 1318 for (i = 0; i < 7; i++) { | |
| 1319 grid[(((size - 7) + i) * size) + 8] |= (seq >> (i + 8)) & 0x01; | |
| 1320 } | |
| 1321 | |
| 1322 grid[(7 * size) + 8] |= (seq >> 6) & 0x01; | |
| 1323 grid[(8 * size) + 8] |= (seq >> 7) & 0x01; | |
| 1324 grid[(8 * size) + 7] |= (seq >> 8) & 0x01; | |
| 1325 } | |
| 1326 | |
| 1327 static int qr_apply_bitmask(unsigned char *grid, const int size, const int ecc_level, const int user_mask, | |
| 1328 const int fast_encode, const int debug_print) { | |
| 1329 int x, y; | |
| 1330 int r, k; | |
| 1331 int bit; | |
| 1332 int pattern, penalty[8]; | |
| 1333 int best_pattern; | |
| 1334 int size_squared = size * size; | |
| 1335 unsigned char *mask = (unsigned char *) z_alloca(size_squared); | |
| 1336 unsigned char *local = (unsigned char *) z_alloca(size_squared); | |
| 1337 #ifdef ZINTLOG | |
| 1338 char str[15]; | |
| 1339 #endif | |
| 1340 | |
| 1341 /* Perform data masking */ | |
| 1342 memset(mask, 0, size_squared); | |
| 1343 for (y = 0; y < size; y++) { | |
| 1344 r = y * size; | |
| 1345 for (x = 0; x < size; x++) { | |
| 1346 | |
| 1347 /* all eight bitmask variants are encoded in the 8 bits of the bytes that make up the mask array. */ | |
| 1348 if (!(grid[r + x] & 0xf0)) { /* exclude areas not to be masked. */ | |
| 1349 if (((y + x) & 1) == 0) { | |
| 1350 mask[r + x] |= 0x01; | |
| 1351 } | |
| 1352 if (!fast_encode) { | |
| 1353 if ((y & 1) == 0) { | |
| 1354 mask[r + x] |= 0x02; | |
| 1355 } | |
| 1356 } | |
| 1357 if ((x % 3) == 0) { | |
| 1358 mask[r + x] |= 0x04; | |
| 1359 } | |
| 1360 if (!fast_encode) { | |
| 1361 if (((y + x) % 3) == 0) { | |
| 1362 mask[r + x] |= 0x08; | |
| 1363 } | |
| 1364 } | |
| 1365 if ((((y / 2) + (x / 3)) & 1) == 0) { | |
| 1366 mask[r + x] |= 0x10; | |
| 1367 } | |
| 1368 if (!fast_encode) { | |
| 1369 if ((y * x) % 6 == 0) { /* Equivalent to (y * x) % 2 + (y * x) % 3 == 0 */ | |
| 1370 mask[r + x] |= 0x20; | |
| 1371 } | |
| 1372 if (((((y * x) & 1) + ((y * x) % 3)) & 1) == 0) { | |
| 1373 mask[r + x] |= 0x40; | |
| 1374 } | |
| 1375 } | |
| 1376 if (((((y + x) & 1) + ((y * x) % 3)) & 1) == 0) { | |
| 1377 mask[r + x] |= 0x80; | |
| 1378 } | |
| 1379 } | |
| 1380 } | |
| 1381 } | |
| 1382 | |
| 1383 if (user_mask) { | |
| 1384 best_pattern = user_mask - 1; | |
| 1385 } else { | |
| 1386 /* all eight bitmask variants have been encoded in the 8 bits of the bytes | |
| 1387 * that make up the mask array. select them for evaluation according to the | |
| 1388 * desired pattern.*/ | |
| 1389 best_pattern = 0; | |
| 1390 for (pattern = 0; pattern < 8; pattern++) { | |
| 1391 if (fast_encode && pattern != 0 && pattern != 2 && pattern != 4 && pattern != 7) { | |
| 1392 continue; | |
| 1393 } | |
| 1394 bit = 1 << pattern; | |
| 1395 for (k = 0; k < size_squared; k++) { | |
| 1396 if (mask[k] & bit) { | |
| 1397 local[k] = grid[k] ^ 0x01; | |
| 1398 } else { | |
| 1399 local[k] = grid[k] & 0x0f; | |
| 1400 } | |
| 1401 } | |
| 1402 qr_add_format_info(local, size, ecc_level, pattern); | |
| 1403 | |
| 1404 penalty[pattern] = qr_evaluate(local, size); | |
| 1405 | |
| 1406 if (penalty[pattern] < penalty[best_pattern]) { | |
| 1407 best_pattern = pattern; | |
| 1408 } | |
| 1409 } | |
| 1410 } | |
| 1411 | |
| 1412 if (debug_print) { | |
| 1413 printf("Mask: %d (%s)", best_pattern, user_mask ? "specified" : fast_encode ? "fast automatic": "automatic"); | |
| 1414 if (!user_mask) { | |
| 1415 if (fast_encode) { | |
| 1416 printf(" 0:%d 2:%d 4:%d 7:%d", penalty[0], penalty[2], penalty[4], penalty[7]); | |
| 1417 } else { | |
| 1418 for (pattern = 0; pattern < 8; pattern++) printf(" %d:%d", pattern, penalty[pattern]); | |
| 1419 } | |
| 1420 } | |
| 1421 fputc('\n', stdout); | |
| 1422 } | |
| 1423 | |
| 1424 #ifdef ZINTLOG | |
| 1425 sprintf(str, "%d", best_pattern); | |
| 1426 write_log("chose pattern:"); | |
| 1427 write_log(str); | |
| 1428 #endif | |
| 1429 | |
| 1430 /* Apply mask */ | |
| 1431 if (!user_mask && best_pattern == 7) { /* Reuse last */ | |
| 1432 memcpy(grid, local, size_squared); | |
| 1433 } else { | |
| 1434 bit = 1 << best_pattern; | |
| 1435 for (y = 0; y < size_squared; y++) { | |
| 1436 if (mask[y] & bit) { | |
| 1437 grid[y] ^= 0x01; | |
| 1438 } | |
| 1439 } | |
| 1440 } | |
| 1441 | |
| 1442 return best_pattern; | |
| 1443 } | |
| 1444 | |
| 1445 /* Add version information */ | |
| 1446 static void qr_add_version_info(unsigned char *grid, const int size, const int version) { | |
| 1447 int i; | |
| 1448 | |
| 1449 unsigned int version_data = qr_annex_d[version - 7]; | |
| 1450 for (i = 0; i < 6; i++) { | |
| 1451 grid[((size - 11) * size) + i] |= (version_data >> (i * 3)) & 1; | |
| 1452 grid[((size - 10) * size) + i] |= (version_data >> ((i * 3) + 1)) & 1; | |
| 1453 grid[((size - 9) * size) + i] |= (version_data >> ((i * 3) + 2)) & 1; | |
| 1454 grid[(i * size) + (size - 11)] |= (version_data >> (i * 3)) & 1; | |
| 1455 grid[(i * size) + (size - 10)] |= (version_data >> ((i * 3) + 1)) & 1; | |
| 1456 grid[(i * size) + (size - 9)] |= (version_data >> ((i * 3) + 2)) & 1; | |
| 1457 } | |
| 1458 } | |
| 1459 | |
| 1460 /* Find the length of the block starting from 'start' */ | |
| 1461 static int qr_blockLength(const int start, const char mode[], const int length) { | |
| 1462 int i; | |
| 1463 int count = 0; | |
| 1464 char start_mode = mode[start]; | |
| 1465 | |
| 1466 i = start; | |
| 1467 | |
| 1468 do { | |
| 1469 count++; | |
| 1470 } while (((i + count) < length) && (mode[i + count] == start_mode)); | |
| 1471 | |
| 1472 return count; | |
| 1473 } | |
| 1474 | |
| 1475 /* Calculate the actual bitlength of the proposed binary string */ | |
| 1476 static int qr_calc_binlen(const int version, char mode[], const unsigned int ddata[], const int length, | |
| 1477 const int mode_preset, const int gs1, const int eci, const int debug_print) { | |
| 1478 int i, j; | |
| 1479 char currentMode; | |
| 1480 int count = 0; | |
| 1481 int alphalength; | |
| 1482 int blocklength; | |
| 1483 | |
| 1484 if (!mode_preset) { | |
| 1485 qr_define_mode(mode, ddata, length, gs1, version, debug_print); | |
| 1486 } | |
| 1487 | |
| 1488 currentMode = ' '; /* Null */ | |
| 1489 | |
| 1490 if (eci != 0) { /* Not applicable to MICROQR */ | |
| 1491 count += 4; | |
| 1492 if (eci <= 127) { | |
| 1493 count += 8; | |
| 1494 } else if (eci <= 16383) { | |
| 1495 count += 16; | |
| 1496 } else { | |
| 1497 count += 24; | |
| 1498 } | |
| 1499 } | |
| 1500 | |
| 1501 for (i = 0; i < length; i++) { | |
| 1502 if (mode[i] != currentMode) { | |
| 1503 count += qr_mode_bits(version) + qr_cci_bits(version, mode[i]); | |
| 1504 blocklength = qr_blockLength(i, mode, length); | |
| 1505 switch (mode[i]) { | |
| 1506 case 'K': | |
| 1507 count += (blocklength * 13); | |
| 1508 break; | |
| 1509 case 'B': | |
| 1510 for (j = i; j < (i + blocklength); j++) { | |
| 1511 if (ddata[j] > 0xff) { | |
| 1512 count += 16; | |
| 1513 } else { | |
| 1514 count += 8; | |
| 1515 } | |
| 1516 } | |
| 1517 break; | |
| 1518 case 'A': | |
| 1519 alphalength = blocklength; | |
| 1520 if (gs1) { | |
| 1521 /* In alphanumeric mode % becomes %% */ | |
| 1522 for (j = i; j < (i + blocklength); j++) { | |
| 1523 if (ddata[j] == '%') { | |
| 1524 alphalength++; | |
| 1525 } | |
| 1526 } | |
| 1527 } | |
| 1528 switch (alphalength % 2) { | |
| 1529 case 0: | |
| 1530 count += (alphalength / 2) * 11; | |
| 1531 break; | |
| 1532 case 1: | |
| 1533 count += ((alphalength - 1) / 2) * 11; | |
| 1534 count += 6; | |
| 1535 break; | |
| 1536 } | |
| 1537 break; | |
| 1538 case 'N': | |
| 1539 switch (blocklength % 3) { | |
| 1540 case 0: | |
| 1541 count += (blocklength / 3) * 10; | |
| 1542 break; | |
| 1543 case 1: | |
| 1544 count += ((blocklength - 1) / 3) * 10; | |
| 1545 count += 4; | |
| 1546 break; | |
| 1547 case 2: | |
| 1548 count += ((blocklength - 2) / 3) * 10; | |
| 1549 count += 7; | |
| 1550 break; | |
| 1551 } | |
| 1552 break; | |
| 1553 } | |
| 1554 currentMode = mode[i]; | |
| 1555 } | |
| 1556 } | |
| 1557 | |
| 1558 return count; | |
| 1559 } | |
| 1560 | |
| 1561 /* Call `qr_calc_binlen()` on each segment */ | |
| 1562 static int qr_calc_binlen_segs(const int version, char mode[], const unsigned int ddata[], | |
| 1563 const struct zint_seg segs[], const int seg_count, const struct zint_structapp *p_structapp, | |
| 1564 const int mode_preset, const int gs1, const int debug_print) { | |
| 1565 int i; | |
| 1566 int count = 0; | |
| 1567 const unsigned int *dd = ddata; | |
| 1568 char *m = mode; | |
| 1569 | |
| 1570 if (p_structapp) { | |
| 1571 count += 4 + 8 + 8; | |
| 1572 } | |
| 1573 | |
| 1574 if (gs1) { /* Not applicable to MICROQR */ | |
| 1575 if (version < RMQR_VERSION) { | |
| 1576 count += 4; | |
| 1577 } else { | |
| 1578 count += 3; | |
| 1579 } | |
| 1580 } | |
| 1581 | |
| 1582 for (i = 0; i < seg_count; i++) { | |
| 1583 count += qr_calc_binlen(version, m, dd, segs[i].length, mode_preset, gs1, segs[i].eci, debug_print); | |
| 1584 m += segs[i].length; | |
| 1585 dd += segs[i].length; | |
| 1586 } | |
| 1587 | |
| 1588 if (debug_print) { | |
| 1589 printf("Estimated Binary Length: %d (version %d, gs1 %d)\n", count, version, gs1); | |
| 1590 } | |
| 1591 | |
| 1592 return count; | |
| 1593 } | |
| 1594 | |
| 1595 /* Helper to process source data into `ddata` array */ | |
| 1596 static int qr_prep_data(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count, | |
| 1597 unsigned int ddata[]) { | |
| 1598 int warn_number = 0; | |
| 1599 int i; | |
| 1600 /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for non-Shift JIS in UNICODE_MODE */ | |
| 1601 const int full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; | |
| 1602 | |
| 1603 if ((symbol->input_mode & 0x07) == DATA_MODE) { | |
| 1604 sjis_cpy_segs(segs, seg_count, ddata, full_multibyte); | |
| 1605 } else { | |
| 1606 unsigned int *dd = ddata; | |
| 1607 for (i = 0; i < seg_count; i++) { | |
| 1608 int done = 0; | |
| 1609 if (segs[i].eci != 20 || seg_count > 1) { /* Unless ECI 20 (Shift JIS) or have multiple segments */ | |
| 1610 /* Try other encodings (ECI 0 defaults to ISO/IEC 8859-1) */ | |
| 1611 int error_number = sjis_utf8_to_eci(segs[i].eci, segs[i].source, &segs[i].length, dd, full_multibyte); | |
| 1612 if (error_number == 0) { | |
| 1613 done = 1; | |
| 1614 } else if (segs[i].eci || seg_count > 1) { | |
| 1615 return errtxtf(error_number, symbol, 575, "Invalid character in input for ECI '%d'", segs[i].eci); | |
| 1616 } | |
| 1617 } | |
| 1618 if (!done) { | |
| 1619 /* Try Shift-JIS */ | |
| 1620 int error_number = sjis_utf8(symbol, segs[i].source, &segs[i].length, dd); | |
| 1621 if (error_number != 0) { | |
| 1622 return error_number; | |
| 1623 } | |
| 1624 if (segs[i].eci != 20) { | |
| 1625 warn_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 760, | |
| 1626 "Converted to Shift JIS but no ECI specified"); | |
| 1627 } | |
| 1628 } | |
| 1629 dd += segs[i].length; | |
| 1630 } | |
| 1631 } | |
| 1632 | |
| 1633 return warn_number; | |
| 1634 } | |
| 1635 | |
| 1636 INTERNAL int qrcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { | |
| 1637 int warn_number; | |
| 1638 int i, j, est_binlen, prev_est_binlen; | |
| 1639 int ecc_level, autosize, version, max_cw, target_codewords, blocks, size; | |
| 1640 int bitmask; | |
| 1641 int user_mask; | |
| 1642 int canShrink; | |
| 1643 int size_squared; | |
| 1644 const struct zint_structapp *p_structapp = NULL; | |
| 1645 const int gs1 = ((symbol->input_mode & 0x07) == GS1_MODE); | |
| 1646 const int fast_encode = symbol->input_mode & FAST_MODE; | |
| 1647 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 1648 const int eci_length_segs = get_eci_length_segs(segs, seg_count); | |
| 1649 struct zint_seg *local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * seg_count); | |
| 1650 unsigned int *ddata = (unsigned int *) z_alloca(sizeof(unsigned int) * eci_length_segs); | |
| 1651 char *mode = (char *) z_alloca(eci_length_segs); | |
| 1652 char *prev_mode = (char *) z_alloca(eci_length_segs); | |
| 1653 unsigned char *datastream; | |
| 1654 unsigned char *fullstream; | |
| 1655 unsigned char *grid; | |
| 1656 | |
| 1657 user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 8 */ | |
| 1658 if (user_mask > 8) { | |
| 1659 user_mask = 0; /* Ignore */ | |
| 1660 } | |
| 1661 | |
| 1662 segs_cpy(symbol, segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs & protect lengths) */ | |
| 1663 | |
| 1664 warn_number = qr_prep_data(symbol, local_segs, seg_count, ddata); | |
| 1665 if (warn_number >= ZINT_ERROR) { | |
| 1666 return warn_number; | |
| 1667 } | |
| 1668 | |
| 1669 if (symbol->structapp.count) { | |
| 1670 if (symbol->structapp.count < 2 || symbol->structapp.count > 16) { | |
| 1671 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 750, | |
| 1672 "Structured Append count '%d' out of range (2 to 16)", symbol->structapp.count); | |
| 1673 } | |
| 1674 if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) { | |
| 1675 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 751, | |
| 1676 "Structured Append index '%1$d' out of range (1 to count %2$d)", | |
| 1677 symbol->structapp.index, symbol->structapp.count); | |
| 1678 } | |
| 1679 if (symbol->structapp.id[0]) { | |
| 1680 int id, id_len; | |
| 1681 | |
| 1682 for (id_len = 1; id_len < 4 && symbol->structapp.id[id_len]; id_len++); | |
| 1683 | |
| 1684 if (id_len > 3) { /* Max value 255 */ | |
| 1685 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 752, | |
| 1686 "Structured Append ID length %d too long (3 digit maximum)", id_len); | |
| 1687 } | |
| 1688 | |
| 1689 id = to_int((const unsigned char *) symbol->structapp.id, id_len); | |
| 1690 if (id == -1) { | |
| 1691 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 753, "Invalid Structured Append ID (digits only)"); | |
| 1692 } | |
| 1693 if (id > 255) { | |
| 1694 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 754, | |
| 1695 "Structured Append ID value '%d' out of range (0 to 255)", id); | |
| 1696 } | |
| 1697 } | |
| 1698 p_structapp = &symbol->structapp; | |
| 1699 } | |
| 1700 | |
| 1701 /* GS1 General Specifications 22.0 section 5.7.3 says Structured Append and ECIs not supported | |
| 1702 for GS1 QR Code so check and return ZINT_WARN_NONCOMPLIANT if either true */ | |
| 1703 if (gs1 && warn_number == 0) { | |
| 1704 for (i = 0; i < seg_count; i++) { | |
| 1705 if (local_segs[i].eci) { | |
| 1706 warn_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 755, | |
| 1707 "Using ECI in GS1 mode not supported by GS1 standards"); | |
| 1708 break; | |
| 1709 } | |
| 1710 } | |
| 1711 if (warn_number == 0 && p_structapp) { | |
| 1712 warn_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 756, | |
| 1713 "Using Structured Append in GS1 mode not supported by GS1 standards"); | |
| 1714 } | |
| 1715 } | |
| 1716 | |
| 1717 est_binlen = qr_calc_binlen_segs(40, mode, ddata, local_segs, seg_count, p_structapp, 0 /*mode_preset*/, gs1, | |
| 1718 debug_print); | |
| 1719 | |
| 1720 if ((symbol->option_1 >= 1) && (symbol->option_1 <= 4)) { | |
| 1721 ecc_level = symbol->option_1 - 1; | |
| 1722 } else { | |
| 1723 ecc_level = QR_LEVEL_L; | |
| 1724 } | |
| 1725 max_cw = qr_data_codewords[ecc_level][39]; | |
| 1726 | |
| 1727 if (est_binlen > (8 * max_cw)) { | |
| 1728 if (ecc_level == QR_LEVEL_L) { | |
| 1729 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 567, "Input too long, requires %1$d codewords (maximum %2$d)", | |
| 1730 (est_binlen + 7) / 8, max_cw); | |
| 1731 } | |
| 1732 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 561, | |
| 1733 "Input too long for ECC level %1$c, requires %2$d codewords (maximum %3$d)", | |
| 1734 qr_ecc_level_names[ecc_level], (est_binlen + 7) / 8, max_cw); | |
| 1735 } | |
| 1736 | |
| 1737 autosize = 40; | |
| 1738 for (i = 39; i >= 0; i--) { | |
| 1739 if ((8 * qr_data_codewords[ecc_level][i]) >= est_binlen) { | |
| 1740 autosize = i + 1; | |
| 1741 } | |
| 1742 } | |
| 1743 if (autosize != 40) { | |
| 1744 /* Save version 40 estimate in case incorrect costings in `qr_define_mode()` lead to its `mode` being better | |
| 1745 than current lower version one */ | |
| 1746 prev_est_binlen = est_binlen; | |
| 1747 est_binlen = qr_calc_binlen_segs(autosize, mode, ddata, local_segs, seg_count, p_structapp, 0 /*mode_preset*/, | |
| 1748 gs1, debug_print); | |
| 1749 if (prev_est_binlen < est_binlen) { /* Shouldn't happen */ | |
| 1750 assert(0); /* Not reached (hopefully) */ | |
| 1751 /* Defensively use version 40 `mode` to avoid crashes (ticket #300) */ | |
| 1752 est_binlen = qr_calc_binlen_segs(40, mode, ddata, local_segs, seg_count, p_structapp, 0 /*mode_preset*/, | |
| 1753 gs1, debug_print); | |
| 1754 assert(est_binlen == prev_est_binlen); | |
| 1755 } | |
| 1756 } | |
| 1757 | |
| 1758 /* Now see if the optimised binary will fit in a smaller symbol. */ | |
| 1759 canShrink = 1; | |
| 1760 | |
| 1761 do { | |
| 1762 if (autosize == 1) { | |
| 1763 canShrink = 0; | |
| 1764 } else { | |
| 1765 prev_est_binlen = est_binlen; | |
| 1766 memcpy(prev_mode, mode, eci_length_segs); | |
| 1767 est_binlen = qr_calc_binlen_segs(autosize - 1, mode, ddata, local_segs, seg_count, p_structapp, | |
| 1768 0 /*mode_preset*/, gs1, debug_print); | |
| 1769 | |
| 1770 if ((8 * qr_data_codewords[ecc_level][autosize - 2]) < est_binlen) { | |
| 1771 canShrink = 0; | |
| 1772 } | |
| 1773 | |
| 1774 if (canShrink == 1) { | |
| 1775 /* Optimisation worked - data will fit in a smaller symbol */ | |
| 1776 autosize--; | |
| 1777 } else { | |
| 1778 /* Data did not fit in the smaller symbol, revert to original size */ | |
| 1779 est_binlen = prev_est_binlen; | |
| 1780 memcpy(mode, prev_mode, eci_length_segs); | |
| 1781 } | |
| 1782 } | |
| 1783 } while (canShrink == 1); | |
| 1784 | |
| 1785 version = autosize; | |
| 1786 | |
| 1787 if ((symbol->option_2 >= 1) && (symbol->option_2 <= 40)) { | |
| 1788 /* If the user has selected a larger symbol than the smallest available, | |
| 1789 then use the size the user has selected, and re-optimise for this | |
| 1790 symbol size. | |
| 1791 */ | |
| 1792 if (symbol->option_2 > version) { | |
| 1793 version = symbol->option_2; | |
| 1794 est_binlen = qr_calc_binlen_segs(symbol->option_2, mode, ddata, local_segs, seg_count, p_structapp, | |
| 1795 0 /*mode_preset*/, gs1, debug_print); | |
| 1796 } | |
| 1797 | |
| 1798 if (symbol->option_2 < version) { | |
| 1799 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 569, | |
| 1800 "Input too long for Version %1$d-%2$c, requires %3$d codewords (maximum %4$d)", | |
| 1801 symbol->option_2, qr_ecc_level_names[ecc_level], (est_binlen + 7) / 8, | |
| 1802 qr_data_codewords[ecc_level][symbol->option_2 - 1]); | |
| 1803 } | |
| 1804 } | |
| 1805 | |
| 1806 /* Ensure maxium error correction capacity unless user-specified */ | |
| 1807 if (symbol->option_1 == -1 || symbol->option_1 - 1 != ecc_level) { | |
| 1808 if (est_binlen <= qr_data_codewords[QR_LEVEL_H][version - 1] * 8) { | |
| 1809 ecc_level = QR_LEVEL_H; | |
| 1810 } else if (est_binlen <= qr_data_codewords[QR_LEVEL_Q][version - 1] * 8) { | |
| 1811 ecc_level = QR_LEVEL_Q; | |
| 1812 } else if (est_binlen <= qr_data_codewords[QR_LEVEL_M][version - 1] * 8) { | |
| 1813 ecc_level = QR_LEVEL_M; | |
| 1814 } | |
| 1815 } | |
| 1816 | |
| 1817 target_codewords = qr_data_codewords[ecc_level][version - 1]; | |
| 1818 blocks = qr_blocks[ecc_level][version - 1]; | |
| 1819 | |
| 1820 if (debug_print) { | |
| 1821 printf("Minimum codewords: %d\n", (est_binlen + 7) / 8); | |
| 1822 printf("Selected version: %d-%c (%dx%d)\n", | |
| 1823 version, qr_ecc_level_names[ecc_level], qr_sizes[version - 1], qr_sizes[version - 1]); | |
| 1824 printf("Number of data codewords in symbol: %d\n", target_codewords); | |
| 1825 printf("Number of ECC blocks: %d\n", blocks); | |
| 1826 } | |
| 1827 | |
| 1828 datastream = (unsigned char *) z_alloca(target_codewords + 1); | |
| 1829 fullstream = (unsigned char *) z_alloca(qr_total_codewords[version - 1] + 1); | |
| 1830 | |
| 1831 (void) qr_binary_segs(datastream, version, target_codewords, mode, ddata, local_segs, seg_count, p_structapp, gs1, | |
| 1832 est_binlen, debug_print); | |
| 1833 #ifdef ZINT_TEST | |
| 1834 if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); | |
| 1835 #endif | |
| 1836 qr_add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); | |
| 1837 | |
| 1838 size = qr_sizes[version - 1]; | |
| 1839 size_squared = size * size; | |
| 1840 | |
| 1841 grid = (unsigned char *) z_alloca(size_squared); | |
| 1842 memset(grid, 0, size_squared); | |
| 1843 | |
| 1844 qr_setup_grid(grid, size, version); | |
| 1845 qr_populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); | |
| 1846 | |
| 1847 if (version >= 7) { | |
| 1848 qr_add_version_info(grid, size, version); | |
| 1849 } | |
| 1850 | |
| 1851 bitmask = qr_apply_bitmask(grid, size, ecc_level, user_mask, fast_encode, debug_print); | |
| 1852 | |
| 1853 qr_add_format_info(grid, size, ecc_level, bitmask); | |
| 1854 | |
| 1855 symbol->width = size; | |
| 1856 symbol->rows = size; | |
| 1857 | |
| 1858 for (i = 0; i < size; i++) { | |
| 1859 int r = i * size; | |
| 1860 for (j = 0; j < size; j++) { | |
| 1861 if (grid[r + j] & 0x01) { | |
| 1862 set_module(symbol, i, j); | |
| 1863 } | |
| 1864 } | |
| 1865 symbol->row_height[i] = 1; | |
| 1866 } | |
| 1867 symbol->height = size; | |
| 1868 | |
| 1869 return warn_number; | |
| 1870 } | |
| 1871 | |
| 1872 /* Write terminator, padding & ECC */ | |
| 1873 static int microqr_end(struct zint_symbol *symbol, char binary_data[], int bp, const int ecc_level, | |
| 1874 const int version) { | |
| 1875 int i, j; | |
| 1876 int bits_left; | |
| 1877 unsigned char data_blocks[17]; | |
| 1878 unsigned char ecc_blocks[15]; | |
| 1879 rs_t rs; | |
| 1880 | |
| 1881 const int terminator_bits = qr_terminator_bits(MICROQR_VERSION + version); | |
| 1882 const int bits_total = microqr_data[ecc_level][version][0]; | |
| 1883 const int data_codewords = microqr_data[ecc_level][version][1]; | |
| 1884 const int ecc_codewords = microqr_data[ecc_level][version][2]; | |
| 1885 const int bits_end = version == 0 || version == 2 ? 4 : 8; | |
| 1886 | |
| 1887 /* Add terminator */ | |
| 1888 bits_left = bits_total - bp; | |
| 1889 if (bits_left <= terminator_bits) { | |
| 1890 if (bits_left) { | |
| 1891 bp = bin_append_posn(0, bits_left, binary_data, bp); | |
| 1892 bits_left = 0; | |
| 1893 } | |
| 1894 } else { | |
| 1895 bp = bin_append_posn(0, terminator_bits, binary_data, bp); | |
| 1896 bits_left -= terminator_bits; | |
| 1897 } | |
| 1898 | |
| 1899 if (symbol->debug & ZINT_DEBUG_PRINT) { | |
| 1900 printf("M%d Terminated binary (%d): %.*s (bits_left %d)\n", version + 1, bp, bp, binary_data, bits_left); | |
| 1901 } | |
| 1902 | |
| 1903 /* Manage last (4-bit) block */ | |
| 1904 if (bits_end == 4 && bits_left && bits_left <= 4) { | |
| 1905 bp = bin_append_posn(0, bits_left, binary_data, bp); | |
| 1906 bits_left = 0; | |
| 1907 } | |
| 1908 | |
| 1909 if (bits_left) { | |
| 1910 /* Complete current byte */ | |
| 1911 int remainder = 8 - (bp % 8); | |
| 1912 if (remainder != 8) { | |
| 1913 bp = bin_append_posn(0, remainder, binary_data, bp); | |
| 1914 bits_left -= remainder; | |
| 1915 } | |
| 1916 | |
| 1917 /* Add padding */ | |
| 1918 if (bits_end == 4 && bits_left > 4) { | |
| 1919 bits_left -= 4; | |
| 1920 } | |
| 1921 remainder = bits_left / 8; | |
| 1922 for (i = 0; i < remainder; i++) { | |
| 1923 bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp); | |
| 1924 } | |
| 1925 if (bits_end == 4) { | |
| 1926 bp = bin_append_posn(0, 4, binary_data, bp); | |
| 1927 } | |
| 1928 } | |
| 1929 assert((bp & 0x07) == 8 - bits_end); | |
| 1930 | |
| 1931 /* Copy data into codewords */ | |
| 1932 for (i = 0; i < data_codewords; i++) { | |
| 1933 const int bits = i + 1 == data_codewords ? bits_end : 8; | |
| 1934 data_blocks[i] = 0; | |
| 1935 | |
| 1936 for (j = 0; j < bits; j++) { | |
| 1937 if (binary_data[(i * 8) + j] == '1') { | |
| 1938 data_blocks[i] |= 0x80 >> j; | |
| 1939 } | |
| 1940 } | |
| 1941 } | |
| 1942 #ifdef ZINT_TEST | |
| 1943 if (symbol->debug & ZINT_DEBUG_TEST) { | |
| 1944 char bp_buf[10]; | |
| 1945 debug_test_codeword_dump(symbol, data_blocks, data_codewords); | |
| 1946 sprintf(bp_buf, "%d", bp); /* Append `bp` to detect padding errors */ | |
| 1947 errtxt_adj(0, symbol, "%s (%s)", bp_buf); | |
| 1948 } | |
| 1949 #endif | |
| 1950 | |
| 1951 /* Calculate Reed-Solomon error codewords */ | |
| 1952 rs_init_gf(&rs, 0x11d); | |
| 1953 rs_init_code(&rs, ecc_codewords, 0); | |
| 1954 rs_encode(&rs, data_codewords, data_blocks, ecc_blocks); | |
| 1955 | |
| 1956 /* Add Reed-Solomon codewords to binary data */ | |
| 1957 for (i = 0; i < ecc_codewords; i++) { | |
| 1958 bp = bin_append_posn(ecc_blocks[i], 8, binary_data, bp); | |
| 1959 } | |
| 1960 | |
| 1961 return bp; | |
| 1962 } | |
| 1963 | |
| 1964 static void microqr_setup_grid(unsigned char *grid, const int size) { | |
| 1965 int i, toggle = 1; | |
| 1966 | |
| 1967 /* Add timing patterns */ | |
| 1968 for (i = 0; i < size; i++) { | |
| 1969 if (toggle == 1) { | |
| 1970 grid[i] = 0x21; | |
| 1971 grid[(i * size)] = 0x21; | |
| 1972 toggle = 0; | |
| 1973 } else { | |
| 1974 grid[i] = 0x20; | |
| 1975 grid[(i * size)] = 0x20; | |
| 1976 toggle = 1; | |
| 1977 } | |
| 1978 } | |
| 1979 | |
| 1980 /* Add finder patterns */ | |
| 1981 qr_place_finder(grid, size, 0, 0); | |
| 1982 | |
| 1983 /* Add separators */ | |
| 1984 for (i = 0; i < 7; i++) { | |
| 1985 grid[(7 * size) + i] = 0x10; | |
| 1986 grid[(i * size) + 7] = 0x10; | |
| 1987 } | |
| 1988 grid[(7 * size) + 7] = 0x10; | |
| 1989 | |
| 1990 | |
| 1991 /* Reserve space for format information */ | |
| 1992 for (i = 0; i < 8; i++) { | |
| 1993 grid[(8 * size) + i] |= 0x20; | |
| 1994 grid[(i * size) + 8] |= 0x20; | |
| 1995 } | |
| 1996 grid[(8 * size) + 8] |= 20; | |
| 1997 } | |
| 1998 | |
| 1999 static void microqr_populate_grid(unsigned char *grid, const int size, const char full_stream[], int bp) { | |
| 2000 int direction = 1; /* up */ | |
| 2001 int row = 0; /* right hand side */ | |
| 2002 int i; | |
| 2003 int y; | |
| 2004 | |
| 2005 y = size - 1; | |
| 2006 i = 0; | |
| 2007 do { | |
| 2008 int x = (size - 2) - (row * 2); | |
| 2009 | |
| 2010 if (!(grid[(y * size) + (x + 1)] & 0xf0)) { | |
| 2011 if (full_stream[i] == '1') { | |
| 2012 grid[(y * size) + (x + 1)] = 0x01; | |
| 2013 } else { | |
| 2014 grid[(y * size) + (x + 1)] = 0x00; | |
| 2015 } | |
| 2016 i++; | |
| 2017 } | |
| 2018 | |
| 2019 if (i < bp) { | |
| 2020 if (!(grid[(y * size) + x] & 0xf0)) { | |
| 2021 if (full_stream[i] == '1') { | |
| 2022 grid[(y * size) + x] = 0x01; | |
| 2023 } else { | |
| 2024 grid[(y * size) + x] = 0x00; | |
| 2025 } | |
| 2026 i++; | |
| 2027 } | |
| 2028 } | |
| 2029 | |
| 2030 if (direction) { | |
| 2031 y--; | |
| 2032 } else { | |
| 2033 y++; | |
| 2034 } | |
| 2035 if (y == 0) { | |
| 2036 /* reached the top */ | |
| 2037 row++; | |
| 2038 y = 1; | |
| 2039 direction = 0; | |
| 2040 } | |
| 2041 if (y == size) { | |
| 2042 /* reached the bottom */ | |
| 2043 row++; | |
| 2044 y = size - 1; | |
| 2045 direction = 1; | |
| 2046 } | |
| 2047 } while (i < bp); | |
| 2048 } | |
| 2049 | |
| 2050 static int microqr_evaluate(const unsigned char *grid, const int size, const int pattern) { | |
| 2051 int sum1, sum2, i, filter = 0, retval; | |
| 2052 | |
| 2053 switch (pattern) { | |
| 2054 case 0: filter = 0x01; | |
| 2055 break; | |
| 2056 case 1: filter = 0x02; | |
| 2057 break; | |
| 2058 case 2: filter = 0x04; | |
| 2059 break; | |
| 2060 case 3: filter = 0x08; | |
| 2061 break; | |
| 2062 } | |
| 2063 | |
| 2064 sum1 = 0; | |
| 2065 sum2 = 0; | |
| 2066 for (i = 1; i < size; i++) { | |
| 2067 if (grid[(i * size) + size - 1] & filter) { | |
| 2068 sum1++; | |
| 2069 } | |
| 2070 if (grid[((size - 1) * size) + i] & filter) { | |
| 2071 sum2++; | |
| 2072 } | |
| 2073 } | |
| 2074 | |
| 2075 if (sum1 <= sum2) { | |
| 2076 retval = (sum1 * 16) + sum2; | |
| 2077 } else { | |
| 2078 retval = (sum2 * 16) + sum1; | |
| 2079 } | |
| 2080 | |
| 2081 return retval; | |
| 2082 } | |
| 2083 | |
| 2084 static int microqr_apply_bitmask(unsigned char *grid, const int size, const int user_mask, const int debug_print) { | |
| 2085 int x, y; | |
| 2086 int r, k; | |
| 2087 int bit; | |
| 2088 int pattern, value[4]; | |
| 2089 int best_pattern; | |
| 2090 int size_squared = size * size; | |
| 2091 unsigned char *mask = (unsigned char *) z_alloca(size_squared); | |
| 2092 unsigned char *eval = (unsigned char *) z_alloca(size_squared); | |
| 2093 | |
| 2094 /* Perform data masking */ | |
| 2095 memset(mask, 0, size_squared); | |
| 2096 for (y = 0; y < size; y++) { | |
| 2097 r = y * size; | |
| 2098 for (x = 0; x < size; x++) { | |
| 2099 | |
| 2100 if (!(grid[r + x] & 0xf0)) { | |
| 2101 if ((y & 1) == 0) { | |
| 2102 mask[r + x] |= 0x01; | |
| 2103 } | |
| 2104 | |
| 2105 if ((((y / 2) + (x / 3)) & 1) == 0) { | |
| 2106 mask[r + x] |= 0x02; | |
| 2107 } | |
| 2108 | |
| 2109 if (((((y * x) & 1) + ((y * x) % 3)) & 1) == 0) { | |
| 2110 mask[r + x] |= 0x04; | |
| 2111 } | |
| 2112 | |
| 2113 if (((((y + x) & 1) + ((y * x) % 3)) & 1) == 0) { | |
| 2114 mask[r + x] |= 0x08; | |
| 2115 } | |
| 2116 } | |
| 2117 } | |
| 2118 } | |
| 2119 | |
| 2120 if (user_mask) { | |
| 2121 best_pattern = user_mask - 1; | |
| 2122 } else { | |
| 2123 for (k = 0; k < size_squared; k++) { | |
| 2124 if (grid[k] & 0x01) { | |
| 2125 eval[k] = mask[k] ^ 0xff; | |
| 2126 } else { | |
| 2127 eval[k] = mask[k]; | |
| 2128 } | |
| 2129 } | |
| 2130 | |
| 2131 | |
| 2132 /* Evaluate result */ | |
| 2133 best_pattern = 0; | |
| 2134 for (pattern = 0; pattern < 4; pattern++) { | |
| 2135 value[pattern] = microqr_evaluate(eval, size, pattern); | |
| 2136 if (value[pattern] > value[best_pattern]) { | |
| 2137 best_pattern = pattern; | |
| 2138 } | |
| 2139 } | |
| 2140 } | |
| 2141 | |
| 2142 if (debug_print) { | |
| 2143 printf("Mask: %d (%s)", best_pattern, user_mask ? "specified" : "automatic"); | |
| 2144 if (!user_mask) { | |
| 2145 for (pattern = 0; pattern < 4; pattern++) printf(" %d:%d", pattern, value[pattern]); | |
| 2146 } | |
| 2147 fputc('\n', stdout); | |
| 2148 } | |
| 2149 | |
| 2150 /* Apply mask */ | |
| 2151 bit = 1 << best_pattern; | |
| 2152 for (k = 0; k < size_squared; k++) { | |
| 2153 if (mask[k] & bit) { | |
| 2154 grid[k] ^= 0x01; | |
| 2155 } | |
| 2156 } | |
| 2157 | |
| 2158 return best_pattern; | |
| 2159 } | |
| 2160 | |
| 2161 INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length) { | |
| 2162 int i, size, j; | |
| 2163 char full_stream[200]; | |
| 2164 int bp; | |
| 2165 int full_multibyte; | |
| 2166 int user_mask; | |
| 2167 | |
| 2168 unsigned int ddata[40]; | |
| 2169 char mode[40]; | |
| 2170 int alpha_used = 0, byte_or_kanji_used = 0; | |
| 2171 int version_valid[4]; | |
| 2172 int binary_count[4]; | |
| 2173 int ecc_level, version; | |
| 2174 int bitmask, format, format_full; | |
| 2175 int size_squared; | |
| 2176 struct zint_seg segs[1]; | |
| 2177 const int seg_count = 1; | |
| 2178 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 2179 unsigned char *grid; | |
| 2180 | |
| 2181 if (length > 35) { | |
| 2182 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 562, "Input length %d too long (maximum 35)", length); | |
| 2183 } | |
| 2184 | |
| 2185 /* Check option 1 in combination with option 2 */ | |
| 2186 ecc_level = QR_LEVEL_L; | |
| 2187 if (symbol->option_1 >= 1 && symbol->option_1 <= 4) { | |
| 2188 if (symbol->option_1 == 4) { | |
| 2189 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 566, "Error correction level H not available"); | |
| 2190 } | |
| 2191 if (symbol->option_2 >= 1 && symbol->option_2 <= 4) { | |
| 2192 if (symbol->option_2 == 1 && symbol->option_1 != 1) { | |
| 2193 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 574, | |
| 2194 "Version M1 supports error correction level L only"); | |
| 2195 } | |
| 2196 if (symbol->option_2 != 4 && symbol->option_1 == 3) { | |
| 2197 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 563, "Error correction level Q requires Version M4"); | |
| 2198 } | |
| 2199 } | |
| 2200 ecc_level = symbol->option_1 - 1; | |
| 2201 } | |
| 2202 | |
| 2203 /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for non-Shift JIS in UNICODE_MODE */ | |
| 2204 full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; | |
| 2205 user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 4 */ | |
| 2206 if (user_mask > 4) { | |
| 2207 user_mask = 0; /* Ignore */ | |
| 2208 } | |
| 2209 | |
| 2210 if ((symbol->input_mode & 0x07) == DATA_MODE) { | |
| 2211 sjis_cpy(source, &length, ddata, full_multibyte); | |
| 2212 } else { | |
| 2213 /* Try ISO 8859-1 conversion first */ | |
| 2214 int error_number = sjis_utf8_to_eci(3, source, &length, ddata, full_multibyte); | |
| 2215 if (error_number != 0) { | |
| 2216 /* Try Shift-JIS */ | |
| 2217 error_number = sjis_utf8(symbol, source, &length, ddata); | |
| 2218 if (error_number != 0) { | |
| 2219 return error_number; | |
| 2220 } | |
| 2221 } | |
| 2222 } | |
| 2223 | |
| 2224 /* Determine if alpha (excluding numerics), byte or kanji used */ | |
| 2225 for (i = 0; i < length && (alpha_used == 0 || byte_or_kanji_used == 0); i++) { | |
| 2226 if (!z_isdigit(ddata[i])) { | |
| 2227 if (qr_is_alpha(ddata[i], 0 /*gs1*/)) { | |
| 2228 alpha_used = 1; | |
| 2229 } else { | |
| 2230 byte_or_kanji_used = 1; | |
| 2231 } | |
| 2232 } | |
| 2233 } | |
| 2234 | |
| 2235 for (i = 0; i < 4; i++) { | |
| 2236 version_valid[i] = 1; | |
| 2237 } | |
| 2238 | |
| 2239 /* Eliminate possible versions depending on type of content */ | |
| 2240 if (byte_or_kanji_used) { | |
| 2241 version_valid[0] = 0; | |
| 2242 version_valid[1] = 0; | |
| 2243 } else if (alpha_used) { | |
| 2244 version_valid[0] = 0; | |
| 2245 } | |
| 2246 | |
| 2247 /* Eliminate possible versions depending on error correction level specified */ | |
| 2248 if (ecc_level == QR_LEVEL_Q) { | |
| 2249 version_valid[0] = 0; | |
| 2250 version_valid[1] = 0; | |
| 2251 version_valid[2] = 0; | |
| 2252 } else if (ecc_level == QR_LEVEL_M) { | |
| 2253 version_valid[0] = 0; | |
| 2254 } | |
| 2255 | |
| 2256 segs[0].source = source; | |
| 2257 segs[0].length = length; | |
| 2258 segs[0].eci = 0; | |
| 2259 | |
| 2260 /* Determine length of binary data */ | |
| 2261 for (i = 0; i < 4; i++) { | |
| 2262 if (version_valid[i]) { | |
| 2263 binary_count[i] = qr_calc_binlen_segs(MICROQR_VERSION + i, mode, ddata, segs, seg_count, | |
| 2264 NULL /*p_structapp*/, 0 /*mode_preset*/, 0 /*gs1*/, debug_print); | |
| 2265 } else { | |
| 2266 binary_count[i] = 128 + 1; | |
| 2267 } | |
| 2268 } | |
| 2269 | |
| 2270 /* Eliminate possible versions depending on binary length and error correction level specified */ | |
| 2271 if (binary_count[3] > microqr_data[ecc_level][3][0]) { | |
| 2272 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 565, | |
| 2273 "Input too long for Version M4-%1$c, requires %2$d codewords (maximum %3$d)", | |
| 2274 qr_ecc_level_names[ecc_level], (binary_count[3] + 7) / 8, microqr_data[ecc_level][3][1]); | |
| 2275 } | |
| 2276 for (i = 0; i < 3; i++) { | |
| 2277 if (binary_count[i] > microqr_data[ecc_level][i][0]) { | |
| 2278 version_valid[i] = 0; | |
| 2279 } | |
| 2280 } | |
| 2281 | |
| 2282 /* Auto-select lowest valid size */ | |
| 2283 version = 3; | |
| 2284 if (version_valid[2]) { | |
| 2285 version = 2; | |
| 2286 } | |
| 2287 if (version_valid[1]) { | |
| 2288 version = 1; | |
| 2289 } | |
| 2290 if (version_valid[0]) { | |
| 2291 version = 0; | |
| 2292 } | |
| 2293 | |
| 2294 /* Get version from user */ | |
| 2295 if ((symbol->option_2 >= 1) && (symbol->option_2 <= 4)) { | |
| 2296 if (symbol->option_2 == 1 && (i = not_sane(NEON_F, source, length))) { | |
| 2297 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 758, | |
| 2298 "Invalid character at position %d in input for Version M1 (digits only)", i); | |
| 2299 } else if (symbol->option_2 == 2 && not_sane(QR_ALPHA, source, length)) { | |
| 2300 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 759, | |
| 2301 "Invalid character in input for Version M2 (digits, A-Z, space and \"$%*+-./:\" only)"); | |
| 2302 } | |
| 2303 if (symbol->option_2 - 1 >= version) { | |
| 2304 version = symbol->option_2 - 1; | |
| 2305 } else { | |
| 2306 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 570, | |
| 2307 "Input too long for Version M%1$d-%2$c, requires %3$d codewords (maximum %4$d)", | |
| 2308 symbol->option_2, qr_ecc_level_names[ecc_level], (binary_count[version] + 7) / 8, | |
| 2309 microqr_data[ecc_level][symbol->option_2 - 1][1]); | |
| 2310 } | |
| 2311 } | |
| 2312 | |
| 2313 /* If there is enough unused space then increase the error correction level, unless user-specified */ | |
| 2314 if (version && (symbol->option_1 == -1 || symbol->option_1 - 1 != ecc_level)) { | |
| 2315 if (binary_count[version] <= microqr_data[QR_LEVEL_Q][version][0]) { | |
| 2316 ecc_level = QR_LEVEL_Q; | |
| 2317 } else if (binary_count[version] <= microqr_data[QR_LEVEL_M][version][0]) { | |
| 2318 ecc_level = QR_LEVEL_M; | |
| 2319 } | |
| 2320 } | |
| 2321 | |
| 2322 qr_define_mode(mode, ddata, length, 0 /*gs1*/, MICROQR_VERSION + version, debug_print); | |
| 2323 | |
| 2324 bp = qr_binary_segs((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, ddata, | |
| 2325 segs, seg_count, NULL /*p_structapp*/, 0 /*gs1*/, binary_count[version], debug_print); | |
| 2326 | |
| 2327 if (debug_print) printf("Binary (%d): %.*s\n", bp, bp, full_stream); | |
| 2328 | |
| 2329 bp = microqr_end(symbol, full_stream, bp, ecc_level, version); | |
| 2330 | |
| 2331 size = microqr_sizes[version]; | |
| 2332 size_squared = size * size; | |
| 2333 | |
| 2334 grid = (unsigned char *) z_alloca(size_squared); | |
| 2335 memset(grid, 0, size_squared); | |
| 2336 | |
| 2337 microqr_setup_grid(grid, size); | |
| 2338 microqr_populate_grid(grid, size, full_stream, bp); | |
| 2339 bitmask = microqr_apply_bitmask(grid, size, user_mask, debug_print); | |
| 2340 | |
| 2341 /* Add format data */ | |
| 2342 format = version ? (version - 1) * 2 + ecc_level + 1 : 0; | |
| 2343 | |
| 2344 if (debug_print) { | |
| 2345 printf("Version: M%d-%c, Size: %dx%d, Format: %d\n", | |
| 2346 version + 1, qr_ecc_level_names[ecc_level], size, size, format); | |
| 2347 } | |
| 2348 | |
| 2349 format_full = qr_annex_c1[(format << 2) + bitmask]; | |
| 2350 | |
| 2351 for (i = 1; i <= 8; i++) { | |
| 2352 grid[(8 * size) + i] |= (format_full >> (15 - i)) & 0x01; | |
| 2353 } | |
| 2354 for (i = 7; i >= 1; i--) { | |
| 2355 grid[(i * size) + 8] |= (format_full >> (i - 1)) & 0x01; | |
| 2356 } | |
| 2357 | |
| 2358 symbol->width = size; | |
| 2359 symbol->rows = size; | |
| 2360 | |
| 2361 for (i = 0; i < size; i++) { | |
| 2362 for (j = 0; j < size; j++) { | |
| 2363 if (grid[(i * size) + j] & 0x01) { | |
| 2364 set_module(symbol, i, j); | |
| 2365 } | |
| 2366 } | |
| 2367 symbol->row_height[i] = 1; | |
| 2368 } | |
| 2369 symbol->height = size; | |
| 2370 | |
| 2371 return 0; | |
| 2372 } | |
| 2373 | |
| 2374 /* For UPNQR the symbol size and error correction capacity is fixed */ | |
| 2375 INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int length) { | |
| 2376 int i, j, r, est_binlen; | |
| 2377 int ecc_level, version, target_codewords, blocks, size; | |
| 2378 int bitmask, error_number; | |
| 2379 int user_mask; | |
| 2380 int size_squared; | |
| 2381 struct zint_seg segs[1]; | |
| 2382 const int seg_count = 1; | |
| 2383 const int fast_encode = symbol->input_mode & FAST_MODE; | |
| 2384 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 2385 unsigned char *datastream; | |
| 2386 unsigned char *fullstream; | |
| 2387 unsigned char *grid; | |
| 2388 unsigned int *ddata = (unsigned int *) z_alloca(sizeof(unsigned int) * length); | |
| 2389 char *mode = (char *) z_alloca(length + 1); | |
| 2390 unsigned char *preprocessed = (unsigned char *) z_alloca(length + 1); | |
| 2391 | |
| 2392 symbol->eci = 4; /* Set before any processing */ | |
| 2393 | |
| 2394 user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 8 */ | |
| 2395 if (user_mask > 8) { | |
| 2396 user_mask = 0; /* Ignore */ | |
| 2397 } | |
| 2398 | |
| 2399 switch (symbol->input_mode & 0x07) { | |
| 2400 case DATA_MODE: | |
| 2401 /* Input is already in ISO-8859-2 format */ | |
| 2402 for (i = 0; i < length; i++) { | |
| 2403 ddata[i] = source[i]; | |
| 2404 mode[i] = 'B'; | |
| 2405 } | |
| 2406 break; | |
| 2407 case GS1_MODE: /* Should never happen as checked before being called */ | |
| 2408 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 571, | |
| 2409 "UPNQR does not support GS1 data"); /* Not reached */ | |
| 2410 break; | |
| 2411 case UNICODE_MODE: | |
| 2412 error_number = utf8_to_eci(4, source, preprocessed, &length); | |
| 2413 if (error_number != 0) { | |
| 2414 return errtxt(error_number, symbol, 572, "Invalid character in input for ECI '4'"); | |
| 2415 } | |
| 2416 for (i = 0; i < length; i++) { | |
| 2417 ddata[i] = preprocessed[i]; | |
| 2418 mode[i] = 'B'; | |
| 2419 } | |
| 2420 break; | |
| 2421 } | |
| 2422 | |
| 2423 segs[0].source = source; | |
| 2424 segs[0].length = length; | |
| 2425 segs[0].eci = 4; | |
| 2426 | |
| 2427 est_binlen = qr_calc_binlen_segs(15, mode, ddata, segs, seg_count, NULL /*p_structapp*/, 1 /*mode_preset*/, | |
| 2428 0 /*gs1*/, debug_print); | |
| 2429 | |
| 2430 ecc_level = QR_LEVEL_M; | |
| 2431 | |
| 2432 if (est_binlen > 3320) { | |
| 2433 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 573, "Input too long, requires %d codewords (maximum 415)", | |
| 2434 (est_binlen + 7) / 8); | |
| 2435 } | |
| 2436 | |
| 2437 version = 15; /* 77 x 77 */ | |
| 2438 | |
| 2439 target_codewords = qr_data_codewords[ecc_level][version - 1]; | |
| 2440 blocks = qr_blocks[ecc_level][version - 1]; | |
| 2441 | |
| 2442 datastream = (unsigned char *) z_alloca(target_codewords + 1); | |
| 2443 fullstream = (unsigned char *) z_alloca(qr_total_codewords[version - 1] + 1); | |
| 2444 | |
| 2445 (void) qr_binary_segs(datastream, version, target_codewords, mode, ddata, segs, seg_count, NULL /*p_structapp*/, | |
| 2446 0 /*gs1*/, est_binlen, debug_print); | |
| 2447 #ifdef ZINT_TEST | |
| 2448 if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); | |
| 2449 #endif | |
| 2450 qr_add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); | |
| 2451 | |
| 2452 size = qr_sizes[version - 1]; | |
| 2453 size_squared = size * size; | |
| 2454 | |
| 2455 grid = (unsigned char *) z_alloca(size_squared); | |
| 2456 memset(grid, 0, size_squared); | |
| 2457 | |
| 2458 qr_setup_grid(grid, size, version); | |
| 2459 qr_populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); | |
| 2460 | |
| 2461 qr_add_version_info(grid, size, version); | |
| 2462 | |
| 2463 bitmask = qr_apply_bitmask(grid, size, ecc_level, user_mask, fast_encode, debug_print); | |
| 2464 | |
| 2465 qr_add_format_info(grid, size, ecc_level, bitmask); | |
| 2466 | |
| 2467 symbol->width = size; | |
| 2468 symbol->rows = size; | |
| 2469 | |
| 2470 for (i = 0; i < size; i++) { | |
| 2471 r = i * size; | |
| 2472 for (j = 0; j < size; j++) { | |
| 2473 if (grid[r + j] & 0x01) { | |
| 2474 set_module(symbol, i, j); | |
| 2475 } | |
| 2476 } | |
| 2477 symbol->row_height[i] = 1; | |
| 2478 } | |
| 2479 symbol->height = size; | |
| 2480 | |
| 2481 return 0; | |
| 2482 } | |
| 2483 | |
| 2484 static const char rmqr_version_names[38][8] = { | |
| 2485 "R7x43", "R7x59", "R7x77", "R7x99", "R7x139", "R9x43", "R9x59", "R9x77", | |
| 2486 "R9x99", "R9x139", "R11x27", "R11x43", "R11x59", "R11x77", "R11x99", "R11x139", | |
| 2487 "R13x27", "R13x43", "R13x59", "R13x77", "R13x99", "R13x139", "R15x43", "R15x59", | |
| 2488 "R15x77", "R15x99", "R15x139", "R17x43", "R17x59", "R17x77", "R17x99", "R17x139", | |
| 2489 "R7xW", "R9xW", "R11xW", "R13xW", "R15xW", "R17xW", | |
| 2490 }; | |
| 2491 | |
| 2492 static void rmqr_setup_grid(unsigned char *grid, const int h_size, const int v_size) { | |
| 2493 int i, j; | |
| 2494 char alignment[] = {0x1F, 0x11, 0x15, 0x11, 0x1F}; | |
| 2495 int h_version, finder_position; | |
| 2496 | |
| 2497 /* Add timing patterns - top and bottom */ | |
| 2498 for (i = 0; i < h_size; i++) { | |
| 2499 if (i % 2) { | |
| 2500 grid[i] = 0x20; | |
| 2501 grid[((v_size - 1) * h_size) + i] = 0x20; | |
| 2502 } else { | |
| 2503 grid[i] = 0x21; | |
| 2504 grid[((v_size - 1) * h_size) + i] = 0x21; | |
| 2505 } | |
| 2506 } | |
| 2507 | |
| 2508 /* Add timing patterns - left and right */ | |
| 2509 for (i = 0; i < v_size; i++) { | |
| 2510 if (i % 2) { | |
| 2511 grid[i * h_size] = 0x20; | |
| 2512 grid[(i * h_size) + (h_size - 1)] = 0x20; | |
| 2513 } else { | |
| 2514 grid[i * h_size] = 0x21; | |
| 2515 grid[(i * h_size) + (h_size - 1)] = 0x21; | |
| 2516 } | |
| 2517 } | |
| 2518 | |
| 2519 /* Add finder pattern */ | |
| 2520 qr_place_finder(grid, h_size, 0, 0); /* This works because finder is always top left */ | |
| 2521 | |
| 2522 /* Add finder sub-pattern to bottom right */ | |
| 2523 for (i = 0; i < 5; i++) { | |
| 2524 for (j = 0; j < 5; j++) { | |
| 2525 if (alignment[j] & 0x10 >> i) { | |
| 2526 grid[((v_size - 5) * h_size) + (h_size * i) + (h_size - 5) + j] = 0x11; | |
| 2527 } else { | |
| 2528 grid[((v_size - 5) * h_size) + (h_size * i) + (h_size - 5) + j] = 0x10; | |
| 2529 } | |
| 2530 } | |
| 2531 } | |
| 2532 | |
| 2533 /* Add corner finder pattern - bottom left */ | |
| 2534 grid[(v_size - 2) * h_size] = 0x11; | |
| 2535 grid[((v_size - 2) * h_size) + 1] = 0x10; | |
| 2536 grid[((v_size - 1) * h_size) + 1] = 0x11; | |
| 2537 | |
| 2538 /* Add corner finder pattern - top right */ | |
| 2539 grid[h_size - 2] = 0x11; | |
| 2540 grid[(h_size * 2) - 2] = 0x10; | |
| 2541 grid[(h_size * 2) - 1] = 0x11; | |
| 2542 | |
| 2543 /* Add seperator */ | |
| 2544 for (i = 0; i < 7; i++) { | |
| 2545 grid[(i * h_size) + 7] = 0x20; | |
| 2546 } | |
| 2547 if (v_size > 7) { | |
| 2548 /* Note for v_size = 9 this overrides the bottom right corner finder pattern */ | |
| 2549 for (i = 0; i < 8; i++) { | |
| 2550 grid[(7 * h_size) + i] = 0x20; | |
| 2551 } | |
| 2552 } | |
| 2553 | |
| 2554 /* Add alignment patterns */ | |
| 2555 if (h_size > 27) { | |
| 2556 h_version = 0; /* Suppress compiler warning [-Wmaybe-uninitialized] */ | |
| 2557 for (i = 0; i < 5; i++) { | |
| 2558 if (h_size == rmqr_width[i]) { | |
| 2559 h_version = i; | |
| 2560 break; | |
| 2561 } | |
| 2562 } | |
| 2563 | |
| 2564 for (i = 0; i < 4; i++) { | |
| 2565 finder_position = rmqr_table_d1[(h_version * 4) + i]; | |
| 2566 | |
| 2567 if (finder_position != 0) { | |
| 2568 for (j = 0; j < v_size; j++) { | |
| 2569 if (j % 2) { | |
| 2570 grid[(j * h_size) + finder_position] = 0x10; | |
| 2571 } else { | |
| 2572 grid[(j * h_size) + finder_position] = 0x11; | |
| 2573 } | |
| 2574 } | |
| 2575 | |
| 2576 /* Top square */ | |
| 2577 grid[h_size + finder_position - 1] = 0x11; | |
| 2578 grid[(h_size * 2) + finder_position - 1] = 0x11; | |
| 2579 grid[h_size + finder_position + 1] = 0x11; | |
| 2580 grid[(h_size * 2) + finder_position + 1] = 0x11; | |
| 2581 | |
| 2582 /* Bottom square */ | |
| 2583 grid[(h_size * (v_size - 3)) + finder_position - 1] = 0x11; | |
| 2584 grid[(h_size * (v_size - 2)) + finder_position - 1] = 0x11; | |
| 2585 grid[(h_size * (v_size - 3)) + finder_position + 1] = 0x11; | |
| 2586 grid[(h_size * (v_size - 2)) + finder_position + 1] = 0x11; | |
| 2587 } | |
| 2588 } | |
| 2589 } | |
| 2590 | |
| 2591 /* Reserve space for format information */ | |
| 2592 for (i = 0; i < 5; i++) { | |
| 2593 for (j = 0; j < 3; j++) { | |
| 2594 grid[(h_size * (i + 1)) + j + 8] = 0x20; | |
| 2595 grid[(h_size * (v_size - 6)) + (h_size * i) + j + (h_size - 8)] = 0x20; | |
| 2596 } | |
| 2597 } | |
| 2598 grid[(h_size * 1) + 11] = 0x20; | |
| 2599 grid[(h_size * 2) + 11] = 0x20; | |
| 2600 grid[(h_size * 3) + 11] = 0x20; | |
| 2601 grid[(h_size * (v_size - 6)) + (h_size - 5)] = 0x20; | |
| 2602 grid[(h_size * (v_size - 6)) + (h_size - 4)] = 0x20; | |
| 2603 grid[(h_size * (v_size - 6)) + (h_size - 3)] = 0x20; | |
| 2604 } | |
| 2605 | |
| 2606 /* rMQR according to 2018 draft standard */ | |
| 2607 INTERNAL int rmqr(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { | |
| 2608 int warn_number; | |
| 2609 int i, j, est_binlen; | |
| 2610 int ecc_level, autosize, version, max_cw, target_codewords, blocks, h_size, v_size; | |
| 2611 int footprint, best_footprint, format_data; | |
| 2612 unsigned int left_format_info, right_format_info; | |
| 2613 const int gs1 = ((symbol->input_mode & 0x07) == GS1_MODE); | |
| 2614 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 2615 const int eci_length_segs = get_eci_length_segs(segs, seg_count); | |
| 2616 struct zint_seg *local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * seg_count); | |
| 2617 unsigned int *ddata = (unsigned int *) z_alloca(sizeof(unsigned int) * eci_length_segs); | |
| 2618 char *mode = (char *) z_alloca(eci_length_segs); | |
| 2619 unsigned char *datastream; | |
| 2620 unsigned char *fullstream; | |
| 2621 unsigned char *grid; | |
| 2622 | |
| 2623 if (symbol->option_1 == 1) { | |
| 2624 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 576, "Error correction level L not available in rMQR"); | |
| 2625 } | |
| 2626 if (symbol->option_1 == 3) { | |
| 2627 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 577, "Error correction level Q not available in rMQR"); | |
| 2628 } | |
| 2629 | |
| 2630 if ((symbol->option_2 < 0) || (symbol->option_2 > 38)) { | |
| 2631 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 579, "Version '%d' out of range (1 to 38)", | |
| 2632 symbol->option_2); | |
| 2633 } | |
| 2634 | |
| 2635 segs_cpy(symbol, segs, seg_count, local_segs); | |
| 2636 | |
| 2637 warn_number = qr_prep_data(symbol, local_segs, seg_count, ddata); | |
| 2638 if (warn_number >= ZINT_ERROR) { | |
| 2639 return warn_number; | |
| 2640 } | |
| 2641 | |
| 2642 /* GS1 General Specifications 22.0 section 5.7.3 says ECIs not supported | |
| 2643 for GS1 QR Code so check and return ZINT_WARN_NONCOMPLIANT if true */ | |
| 2644 if (gs1 && warn_number == 0) { | |
| 2645 for (i = 0; i < seg_count; i++) { | |
| 2646 if (local_segs[i].eci) { | |
| 2647 warn_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 757, | |
| 2648 "Using ECI in GS1 mode not supported by GS1 standards"); | |
| 2649 break; | |
| 2650 } | |
| 2651 } | |
| 2652 } | |
| 2653 | |
| 2654 est_binlen = qr_calc_binlen_segs(RMQR_VERSION + 31, mode, ddata, local_segs, seg_count, NULL /*p_structapp*/, | |
| 2655 0 /*mode_preset*/, gs1, debug_print); | |
| 2656 | |
| 2657 ecc_level = symbol->option_1 == 4 ? QR_LEVEL_H : QR_LEVEL_M; | |
| 2658 max_cw = rmqr_data_codewords[ecc_level >> 1][31]; | |
| 2659 | |
| 2660 if (est_binlen > (8 * max_cw)) { | |
| 2661 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 578, | |
| 2662 "Input too long for ECC level %1$c, requires %2$d codewords (maximum %3$d)", | |
| 2663 qr_ecc_level_names[ecc_level], (est_binlen + 7) / 8, max_cw); | |
| 2664 } | |
| 2665 | |
| 2666 version = 31; /* Set default to keep compiler happy */ | |
| 2667 | |
| 2668 if (symbol->option_2 == 0) { | |
| 2669 /* Automatic symbol size */ | |
| 2670 autosize = 31; | |
| 2671 best_footprint = rmqr_height[31] * rmqr_width[31]; | |
| 2672 for (version = 30; version >= 0; version--) { | |
| 2673 est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, | |
| 2674 NULL /*p_structapp*/, 0 /*mode_preset*/, gs1, debug_print); | |
| 2675 footprint = rmqr_height[version] * rmqr_width[version]; | |
| 2676 if (8 * rmqr_data_codewords[ecc_level >> 1][version] >= est_binlen) { | |
| 2677 if (footprint < best_footprint) { | |
| 2678 autosize = version; | |
| 2679 best_footprint = footprint; | |
| 2680 } | |
| 2681 } | |
| 2682 } | |
| 2683 version = autosize; | |
| 2684 est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, | |
| 2685 NULL /*p_structapp*/, 0 /*mode_preset*/, gs1, debug_print); | |
| 2686 } | |
| 2687 | |
| 2688 if ((symbol->option_2 >= 1) && (symbol->option_2 <= 32)) { | |
| 2689 /* User specified symbol size */ | |
| 2690 version = symbol->option_2 - 1; | |
| 2691 est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, | |
| 2692 NULL /*p_structapp*/, 0 /*mode_preset*/, gs1, debug_print); | |
| 2693 } | |
| 2694 | |
| 2695 if (symbol->option_2 >= 33) { | |
| 2696 /* User has specified symbol height only */ | |
| 2697 version = rmqr_fixed_height_upper_bound[symbol->option_2 - 32]; | |
| 2698 for (i = version - 1; i > rmqr_fixed_height_upper_bound[symbol->option_2 - 33]; i--) { | |
| 2699 est_binlen = qr_calc_binlen_segs(RMQR_VERSION + i, mode, ddata, local_segs, seg_count, | |
| 2700 NULL /*p_structapp*/, 0 /*mode_preset*/, gs1, debug_print); | |
| 2701 if (8 * rmqr_data_codewords[ecc_level >> 1][i] >= est_binlen) { | |
| 2702 version = i; | |
| 2703 } | |
| 2704 } | |
| 2705 est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, | |
| 2706 NULL /*p_structapp*/, 0 /*mode_preset*/, gs1, debug_print); | |
| 2707 } | |
| 2708 | |
| 2709 if (symbol->option_1 == -1) { | |
| 2710 /* Detect if there is enough free space to increase ECC level */ | |
| 2711 if (est_binlen < rmqr_data_codewords[QR_LEVEL_H >> 1][version] * 8) { | |
| 2712 ecc_level = QR_LEVEL_H; | |
| 2713 } | |
| 2714 } | |
| 2715 | |
| 2716 target_codewords = rmqr_data_codewords[ecc_level >> 1][version]; | |
| 2717 blocks = rmqr_blocks[ecc_level >> 1][version]; | |
| 2718 | |
| 2719 if (est_binlen > (target_codewords * 8)) { | |
| 2720 /* User has selected a symbol too small for the data */ | |
| 2721 assert(symbol->option_2 > 0); | |
| 2722 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 560, | |
| 2723 "Input too long for Version %1$d %2$s-%3$c, requires %4$d codewords (maximum %5$d)", | |
| 2724 symbol->option_2, rmqr_version_names[symbol->option_2 - 1], qr_ecc_level_names[ecc_level], | |
| 2725 (est_binlen + 7) / 8, target_codewords); | |
| 2726 } | |
| 2727 | |
| 2728 if (debug_print) { | |
| 2729 printf("Minimum codewords: %d\n", (est_binlen + 7) / 8); | |
| 2730 printf("Selected version: %d = R%dx%d-%c\n", | |
| 2731 (version + 1), rmqr_height[version], rmqr_width[version], qr_ecc_level_names[ecc_level]); | |
| 2732 printf("Number of data codewords in symbol: %d\n", target_codewords); | |
| 2733 printf("Number of ECC blocks: %d\n", blocks); | |
| 2734 } | |
| 2735 | |
| 2736 datastream = (unsigned char *) z_alloca(target_codewords + 1); | |
| 2737 fullstream = (unsigned char *) z_alloca(rmqr_total_codewords[version] + 1); | |
| 2738 | |
| 2739 (void) qr_binary_segs(datastream, RMQR_VERSION + version, target_codewords, mode, ddata, local_segs, seg_count, | |
| 2740 NULL /*p_structapp*/, gs1, est_binlen, debug_print); | |
| 2741 #ifdef ZINT_TEST | |
| 2742 if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); | |
| 2743 #endif | |
| 2744 qr_add_ecc(fullstream, datastream, RMQR_VERSION + version, target_codewords, blocks, debug_print); | |
| 2745 | |
| 2746 h_size = rmqr_width[version]; | |
| 2747 v_size = rmqr_height[version]; | |
| 2748 | |
| 2749 grid = (unsigned char *) z_alloca(h_size * v_size); | |
| 2750 memset(grid, 0, h_size * v_size); | |
| 2751 | |
| 2752 rmqr_setup_grid(grid, h_size, v_size); | |
| 2753 qr_populate_grid(grid, h_size, v_size, fullstream, rmqr_total_codewords[version]); | |
| 2754 | |
| 2755 /* apply bitmask */ | |
| 2756 for (i = 0; i < v_size; i++) { | |
| 2757 int r = i * h_size; | |
| 2758 for (j = 0; j < h_size; j++) { | |
| 2759 if ((grid[r + j] & 0xf0) == 0) { | |
| 2760 /* This is a data module */ | |
| 2761 if (((i / 2) + (j / 3)) % 2 == 0) { /* < This is the data mask from section 7.8.2 */ | |
| 2762 /* This module needs to be changed */ | |
| 2763 grid[r + j] ^= 0x01; | |
| 2764 } | |
| 2765 } | |
| 2766 } | |
| 2767 } | |
| 2768 | |
| 2769 /* add format information */ | |
| 2770 format_data = version; | |
| 2771 if (ecc_level == QR_LEVEL_H) { | |
| 2772 format_data += 32; | |
| 2773 } | |
| 2774 left_format_info = rmqr_format_info_left[format_data]; | |
| 2775 right_format_info = rmqr_format_info_right[format_data]; | |
| 2776 | |
| 2777 for (i = 0; i < 5; i++) { | |
| 2778 for (j = 0; j < 3; j++) { | |
| 2779 grid[(h_size * (i + 1)) + j + 8] = (left_format_info >> ((j * 5) + i)) & 0x01; | |
| 2780 grid[(h_size * (v_size - 6)) + (h_size * i) + j + (h_size - 8)] | |
| 2781 = (right_format_info >> ((j * 5) + i)) & 0x01; | |
| 2782 } | |
| 2783 } | |
| 2784 grid[(h_size * 1) + 11] = (left_format_info >> 15) & 0x01; | |
| 2785 grid[(h_size * 2) + 11] = (left_format_info >> 16) & 0x01; | |
| 2786 grid[(h_size * 3) + 11] = (left_format_info >> 17) & 0x01; | |
| 2787 grid[(h_size * (v_size - 6)) + (h_size - 5)] = (right_format_info >> 15) & 0x01; | |
| 2788 grid[(h_size * (v_size - 6)) + (h_size - 4)] = (right_format_info >> 16) & 0x01; | |
| 2789 grid[(h_size * (v_size - 6)) + (h_size - 3)] = (right_format_info >> 17) & 0x01; | |
| 2790 | |
| 2791 symbol->width = h_size; | |
| 2792 symbol->rows = v_size; | |
| 2793 | |
| 2794 for (i = 0; i < v_size; i++) { | |
| 2795 int r = i * h_size; | |
| 2796 for (j = 0; j < h_size; j++) { | |
| 2797 if (grid[r + j] & 0x01) { | |
| 2798 set_module(symbol, i, j); | |
| 2799 } | |
| 2800 } | |
| 2801 symbol->row_height[i] = 1; | |
| 2802 } | |
| 2803 symbol->height = v_size; | |
| 2804 | |
| 2805 return warn_number; | |
| 2806 } | |
| 2807 | |
| 2808 /* vim: set ts=4 sw=4 et : */ |
