RMQR: add ECI support; GUI/CLI: fix dev version test

This commit is contained in:
gitlost 2021-08-20 16:50:39 +01:00
parent 62cc9e49f5
commit 67b2a9c99d
9 changed files with 446 additions and 152 deletions

View file

@ -47,6 +47,8 @@
#define LEVEL_Q 3
#define LEVEL_H 4
static const char ecc_level_names[] = { 'L', 'M', 'Q', 'H' };
#define QR_PERCENT 38 /* Alphanumeric mode % */
#define RMQR_VERSION 41
@ -417,7 +419,7 @@ static void qr_binary(unsigned char datastream[], const int version, const int t
}
}
if (eci != 0) { /* Not applicable to RMQR or MICROQR */
if (eci != 0) { /* Not applicable to MICROQR */
bp = bin_append_posn(7, 4, binary, bp); /* ECI (Table 4) */
if (eci <= 127) {
bp = bin_append_posn(eci, 8, binary, bp); /* 000000 to 000127 */
@ -695,6 +697,8 @@ static void qr_binary(unsigned char datastream[], const int version, const int t
(void) bin_append_posn(0, padbits, binary, bp); /* Last use so not setting bp */
}
if (debug_print) printf("Terminated binary (%d): %.*s (padbits %d)\n", bp, bp, binary, padbits);
/* Put data into 8-bit codewords */
for (i = 0; i < current_bytes; i++) {
int p;
@ -1721,6 +1725,14 @@ INTERNAL int qr_code(struct zint_symbol *symbol, unsigned char source[], int len
break;
}
if (debug_print) {
printf("Minimum codewords: %d\n", (est_binlen + 7) / 8);
printf("Selected version: %d-%c (%dx%d)\n",
version, ecc_level_names[ecc_level - 1], qr_sizes[version - 1], qr_sizes[version - 1]);
printf("Number of data codewords in symbol: %d\n", target_codewords);
printf("Number of ECC blocks: %d\n", blocks);
}
#ifndef _MSC_VER
unsigned char datastream[target_codewords + 1];
unsigned char fullstream[qr_total_codewords[version - 1] + 1];
@ -2399,7 +2411,7 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len
return ZINT_ERROR_INVALID_OPTION;
}
if (symbol->option_2 != 4 && symbol->option_1 == 3) {
strcpy(symbol->errtxt, "575: Error correction level Q requires Version M4");
strcpy(symbol->errtxt, "563: Error correction level Q requires Version M4");
return ZINT_ERROR_INVALID_OPTION;
}
}
@ -2604,7 +2616,8 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len
}
if (debug_print) {
printf("Version: M%d, Size: %dx%d, ECC: %d, Format %d\n", version + 1, size, size, ecc_level, format);
printf("Version: M%d-%c, Size: %dx%d, Format: %d\n",
version + 1, ecc_level_names[ecc_level - 1], size, size, format);
}
format_full = qr_annex_c1[(format << 2) + bitmask];
@ -2909,16 +2922,17 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
int footprint, best_footprint, format_data;
unsigned int left_format_info, right_format_info;
int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
int eci_length = get_eci_length(symbol->eci, source, length);
#ifndef _MSC_VER
unsigned int jisdata[length + 1];
char mode[length + 1];
unsigned int jisdata[eci_length + 1];
char mode[eci_length + 1];
#else
unsigned char *datastream;
unsigned char *fullstream;
unsigned char *grid;
unsigned int *jisdata = (unsigned int *) _alloca((length + 1) * sizeof(unsigned int));
char *mode = (char *) _alloca(length + 1);
unsigned int *jisdata = (unsigned int *) _alloca((eci_length + 1) * sizeof(unsigned int));
char *mode = (char *) _alloca(eci_length + 1);
#endif
gs1 = ((symbol->input_mode & 0x07) == GS1_MODE);
@ -2928,18 +2942,27 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
if ((symbol->input_mode & 0x07) == DATA_MODE) {
sjis_cpy(source, &length, jisdata, full_multibyte);
} else {
/* Try ISO 8859-1 conversion first */
int error_number = sjis_utf8_to_eci(3, source, &length, jisdata, full_multibyte);
if (error_number != 0) {
int done = 0;
if (symbol->eci != 20) { /* Unless ECI 20 (Shift JIS) */
/* Try other encodings (ECI 0 defaults to ISO/IEC 8859-1) */
int error_number = sjis_utf8_to_eci(symbol->eci, source, &length, jisdata, full_multibyte);
if (error_number == 0) {
done = 1;
} else if (symbol->eci) {
sprintf(symbol->errtxt, "564: Invalid character in input data for ECI %d", symbol->eci);
return error_number;
}
}
if (!done) {
/* Try Shift-JIS */
error_number = sjis_utf8(symbol, source, &length, jisdata);
int error_number = sjis_utf8(symbol, source, &length, jisdata);
if (error_number != 0) {
return error_number;
}
}
}
est_binlen = getBinaryLength(RMQR_VERSION + 31, mode, jisdata, length, gs1, 0 /*eci*/, debug_print);
est_binlen = getBinaryLength(RMQR_VERSION + 31, mode, jisdata, length, gs1, symbol->eci, debug_print);
ecc_level = LEVEL_M;
max_cw = 152;
@ -2975,7 +2998,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
autosize = 31;
best_footprint = rmqr_height[31] * rmqr_width[31];
for (version = 30; version >= 0; version--) {
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print);
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci, debug_print);
footprint = rmqr_height[version] * rmqr_width[version];
if (ecc_level == LEVEL_M) {
if (8 * rmqr_data_codewords_M[version] >= est_binlen) {
@ -2994,20 +3017,20 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
}
}
version = autosize;
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print);
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci, debug_print);
}
if ((symbol->option_2 >= 1) && (symbol->option_2 <= 32)) {
// User specified symbol size
version = symbol->option_2 - 1;
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print);
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci, debug_print);
}
if (symbol->option_2 >= 33) {
// User has specified symbol height only
version = rmqr_fixed_height_upper_bound[symbol->option_2 - 32];
for (i = version - 1; i > rmqr_fixed_height_upper_bound[symbol->option_2 - 33]; i--) {
est_binlen = getBinaryLength(RMQR_VERSION + i, mode, jisdata, length, gs1, 0 /*eci*/, debug_print);
est_binlen = getBinaryLength(RMQR_VERSION + i, mode, jisdata, length, gs1, symbol->eci, debug_print);
if (ecc_level == LEVEL_M) {
if (8 * rmqr_data_codewords_M[i] >= est_binlen) {
version = i;
@ -3018,7 +3041,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
}
}
}
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print);
est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci, debug_print);
}
if (symbol->option_1 == -1) {
@ -3043,15 +3066,11 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
}
if (debug_print) {
printf("Minimum codewords = %d\n", est_binlen / 8);
printf("Selected version: %d = R%dx%d-", (version + 1), rmqr_height[version], rmqr_width[version]);
if (ecc_level == LEVEL_M) {
printf("M\n");
} else {
printf("H\n");
}
printf("Number of data codewords in symbol = %d\n", target_codewords);
printf("Number of ECC blocks = %d\n", blocks);
printf("Minimum codewords: %d\n", (est_binlen + 7) / 8);
printf("Selected version: %d = R%dx%d-%c\n",
(version + 1), rmqr_height[version], rmqr_width[version], ecc_level_names[ecc_level - 1]);
printf("Number of data codewords in symbol: %d\n", target_codewords);
printf("Number of ECC blocks: %d\n", blocks);
}
#ifndef _MSC_VER
@ -3062,7 +3081,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
fullstream = (unsigned char *) _alloca(rmqr_total_codewords[version] + 1);
#endif
qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, gs1, 0 /*eci*/, est_binlen,
qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen,
debug_print);
#ifdef ZINT_TEST
if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords);