From 91251fbc26d809223f02ecafe62144ed6029074e Mon Sep 17 00:00:00 2001 From: hooper114 Date: Tue, 18 May 2010 08:33:03 +0000 Subject: [PATCH] Maxicode - error correction bug and misplaced finder --- backend/maxicode.c | 129 +++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 70 deletions(-) diff --git a/backend/maxicode.c b/backend/maxicode.c index 3b60e866..3e77d909 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008 Robin Stuart + Copyright (C) 2010 Robin Stuart This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,18 +19,14 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* This code has been thoroughly checked against ISO/IEC 16023:2000 */ +/* Includes corrections thanks to Monica Swanson @ Source Technologies */ #include "common.h" #include "maxicode.h" #include "reedsol.h" #include #include -#ifdef __APPLE__ -#include -#else -#include -#endif +#include int maxi_codeword[144]; @@ -42,17 +38,17 @@ void maxi_do_primary_check( ) int j; int datalen = 10; int ecclen = 10; - + rs_init_gf(0x43); rs_init_code(ecclen, 1); - + for(j = 0; j < datalen; j += 1) data[j] = maxi_codeword[j]; - + rs_encode(datalen, data, results); for ( j = 0; j < ecclen; j += 1) - maxi_codeword[ datalen + j] = results[j]; + maxi_codeword[ datalen + j] = results[ecclen - 1 - j]; rs_free(); } @@ -63,7 +59,7 @@ void maxi_do_secondary_chk_odd( int ecclen ) unsigned char results[30]; int j; int datalen = 68; - + rs_init_gf(0x43); rs_init_code(ecclen, 1); @@ -77,7 +73,7 @@ void maxi_do_secondary_chk_odd( int ecclen ) rs_encode(datalen/2, data, results); for ( j = 0; j < (ecclen); j += 1) - maxi_codeword[ datalen + (2 *j) + 1 + 20 ] = results[j]; + maxi_codeword[ datalen + (2 *j) + 1 + 20 ] = results[ecclen - 1 - j]; rs_free(); } @@ -94,7 +90,7 @@ void maxi_do_secondary_chk_even(int ecclen ) rs_init_gf(0x43); rs_init_code(ecclen, 1); - + for(j = 0; j < datalen + 1; j += 1) if ((j % 2) == 0) // even data[j/2] = maxi_codeword[j + 20]; @@ -102,7 +98,7 @@ void maxi_do_secondary_chk_even(int ecclen ) rs_encode(datalen/2, data, results); for ( j = 0; j < (ecclen); j += 1) - maxi_codeword[ datalen + (2 *j) + 20] = results[j]; + maxi_codeword[ datalen + (2 *j) + 20] = results[ecclen - 1 - j]; rs_free(); } @@ -110,7 +106,7 @@ void maxi_bump(int set[], int character[], int bump_posn) { /* Moves everything up so that a shift or latch can be inserted */ int i; - + for(i = 143; i > bump_posn; i--) { set[i] = set[i - 1]; character[i] = character[i - 1]; @@ -120,29 +116,29 @@ void maxi_bump(int set[], int character[], int bump_posn) int maxi_text_process(int mode, unsigned char source[], int length) { /* Format text according to Appendix A */ - + /* This code doesn't make use of [Lock in C], [Lock in D] and [Lock in E] and so is not always the most efficient at compressing data, but should suffice for most applications */ - + int set[144], character[144], i, j, done, count, current_set; - + if(length > 138) { return ERROR_TOO_LONG; } - + for(i = 0; i < 144; i++) { set[i] = -1; character[i] = 0; } - + for (i = 0; i < length; i++) { /* Look up characters in table from Appendix A - this gives value and code set for most characters */ set[i] = maxiCodeSet[source[i]]; character[i] = maxiSymbolChar[source[i]]; } - + /* If a character can be represented in more than one code set, pick which version to use */ if(set[0] == 0) { @@ -172,7 +168,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) } done = 1; } - + if((character[i] == 28) && (done == 0)) { /* FS */ if(set[i - 1] == 5) { @@ -183,7 +179,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) } done = 1; } - + if((character[i] == 29) && (done == 0)) { /* GS */ if(set[i - 1] == 5) { @@ -205,7 +201,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) } done = 1; } - + if((character[i] == 32) && (done == 0)) { /* Space */ if(set[i - 1] == 1) { @@ -253,7 +249,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) } done = 1; } - + if((character[i] == 46) && (done == 0)) { /* Full Stop */ if(set[i - 1] == 2) { @@ -269,7 +265,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) } done = 1; } - + if((character[i] == 47) && (done == 0)) { /* Slash */ if(set[i - 1] == 2) { @@ -285,7 +281,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) } done = 1; } - + if((character[i] == 58) && (done == 0)) { /* Colon */ if(set[i - 1] == 2) { @@ -303,7 +299,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) } } } - + for(i = length; i < 144; i++) { /* Add the padding */ if(set[length - 1] == 2) { @@ -339,7 +335,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) count = 0; } } - + /* Add shift and latch characters */ current_set = 1; i = 0; @@ -426,20 +422,20 @@ int maxi_text_process(int mode, unsigned char source[], int length) /* Number compression */ char substring[11]; int value; - + for(j = 0; j < 10; j++) { substring[j] = character[i + j]; } substring[10] = '\0'; value = atoi(substring); - + character[i] = 31; /* NS */ character[i + 1] = (value & 0x3f000000) >> 24; character[i + 2] = (value & 0xfc0000) >> 18; character[i + 3] = (value & 0x3f000) >> 12; character[i + 4] = (value & 0xfc0) >> 6; character[i + 5] = (value & 0x3f); - + i += 6; for(j = i; j < 140; j++) { set[j] = set[j + 3]; @@ -454,23 +450,23 @@ int maxi_text_process(int mode, unsigned char source[], int length) if(((mode ==2) || (mode == 3)) && (length > 84)) { return ERROR_TOO_LONG; } - + if(((mode == 4) || (mode == 6)) && (length > 93)) { return ERROR_TOO_LONG; } - + if((mode == 5) && (length > 77)) { return ERROR_TOO_LONG; } - - + + /* Copy the encoded text into the codeword array */ if((mode == 2) || (mode == 3)) { for(i = 0; i < 84; i++) { /* secondary only */ maxi_codeword[i + 20] = character[i]; } } - + if((mode == 4) || (mode == 6)) { for(i = 0; i < 9; i++) { /* primary */ maxi_codeword[i + 1] = character[i]; @@ -479,7 +475,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) maxi_codeword[i + 20] = character[i + 9]; } } - + if(mode == 5) { for(i = 0; i < 9; i++) { /* primary */ maxi_codeword[i + 1] = character[i]; @@ -488,7 +484,7 @@ int maxi_text_process(int mode, unsigned char source[], int length) maxi_codeword[i + 20] = character[i + 9]; } } - + return 0; } @@ -496,16 +492,16 @@ void maxi_do_primary_2(char postcode[], int country, int service) { /* Format structured primary for Mode 2 */ int postcode_length, postcode_num, i; - + for(i = 0; i < 10; i++) { if((postcode[i] < '0') || (postcode[i] > '9')) { postcode[i] = '\0'; } } - + postcode_length = strlen(postcode); postcode_num = atoi(postcode); - + maxi_codeword[0] = ((postcode_num & 0x03) << 4) | 2; maxi_codeword[1] = ((postcode_num & 0xfc) >> 2); maxi_codeword[2] = ((postcode_num & 0x3f00) >> 8); @@ -537,7 +533,7 @@ void maxi_do_primary_3(char postcode[], int country, int service) /* Input characters lower than 27 (NUL - SUB) in postcode are interpreted as capital letters in Code Set A (e.g. LF becomes 'J') */ } - + maxi_codeword[0] = ((postcode[5] & 0x03) << 4) | 3; maxi_codeword[1] = ((postcode[4] & 0x03) << 4) | ((postcode[5] & 0x3c) >> 2); maxi_codeword[2] = ((postcode[3] & 0x03) << 4) | ((postcode[4] & 0x3c) >> 2); @@ -555,7 +551,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) int i, j, block, bit, mode, countrycode = 0, service = 0, lp = 0; int bit_pattern[7], internal_error = 0, eclen, error_number; char postcode[12], countrystr[4], servicestr[4]; - + #ifndef _MSC_VER unsigned char local_source[length + 1]; #else @@ -566,7 +562,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) strcpy(postcode, ""); strcpy(countrystr, ""); strcpy(servicestr, ""); - + /* The following to be replaced by ECI handling */ switch(symbol->input_mode) { case DATA_MODE: @@ -580,14 +576,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) break; } memset(maxi_codeword, 0, sizeof(maxi_codeword)); - - if(symbol->output_options & READER_INIT) { mode = 6; } - - if((mode == 6) && (symbol->input_mode == GS1_MODE)) { - strcpy(symbol->errtxt, "Cannot encode GS1 and Reader Initialisation at the same time"); - return ERROR_INVALID_OPTION; - } - + if(mode == -1) { /* If mode is unspecified */ lp = strlen(symbol->primary); if(lp == 0) { @@ -602,28 +591,28 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) } } } - + if((mode < 2) || (mode > 6)) { /* Only codes 2 to 6 supported */ strcpy(symbol->errtxt, "Invalid Maxicode Mode"); return ERROR_INVALID_OPTION; } - + if((mode == 2) || (mode == 3)) { /* Modes 2 and 3 need data in symbol->primary */ if(lp != 15) { strcpy(symbol->errtxt, "Invalid Primary String"); return ERROR_INVALID_DATA; } - + for(i = 9; i < 15; i++) { /* check that country code and service are numeric */ if((symbol->primary[i] < '0') || (symbol->primary[i] > '9')) { strcpy(symbol->errtxt, "Invalid Primary String"); return ERROR_INVALID_DATA; } } - + memcpy(postcode, symbol->primary, 9); postcode[9] = '\0'; - + if(mode == 2) { for(i = 0; i < 10; i++) { if(postcode[i] == ' ') { @@ -632,17 +621,17 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) } } else if(mode == 3) { postcode[6] = '\0'; } - + countrystr[0] = symbol->primary[9]; countrystr[1] = symbol->primary[10]; countrystr[2] = symbol->primary[11]; countrystr[3] = '\0'; - + servicestr[0] = symbol->primary[12]; servicestr[1] = symbol->primary[13]; servicestr[2] = symbol->primary[14]; servicestr[3] = '\0'; - + countrycode = atoi(countrystr); service = atoi(servicestr); @@ -651,7 +640,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) } else { maxi_codeword[0] = mode; } - + i = maxi_text_process(mode, local_source, length); if(i == ERROR_TOO_LONG ) { strcpy(symbol->errtxt, "Input data too long"); @@ -660,7 +649,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) /* All the data is sorted - now do error correction */ maxi_do_primary_check(); /* always EEC */ - + if ( mode == 5 ) eclen = 56; // 68 data codewords , 56 error corrections else @@ -668,22 +657,22 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) maxi_do_secondary_chk_even(eclen/2); // do error correction of even maxi_do_secondary_chk_odd(eclen/2); // do error correction of odd - + /* Copy data into symbol grid */ for(i = 0; i < 33; i++) { for(j = 0; j < 30; j++) { block = (MaxiGrid[(i * 30) + j] + 5) / 6; bit = (MaxiGrid[(i * 30) + j] + 5) % 6; - + if(block != 0) { - + bit_pattern[0] = (maxi_codeword[block - 1] & 0x20) >> 5; bit_pattern[1] = (maxi_codeword[block - 1] & 0x10) >> 4; bit_pattern[2] = (maxi_codeword[block - 1] & 0x8) >> 3; bit_pattern[3] = (maxi_codeword[block - 1] & 0x4) >> 2; bit_pattern[4] = (maxi_codeword[block - 1] & 0x2) >> 1; bit_pattern[5] = (maxi_codeword[block - 1] & 0x1); - + if(bit_pattern[bit] != 0) { set_module(symbol, i, j); } @@ -695,7 +684,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) set_module(symbol, 0, 28); // Top right filler set_module(symbol, 0, 29); set_module(symbol, 9, 10); // Top left marker - set_module(symbol, 0, 11); + set_module(symbol, 9, 11); set_module(symbol, 10, 11); set_module(symbol, 15, 7); // Left hand marker set_module(symbol, 16, 8); @@ -705,7 +694,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) set_module(symbol, 23, 10); set_module(symbol, 22, 17); // Bottom right marker set_module(symbol, 23, 17); - + symbol->width = 30; symbol->rows = 33;