Maxicode - error correction bug and misplaced finder

This commit is contained in:
hooper114 2010-05-18 08:33:03 +00:00
parent 93d65a910c
commit 91251fbc26

View File

@ -2,7 +2,7 @@
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
Copyright (C) 2010 Robin Stuart <robin@zint.org.uk>
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 <string.h>
#include <stdlib.h>
#ifdef __APPLE__
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif
#include <malloc.h>
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;