From 6beac47e8d0d057102d512d0fd46f3848bd6a24a Mon Sep 17 00:00:00 2001 From: hooper114 Date: Sat, 31 Oct 2009 22:42:10 +0000 Subject: [PATCH] Tidy up loose ends --- backend/gridmtx.c | 54 +++++++++++++++++++++++++++++++++++++++++------ backend/gridmtx.h | 1 + backend/library.c | 2 +- backend/qr.c | 43 ++++++++++++++++++++++++++++--------- 4 files changed, 82 insertions(+), 18 deletions(-) diff --git a/backend/gridmtx.c b/backend/gridmtx.c index 966dd33d..a6a11542 100644 --- a/backend/gridmtx.c +++ b/backend/gridmtx.c @@ -904,10 +904,11 @@ void place_layer_id(char* grid, int size, int layers, int modules, int ecc_level int grid_matrix(struct zint_symbol *symbol, unsigned char source[], int length) { int size, modules, dark, error_number; - int layers, ecc_level, x, y, i, j, glyph; + int auto_layers, min_layers, layers, auto_ecc_level, min_ecc_level, ecc_level; + int x, y, i, j, glyph; char binary[9300]; int data_cw; - int word[1460]; + int word[1460], data_max; #ifndef _MSC_VER int utfdata[length + 1]; @@ -962,14 +963,53 @@ int grid_matrix(struct zint_symbol *symbol, unsigned char source[], int length) /* Determine the size of the symbol */ data_cw = strlen(binary) / 7; - layers = 13; + + auto_layers = 13; for(i = 12; i > 0; i--) { - if(gm_recommend_cw[(i - 1)] >= data_cw) { layers = i; } + if(gm_recommend_cw[(i - 1)] >= data_cw) { auto_layers = i; } + } + min_layers = 13; + for(i = 12; i > 0; i--) { + if(gm_max_cw[(i - 1)] >= data_cw) { min_layers = i; } } - ecc_level = 3; - if(layers == 1) { ecc_level = 5; } - if((layers == 2) || (layers == 3)) { ecc_level = 4; } + layers = auto_layers; + if((symbol->option_2 >= 1) && (symbol->option_2 <= 13)) { + if(symbol->option_2 > min_layers) { + layers = symbol->option_2; + } else { + layers = min_layers; + } + } + + auto_ecc_level = 3; + if(layers == 1) { auto_ecc_level = 5; } + if((layers == 2) || (layers == 3)) { auto_ecc_level = 4; } + min_ecc_level = 1; + if(layers == 1) { min_ecc_level = 4; } + if((layers == 2) || (layers == 3)) { min_ecc_level = 2; } + + ecc_level = auto_ecc_level; + if((symbol->option_1 >= 1) && (symbol->option_1 <= 5)) { + if(symbol->option_1 > min_ecc_level) { + ecc_level = symbol->option_1; + } else { + ecc_level = min_ecc_level; + } + } + + data_max = 1313; + switch(ecc_level) { + case 2: data_max = 1167; break; + case 3: data_max = 1021; break; + case 4: data_max = 875; break; + case 5: data_max = 729; break; + } + + if(data_cw > data_max) { + strcpy(symbol->errtxt, "Input data too long"); + return ERROR_TOO_LONG; + } gm_add_ecc(binary, data_cw, layers, ecc_level, word); size = 6 + (layers * 12); diff --git a/backend/gridmtx.h b/backend/gridmtx.h index 8279148d..ba684a1d 100644 --- a/backend/gridmtx.h +++ b/backend/gridmtx.h @@ -37,6 +37,7 @@ static char shift_set[] = { }; static int gm_recommend_cw[] = { 9, 30, 59, 114, 170, 237, 315, 405, 506, 618, 741, 875, 1021 }; +static int gm_max_cw[] = { 11, 40, 79, 146, 218, 305, 405, 521, 650, 794, 953, 1125, 1313 }; static int gm_total_cw[] = { 18, 50, 98, 162, 242, 338, 450, 578, 722, 882, 1058, 1250, 1458 }; static int gm_data_codewords[] = { diff --git a/backend/library.c b/backend/library.c index aded3998..0ff059b2 100644 --- a/backend/library.c +++ b/backend/library.c @@ -357,7 +357,7 @@ int ZBarcode_ValidID(int symbol_id) case BARCODE_RSS_EXPSTACK_CC: case BARCODE_CHANNEL: case BARCODE_CODEONE: - /* case BARCODE_GRIDMATRIX: */ + case BARCODE_GRIDMATRIX: result = 1; break; } diff --git a/backend/qr.c b/backend/qr.c index 09bf4ce3..332cbc31 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -107,7 +107,7 @@ void define_mode(char mode[], int jisdata[], int length) } } -int estimate_binary_length(char mode[], int length) +int estimate_binary_length(char mode[], int length, int gs1) { /* Make an estimate (worst case scenario) of how long the binary string will be */ int i, count = 0; @@ -115,6 +115,8 @@ int estimate_binary_length(char mode[], int length) int a_count = 0; int n_count = 0; + if(gs1) { count += 4; } + for(i = 0; i < length; i++) { if(mode[i] != current) { switch(mode[i]) { @@ -154,14 +156,14 @@ int estimate_binary_length(char mode[], int length) return count; } -void qr_binary(int datastream[], int version, int target_binlen, char mode[], int jisdata[], int length) +void qr_binary(int datastream[], int version, int target_binlen, char mode[], int jisdata[], int length, int gs1) { /* Convert input data to a binary stream and add padding */ int position = 0, debug = 0; int short_data_block_length, i, scheme; char data_block, padbits; int current_binlen, current_bytes; - int toggle; + int toggle, percent; #ifndef _MSC_VER char binary[target_binlen * 8]; @@ -170,6 +172,10 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in #endif strcpy(binary, ""); + if(gs1) { + concat(binary, "0101"); /* FNC1 */ + } + if(version <= 9) { scheme = 1; } @@ -187,6 +193,8 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in printf("\n"); } + percent = 0; + do { data_block = mode[position]; short_data_block_length = 0; @@ -287,6 +295,10 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in for(i = 0; i < short_data_block_length; i++) { int byte = jisdata[position + i]; + if(gs1 && (byte == '[')) { + byte = 0x1d; /* FNC1 */ + } + if(byte & 0x80) { concat(binary, "1"); } else { concat(binary, "0"); } if(byte & 0x40) { concat(binary, "1"); } else { concat(binary, "0"); } if(byte & 0x20) { concat(binary, "1"); } else { concat(binary, "0"); } @@ -335,7 +347,7 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in while ( i < short_data_block_length ) { int count; int first = 0, second = 0, prod; - + first = posn(RHODIUM, (char) jisdata[position + i]); count = 1; prod = first; @@ -345,7 +357,7 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in count = 2; prod = (first * 45) + second; } - + switch(count) { case 2: if(prod & 0x400) { concat(binary, "1"); } else { concat(binary, "0"); } @@ -365,7 +377,7 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in if(debug) { printf("0x%4X ", prod); } - i += 2; + i += count; }; if(debug) { printf("\n"); } @@ -441,7 +453,7 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in if(debug) { printf("0x%4X (%d)", prod, prod); } - i += 3; + i += count; }; if(debug) { printf("\n"); } @@ -1053,7 +1065,7 @@ int qr_code(struct zint_symbol *symbol, unsigned char source[], int length) { int error_number, i, j, glyph, est_binlen; int ecc_level, autosize, version, max_cw, target_binlen, blocks, size; - int bitmask; + int bitmask, gs1; #ifndef _MSC_VER int utfdata[length + 1]; @@ -1065,6 +1077,12 @@ int qr_code(struct zint_symbol *symbol, unsigned char source[], int length) char* mode = (char *)_alloca(length + 1); #endif + if(symbol->input_mode == GS1_MODE) { + gs1 = 1; + } else { + gs1 = 0; + } + switch(symbol->input_mode) { case DATA_MODE: for(i = 0; i < length; i++) { @@ -1099,7 +1117,7 @@ int qr_code(struct zint_symbol *symbol, unsigned char source[], int length) } define_mode(mode, jisdata, length); - est_binlen = estimate_binary_length(mode, length); + est_binlen = estimate_binary_length(mode, length, gs1); ecc_level = LEVEL_L; max_cw = 2956; @@ -1152,6 +1170,11 @@ int qr_code(struct zint_symbol *symbol, unsigned char source[], int length) } else { version = autosize; } + + /* Ensure maxium error correction capacity */ + if(est_binlen <= qr_data_codewords_M[version - 1]) { ecc_level = LEVEL_M; } + if(est_binlen <= qr_data_codewords_Q[version - 1]) { ecc_level = LEVEL_Q; } + if(est_binlen <= qr_data_codewords_H[version - 1]) { ecc_level = LEVEL_H; } target_binlen = qr_data_codewords_L[version - 1]; blocks = qr_blocks_L[version - 1]; switch(ecc_level) { @@ -1168,7 +1191,7 @@ int qr_code(struct zint_symbol *symbol, unsigned char source[], int length) int* fullstream = (int *)_alloca((qr_total_codewords[version - 1] + 1) * sizeof(int)); #endif - qr_binary(datastream, version, target_binlen, mode, jisdata, length); + qr_binary(datastream, version, target_binlen, mode, jisdata, length, gs1); add_ecc(fullstream, datastream, version, target_binlen, blocks); size = qr_sizes[version - 1];