void rs_error(char data_pattern[]) { /* Adds Reed-Solomon error correction to auspost */ int reader, triple_writer = 0; char triple[31], inv_triple[31]; unsigned char result[5]; for(reader = 2; reader < (int)strlen(data_pattern); reader += 3, triple_writer++) { triple[triple_writer] = convert_pattern(data_pattern[reader], 4) + convert_pattern(data_pattern[reader + 1], 2) + convert_pattern(data_pattern[reader + 2], 0); } for(reader = 0; reader < triple_writer; reader++) { inv_triple[reader] = triple[(triple_writer - 1) - reader]; } rs_init_gf(0x43); rs_init_code(4, 1); rs_encode(triple_writer, (unsigned char*) inv_triple, result); for(reader = 4; reader > 0; reader--) { concat(data_pattern, AusBarTable[(int)result[reader - 1]]); } rs_free(); }
// The following tests the routines with the ISO/IEC 16022 Annexe R data int reedsol_main(void) { register int i; unsigned char data[9] = { 142, 164, 186 }; unsigned char out[5]; rs_init_gf(0x12d); rs_init_code(5, 1); rs_encode(3, data, out); printf("Result of Annexe R encoding:\n"); for (i = 4; i >= 0; i--) printf(" %d\n", out[i]); return 0; }
void maxi_do_primary_check( ) { /* Handles error correction of primary message */ uint8_t data[15]; uint8_t results[15]; 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[ecclen - 1 - j]; rs_free(); }
void maxi_do_secondary_chk_even(int ecclen ) { /* Handles error correction of even characters in secondary */ uint8_t data[100]; uint8_t results[30]; int j; int datalen = 68; if (ecclen == 20) datalen = 84; rs_init_gf(0x43); rs_init_code(ecclen, 1); for(j = 0; j < datalen + 1; j += 1) if (!(j & 1)) // even data[j/2] = maxi_codeword[j + 20]; rs_encode(datalen/2, data, results); for ( j = 0; j < (ecclen); j += 1) maxi_codeword[ datalen + (2 *j) + 20] = results[ecclen - 1 - j]; rs_free(); }
void maxi_do_secondary_chk_odd( int ecclen ) { /* Handles error correction of odd characters in secondary */ unsigned char data[100]; unsigned char results[30]; int j; int datalen = 68; rs_init_gf(0x43); rs_init_code(ecclen, 1); if (ecclen == 20) datalen = 84; for(j = 0; j < datalen; j += 1) if (j & 1) // odd data[(j-1)/2] = maxi_codeword[j + 20]; rs_encode(datalen/2, data, results); for ( j = 0; j < (ecclen); j += 1) maxi_codeword[ datalen + (2 *j) + 1 + 20 ] = results[ecclen - 1 - j]; rs_free(); }
int code_one(struct zint_symbol *symbol, unsigned char source[], int length) { int size = 1, i, j, data_blocks; char datagrid[136][120]; int row, col; int sub_version = 0; if((symbol->option_2 < 0) || (symbol->option_2 > 10)) { strcpy(symbol->errtxt, "Invalid symbol size"); return ERROR_INVALID_OPTION; } if(symbol->option_2 == 9) { /* Version S */ int codewords; short int elreg[112]; unsigned int data[15], ecc[15]; int stream[30]; int block_width; if(length > 18) { strcpy(symbol->errtxt, "Input data too long"); return ERROR_TOO_LONG; } if(is_sane(NEON, source, length) == ERROR_INVALID_DATA) { strcpy(symbol->errtxt, "Invalid input data (Version S encodes numeric input only)"); return ERROR_INVALID_DATA; } sub_version = 3; codewords = 12; block_width = 6; /* Version S-30 */ if(length <= 12) { sub_version = 2; codewords = 8; block_width = 4; } /* Version S-20 */ if(length <= 6) { sub_version = 1; codewords = 4; block_width = 2; } /* Version S-10 */ binary_load(elreg, (char *)source, length); hex_dump(elreg); for(i = 0; i < 15; i++) { data[i] = 0; ecc[i] = 0; } for(i = 0; i < codewords; i++) { data[codewords - i - 1] += 1 * elreg[(i * 5)]; data[codewords - i - 1] += 2 * elreg[(i * 5) + 1]; data[codewords - i - 1] += 4 * elreg[(i * 5) + 2]; data[codewords - i - 1] += 8 * elreg[(i * 5) + 3]; data[codewords - i - 1] += 16 * elreg[(i * 5) + 4]; } rs_init_gf(0x25); rs_init_code(codewords, 1); rs_encode_long(codewords, data, ecc); rs_free(); for(i = 0; i < codewords; i++) { stream[i] = data[i]; stream[i + codewords] = ecc[codewords - i - 1]; } for(i = 0; i < 136; i++) { for(j = 0; j < 120; j++) { datagrid[i][j] = '0'; } } i = 0; for(row = 0; row < 2; row++) { for(col = 0; col < block_width; col++) { if(stream[i] & 0x10) { datagrid[row * 2][col * 5] = '1'; } if(stream[i] & 0x08) { datagrid[row * 2][(col * 5) + 1] = '1'; } if(stream[i] & 0x04) { datagrid[row * 2][(col * 5) + 2] = '1'; } if(stream[i] & 0x02) { datagrid[(row * 2) + 1][col * 5] = '1'; } if(stream[i] & 0x01) { datagrid[(row * 2) + 1][(col * 5) + 1] = '1'; } if(stream[i + 1] & 0x10) { datagrid[row * 2][(col * 5) + 3] = '1'; } if(stream[i + 1] & 0x08) { datagrid[row * 2][(col * 5) + 4] = '1'; } if(stream[i + 1] & 0x04) { datagrid[(row * 2) + 1][(col * 5) + 2] = '1'; } if(stream[i + 1] & 0x02) { datagrid[(row * 2) + 1][(col * 5) + 3] = '1'; } if(stream[i + 1] & 0x01) { datagrid[(row * 2) + 1][(col * 5) + 4] = '1'; } i += 2; } } size = 9; symbol->rows = 8; symbol->width = 10 * sub_version + 1; } if(symbol->option_2 == 10) { /* Version T */ unsigned int data[40], ecc[25]; unsigned int stream[65]; int data_length; int data_cw, ecc_cw, block_width; for(i = 0; i < 40; i++) { data[i] = 0; } data_length = c1_encode(symbol, source, data, length); if(data_length == 0) { return ERROR_TOO_LONG; } if(data_length > 38) { strcpy(symbol->errtxt, "Input data too long"); return ERROR_TOO_LONG; } size = 10; sub_version = 3; data_cw = 38; ecc_cw = 22; block_width = 12; if(data_length <= 24) { sub_version = 2; data_cw = 24; ecc_cw = 16; block_width = 8; } if(data_length <= 10) { sub_version = 1; data_cw = 10; ecc_cw = 10; block_width = 4; } for(i = data_length; i < data_cw; i++) { data[i] = 129; /* Pad */ } /* Calculate error correction data */ rs_init_gf(0x12d); rs_init_code(ecc_cw, 1); rs_encode_long(data_cw, data, ecc); rs_free(); /* "Stream" combines data and error correction data */ for(i = 0; i < data_cw; i++) { stream[i] = data[i]; } for(i = 0; i < ecc_cw; i++) { stream[data_cw + i] = ecc[ecc_cw - i - 1]; } for(i = 0; i < 136; i++) { for(j = 0; j < 120; j++) { datagrid[i][j] = '0'; } } i = 0; for(row = 0; row < 5; row++) { for(col = 0; col < block_width; col++) { if(stream[i] & 0x80) { datagrid[row * 2][col * 4] = '1'; } if(stream[i] & 0x40) { datagrid[row * 2][(col * 4) + 1] = '1'; } if(stream[i] & 0x20) { datagrid[row * 2][(col * 4) + 2] = '1'; } if(stream[i] & 0x10) { datagrid[row * 2][(col * 4) + 3] = '1'; } if(stream[i] & 0x08) { datagrid[(row * 2) + 1][col * 4] = '1'; } if(stream[i] & 0x04) { datagrid[(row * 2) + 1][(col * 4) + 1] = '1'; } if(stream[i] & 0x02) { datagrid[(row * 2) + 1][(col * 4) + 2] = '1'; } if(stream[i] & 0x01) { datagrid[(row * 2) + 1][(col * 4) + 3] = '1'; } i++; } } symbol->rows = 16; symbol->width = (sub_version * 16) + 1; } if((symbol->option_2 != 9) && (symbol->option_2 != 10)) { /* Version A to H */ unsigned int data[1500], ecc[600]; unsigned int sub_data[190], sub_ecc[75]; unsigned int stream[2100]; int data_length; for(i = 0; i < 1500; i++) { data[i] = 0; } data_length = c1_encode(symbol, source, data, length); if(data_length == 0) { return ERROR_TOO_LONG; } for(i = 7; i >= 0; i--) { if(c1_data_length[i] >= data_length) { size = i + 1; } } if(symbol->option_2 > size) { size = symbol->option_2; } for(i = data_length; i < c1_data_length[size - 1]; i++) { data[i] = 129; /* Pad */ } /* Calculate error correction data */ data_length = c1_data_length[size - 1]; for(i = 0; i < 190; i++) { sub_data[i] = 0; } for(i = 0; i < 75; i++) { sub_ecc[i] = 0; } data_blocks = c1_blocks[size - 1]; rs_init_gf(0x12d); rs_init_code(c1_ecc_blocks[size - 1], 0); for(i = 0; i < data_blocks; i++) { for(j = 0; j < c1_data_blocks[size - 1]; j++) { sub_data[j] = data[j * data_blocks + i]; } rs_encode_long(c1_data_blocks[size - 1], sub_data, sub_ecc); for(j = 0; j < c1_ecc_blocks[size - 1]; j++) { ecc[c1_ecc_length[size - 1] - (j * data_blocks + i) - 1] = sub_ecc[j]; } } rs_free(); /* "Stream" combines data and error correction data */ for(i = 0; i < data_length; i++) { stream[i] = data[i]; } for(i = 0; i < c1_ecc_length[size - 1]; i++) { stream[data_length + i] = ecc[i]; } for(i = 0; i < 136; i++) { for(j = 0; j < 120; j++) { datagrid[i][j] = '0'; } } i = 0; for(row = 0; row < c1_grid_height[size - 1]; row++) { for(col = 0; col < c1_grid_width[size - 1]; col++) { if(stream[i] & 0x80) { datagrid[row * 2][col * 4] = '1'; } if(stream[i] & 0x40) { datagrid[row * 2][(col * 4) + 1] = '1'; } if(stream[i] & 0x20) { datagrid[row * 2][(col * 4) + 2] = '1'; } if(stream[i] & 0x10) { datagrid[row * 2][(col * 4) + 3] = '1'; } if(stream[i] & 0x08) { datagrid[(row * 2) + 1][col * 4] = '1'; } if(stream[i] & 0x04) { datagrid[(row * 2) + 1][(col * 4) + 1] = '1'; } if(stream[i] & 0x02) { datagrid[(row * 2) + 1][(col * 4) + 2] = '1'; } if(stream[i] & 0x01) { datagrid[(row * 2) + 1][(col * 4) + 3] = '1'; } i++; } } /* for(i = 0; i < (c1_grid_height[size - 1] * 2); i++) { for(j = 0; j < (c1_grid_width[size - 1] * 4); j++) { printf("%c", datagrid[i][j]); } printf("\n"); } */ symbol->rows = c1_height[size - 1]; symbol->width = c1_width[size - 1]; } switch(size) { case 1: /* Version A */ central_finder(symbol, 6, 3, 1); vert(symbol, 4, 6, 1); vert(symbol, 12, 5, 0); set_module(symbol, 5, 12); spigot(symbol, 0); spigot(symbol, 15); block_copy(symbol, datagrid, 0, 0, 5, 4, 0, 0); block_copy(symbol, datagrid, 0, 4, 5, 12, 0, 2); block_copy(symbol, datagrid, 5, 0, 5, 12, 6, 0); block_copy(symbol, datagrid, 5, 12, 5, 4, 6, 2); break; case 2: /* Version B */ central_finder(symbol, 8, 4, 1); vert(symbol, 4, 8, 1); vert(symbol, 16, 7, 0); set_module(symbol, 7, 16); spigot(symbol, 0); spigot(symbol, 21); block_copy(symbol, datagrid, 0, 0, 7, 4, 0, 0); block_copy(symbol, datagrid, 0, 4, 7, 16, 0, 2); block_copy(symbol, datagrid, 7, 0, 7, 16, 8, 0); block_copy(symbol, datagrid, 7, 16, 7, 4, 8, 2); break; case 3: /* Version C */ central_finder(symbol, 11, 4, 2); vert(symbol, 4, 11, 1); vert(symbol, 26, 13, 1); vert(symbol, 4, 10, 0); vert(symbol, 26, 10, 0); spigot(symbol, 0); spigot(symbol, 27); block_copy(symbol, datagrid, 0, 0, 10, 4, 0, 0); block_copy(symbol, datagrid, 0, 4, 10, 20, 0, 2); block_copy(symbol, datagrid, 0, 24, 10, 4, 0, 4); block_copy(symbol, datagrid, 10, 0, 10, 4, 8, 0); block_copy(symbol, datagrid, 10, 4, 10, 20, 8, 2); block_copy(symbol, datagrid, 10, 24, 10, 4, 8, 4); break; case 4: /* Version D */ central_finder(symbol, 16, 5, 1); vert(symbol, 4, 16, 1); vert(symbol, 20, 16, 1); vert(symbol, 36, 16, 1); vert(symbol, 4, 15, 0); vert(symbol, 20, 15, 0); vert(symbol, 36, 15, 0); spigot(symbol, 0); spigot(symbol, 12); spigot(symbol, 27); spigot(symbol, 39); block_copy(symbol, datagrid, 0, 0, 15, 4, 0, 0); block_copy(symbol, datagrid, 0, 4, 15, 14, 0, 2); block_copy(symbol, datagrid, 0, 18, 15, 14, 0, 4); block_copy(symbol, datagrid, 0, 32, 15, 4, 0, 6); block_copy(symbol, datagrid, 15, 0, 15, 4, 10, 0); block_copy(symbol, datagrid, 15, 4, 15, 14, 10, 2); block_copy(symbol, datagrid, 15, 18, 15, 14, 10, 4); block_copy(symbol, datagrid, 15, 32, 15, 4, 10, 6); break; case 5: /* Version E */ central_finder(symbol, 22, 5, 2); vert(symbol, 4, 22, 1); vert(symbol, 26, 24, 1); vert(symbol, 48, 22, 1); vert(symbol, 4, 21, 0); vert(symbol, 26, 21, 0); vert(symbol, 48, 21, 0); spigot(symbol, 0); spigot(symbol, 12); spigot(symbol, 39); spigot(symbol, 51); block_copy(symbol, datagrid, 0, 0, 21, 4, 0, 0); block_copy(symbol, datagrid, 0, 4, 21, 20, 0, 2); block_copy(symbol, datagrid, 0, 24, 21, 20, 0, 4); block_copy(symbol, datagrid, 0, 44, 21, 4, 0, 6); block_copy(symbol, datagrid, 21, 0, 21, 4, 10, 0); block_copy(symbol, datagrid, 21, 4, 21, 20, 10, 2); block_copy(symbol, datagrid, 21, 24, 21, 20, 10, 4); block_copy(symbol, datagrid, 21, 44, 21, 4, 10, 6); break; case 6: /* Version F */ central_finder(symbol, 31, 5, 3); vert(symbol, 4, 31, 1); vert(symbol, 26, 35, 1); vert(symbol, 48, 31, 1); vert(symbol, 70, 35, 1); vert(symbol, 4, 30, 0); vert(symbol, 26, 30, 0); vert(symbol, 48, 30, 0); vert(symbol, 70, 30, 0); spigot(symbol, 0); spigot(symbol, 12); spigot(symbol, 24); spigot(symbol, 45); spigot(symbol, 57); spigot(symbol, 69); block_copy(symbol, datagrid, 0, 0, 30, 4, 0, 0); block_copy(symbol, datagrid, 0, 4, 30, 20, 0, 2); block_copy(symbol, datagrid, 0, 24, 30, 20, 0, 4); block_copy(symbol, datagrid, 0, 44, 30, 20, 0, 6); block_copy(symbol, datagrid, 0, 64, 30, 4, 0, 8); block_copy(symbol, datagrid, 30, 0, 30, 4, 10, 0); block_copy(symbol, datagrid, 30, 4, 30, 20, 10, 2); block_copy(symbol, datagrid, 30, 24, 30, 20, 10, 4); block_copy(symbol, datagrid, 30, 44, 30, 20, 10, 6); block_copy(symbol, datagrid, 30, 64, 30, 4, 10, 8); break; case 7: /* Version G */ central_finder(symbol, 47, 6, 2); vert(symbol, 6, 47, 1); vert(symbol, 27, 49, 1); vert(symbol, 48, 47, 1); vert(symbol, 69, 49, 1); vert(symbol, 90, 47, 1); vert(symbol, 6, 46, 0); vert(symbol, 27, 46, 0); vert(symbol, 48, 46, 0); vert(symbol, 69, 46, 0); vert(symbol, 90, 46, 0); spigot(symbol, 0); spigot(symbol, 12); spigot(symbol, 24); spigot(symbol, 36); spigot(symbol, 67); spigot(symbol, 79); spigot(symbol, 91); spigot(symbol, 103); block_copy(symbol, datagrid, 0, 0, 46, 6, 0, 0); block_copy(symbol, datagrid, 0, 6, 46, 19, 0, 2); block_copy(symbol, datagrid, 0, 25, 46, 19, 0, 4); block_copy(symbol, datagrid, 0, 44, 46, 19, 0, 6); block_copy(symbol, datagrid, 0, 63, 46, 19, 0, 8); block_copy(symbol, datagrid, 0, 82, 46, 6, 0, 10); block_copy(symbol, datagrid, 46, 0, 46, 6, 12, 0); block_copy(symbol, datagrid, 46, 6, 46, 19, 12, 2); block_copy(symbol, datagrid, 46, 25, 46, 19, 12, 4); block_copy(symbol, datagrid, 46, 44, 46, 19, 12, 6); block_copy(symbol, datagrid, 46, 63, 46, 19, 12, 8); block_copy(symbol, datagrid, 46, 82, 46, 6, 12, 10); break; case 8: /* Version H */ central_finder(symbol, 69, 6, 3); vert(symbol, 6, 69, 1); vert(symbol, 26, 73, 1); vert(symbol, 46, 69, 1); vert(symbol, 66, 73, 1); vert(symbol, 86, 69, 1); vert(symbol, 106, 73, 1); vert(symbol, 126, 69, 1); vert(symbol, 6, 68, 0); vert(symbol, 26, 68, 0); vert(symbol, 46, 68, 0); vert(symbol, 66, 68, 0); vert(symbol, 86, 68, 0); vert(symbol, 106, 68, 0); vert(symbol, 126, 68, 0); spigot(symbol, 0); spigot(symbol, 12); spigot(symbol, 24); spigot(symbol, 36); spigot(symbol, 48); spigot(symbol, 60); spigot(symbol, 87); spigot(symbol, 99); spigot(symbol, 111); spigot(symbol, 123); spigot(symbol, 135); spigot(symbol, 147); block_copy(symbol, datagrid, 0, 0, 68, 6, 0, 0); block_copy(symbol, datagrid, 0, 6, 68, 18, 0, 2); block_copy(symbol, datagrid, 0, 24, 68, 18, 0, 4); block_copy(symbol, datagrid, 0, 42, 68, 18, 0, 6); block_copy(symbol, datagrid, 0, 60, 68, 18, 0, 8); block_copy(symbol, datagrid, 0, 78, 68, 18, 0, 10); block_copy(symbol, datagrid, 0, 96, 68, 18, 0, 12); block_copy(symbol, datagrid, 0, 114, 68, 6, 0, 14); block_copy(symbol, datagrid, 68, 0, 68, 6, 12, 0); block_copy(symbol, datagrid, 68, 6, 68, 18, 12, 2); block_copy(symbol, datagrid, 68, 24, 68, 18, 12, 4); block_copy(symbol, datagrid, 68, 42, 68, 18, 12, 6); block_copy(symbol, datagrid, 68, 60, 68, 18, 12, 8); block_copy(symbol, datagrid, 68, 78, 68, 18, 12, 10); block_copy(symbol, datagrid, 68, 96, 68, 18, 12, 12); block_copy(symbol, datagrid, 68, 114, 68, 6, 12, 14); break; case 9: /* Version S */ horiz(symbol, 5, 1); horiz(symbol, 7, 1); set_module(symbol, 6, 0); set_module(symbol, 6, symbol->width - 1); unset_module(symbol, 7, 1); unset_module(symbol, 7, symbol->width - 2); switch(sub_version) { case 1: /* Version S-10 */ set_module(symbol, 0, 5); block_copy(symbol, datagrid, 0, 0, 4, 5, 0, 0); block_copy(symbol, datagrid, 0, 5, 4, 5, 0, 1); break; case 2: /* Version S-20 */ set_module(symbol, 0, 10); set_module(symbol, 4, 10); block_copy(symbol, datagrid, 0, 0, 4, 10, 0, 0); block_copy(symbol, datagrid, 0, 10, 4, 10, 0, 1); break; case 3: /* Version S-30 */ set_module(symbol, 0, 15); set_module(symbol, 4, 15); set_module(symbol, 6, 15); block_copy(symbol, datagrid, 0, 0, 4, 15, 0, 0); block_copy(symbol, datagrid, 0, 15, 4, 15, 0, 1); break; } break; case 10: /* Version T */ horiz(symbol, 11, 1); horiz(symbol, 13, 1); horiz(symbol, 15, 1); set_module(symbol, 12, 0); set_module(symbol, 12, symbol->width - 1); set_module(symbol, 14, 0); set_module(symbol, 14, symbol->width - 1); unset_module(symbol, 13, 1); unset_module(symbol, 13, symbol->width - 2); unset_module(symbol, 15, 1); unset_module(symbol, 15, symbol->width - 2); switch(sub_version) { case 1: /* Version T-16 */ set_module(symbol, 0, 8); set_module(symbol, 10, 8); block_copy(symbol, datagrid, 0, 0, 10, 8, 0, 0); block_copy(symbol, datagrid, 0, 8, 10, 8, 0, 1); break; case 2: /* Version T-32 */ set_module(symbol, 0, 16); set_module(symbol, 10, 16); set_module(symbol, 12, 16); block_copy(symbol, datagrid, 0, 0, 10, 16, 0, 0); block_copy(symbol, datagrid, 0, 16, 10, 16, 0, 1); break; case 3: /* Verion T-48 */ set_module(symbol, 0, 24); set_module(symbol, 10, 24); set_module(symbol, 12, 24); set_module(symbol, 14, 24); block_copy(symbol, datagrid, 0, 0, 10, 24, 0, 0); block_copy(symbol, datagrid, 0, 24, 10, 24, 0, 1); break; } break; } for(i = 0; i < symbol->rows; i++) { symbol->row_height[i] = 1; } return 0; }
int aztec(struct zint_symbol *symbol, uint8_t source[], int length) { int x, y, i, j, v, data_blocks, ecc_blocks, layers, total_bits; char binary_string[20000], bit_pattern[20045], descriptor[42]; char adjusted_string[20000]; uint8_t desc_data[4], desc_ecc[6]; int err_code, ecc_level, compact, data_length, data_maxsize, codeword_size, adjusted_length; int remainder, padbits, count, gs1, adjustment_size; int debug = 0, reader = 0; int comp_loop = 4; uint8_t local_source[length + 1]; memset(binary_string,0,20000); memset(adjusted_string,0,20000); if(symbol->input_mode == GS1_MODE) { gs1 = 1; } else { gs1 = 0; } if(symbol->output_options & READER_INIT) { reader = 1; comp_loop = 1; } if((gs1 == 1) && (reader == 1)) { strcpy(symbol->errtxt, "Cannot encode in GS1 and Reader Initialisation mode at the same time"); return ZERROR_INVALID_OPTION; } switch(symbol->input_mode) { case DATA_MODE: case GS1_MODE: memcpy(local_source, source, length); local_source[length] = '\0'; break; case UNICODE_MODE: err_code = latin1_process(symbol, source, local_source, &length); if(err_code != 0) { return err_code; } break; } err_code = aztec_text_process(local_source, length, binary_string, gs1); if(err_code != 0) { strcpy(symbol->errtxt, "Input too long or too many extended ASCII characters"); return err_code; } if(!((symbol->option_1 >= -1) && (symbol->option_1 <= 4))) { strcpy(symbol->errtxt, "Invalid error correction level - using default instead"); err_code = ZWARN_INVALID_OPTION; symbol->option_1 = -1; } ecc_level = symbol->option_1; if((ecc_level == -1) || (ecc_level == 0)) { ecc_level = 2; } data_length = strlen(binary_string); layers = 0; /* Keep compiler happy! */ data_maxsize = 0; /* Keep compiler happy! */ adjustment_size = 0; if(symbol->option_2 == 0) { /* The size of the symbol can be determined by Zint */ do { /* Decide what size symbol to use - the smallest that fits the data */ compact = 0; /* 1 = Aztec Compact, 0 = Normal Aztec */ layers = 0; switch(ecc_level) { /* For each level of error correction work out the smallest symbol which the data will fit in */ case 1: for(i = 32; i > 0; i--) { if((data_length + adjustment_size) < Aztec10DataSizes[i - 1]) { layers = i; compact = 0; data_maxsize = Aztec10DataSizes[i - 1]; } } for(i = comp_loop; i > 0; i--) { if((data_length + adjustment_size) < AztecCompact10DataSizes[i - 1]) { layers = i; compact = 1; data_maxsize = AztecCompact10DataSizes[i - 1]; } } break; case 2: for(i = 32; i > 0; i--) { if((data_length + adjustment_size) < Aztec23DataSizes[i - 1]) { layers = i; compact = 0; data_maxsize = Aztec23DataSizes[i - 1]; } } for(i = comp_loop; i > 0; i--) { if((data_length + adjustment_size) < AztecCompact23DataSizes[i - 1]) { layers = i; compact = 1; data_maxsize = AztecCompact23DataSizes[i - 1]; } } break; case 3: for(i = 32; i > 0; i--) { if((data_length + adjustment_size) < Aztec36DataSizes[i - 1]) { layers = i; compact = 0; data_maxsize = Aztec36DataSizes[i - 1]; } } for(i = comp_loop; i > 0; i--) { if((data_length + adjustment_size) < AztecCompact36DataSizes[i - 1]) { layers = i; compact = 1; data_maxsize = AztecCompact36DataSizes[i - 1]; } } break; case 4: for(i = 32; i > 0; i--) { if((data_length + adjustment_size) < Aztec50DataSizes[i - 1]) { layers = i; compact = 0; data_maxsize = Aztec50DataSizes[i - 1]; } } for(i = comp_loop; i > 0; i--) { if((data_length + adjustment_size) < AztecCompact50DataSizes[i - 1]) { layers = i; compact = 1; data_maxsize = AztecCompact50DataSizes[i - 1]; } } break; } if(layers == 0) { /* Couldn't find a symbol which fits the data */ strcpy(symbol->errtxt, "Input too long (too many bits for selected ECC)"); return ZERROR_TOO_LONG; } /* Determine codeword bitlength - Table 3 */ codeword_size = 6; /* if (layers <= 2) */ if((layers >= 3) && (layers <= 8)) { codeword_size = 8; } if((layers >= 9) && (layers <= 22)) { codeword_size = 10; } if(layers >= 23) { codeword_size = 12; } j = 0; i = 0; do { if((j + 1) % codeword_size == 0) { /* Last bit of codeword */ int t, done = 0; count = 0; /* Discover how many '1's in current codeword */ for(t = 0; t < (codeword_size - 1); t++) { if(binary_string[(i - (codeword_size - 1)) + t] == '1') count++; } if(count == (codeword_size - 1)) { adjusted_string[j] = '0'; j++; done = 1; } if(count == 0) { adjusted_string[j] = '1'; j++; done = 1; } if(done == 0) { adjusted_string[j] = binary_string[i]; j++; i++; } } adjusted_string[j] = binary_string[i]; j++; i++; } while (i <= (data_length + 1)); adjusted_string[j] = '\0'; adjusted_length = strlen(adjusted_string); adjustment_size = adjusted_length - data_length; /* Add padding */ remainder = adjusted_length % codeword_size; padbits = codeword_size - remainder; if(padbits == codeword_size) { padbits = 0; } for(i = 0; i < padbits; i++) { concat(adjusted_string, "1"); } adjusted_length = strlen(adjusted_string); count = 0; for(i = (adjusted_length - codeword_size); i < adjusted_length; i++) { if(adjusted_string[i] == '1') { count++; } } if(count == codeword_size) { adjusted_string[adjusted_length - 1] = '0'; } if(debug) { printf("Codewords:\n"); for(i = 0; i < (adjusted_length / codeword_size); i++) { for(j = 0; j < codeword_size; j++) { printf("%c", adjusted_string[(i * codeword_size) + j]); } printf("\n"); } } } while(adjusted_length > data_maxsize); /* This loop will only repeat on the rare occasions when the rule about not having all 1s or all 0s means that the binary string has had to be lengthened beyond the maximum number of bits that can be encoded in a symbol of the selected size */ } else { /* The size of the symbol has been specified by the user */ if((reader == 1) && ((symbol->option_2 >= 2) && (symbol->option_2 <= 4))) { symbol->option_2 = 5; } if((symbol->option_2 >= 1) && (symbol->option_2 <= 4)) { compact = 1; layers = symbol->option_2; } if((symbol->option_2 >= 5) && (symbol->option_2 <= 36)) { compact = 0; layers = symbol->option_2 - 4; } if((symbol->option_2 < 0) || (symbol->option_2 > 36)) { strcpy(symbol->errtxt, "Invalid Aztec Code size"); return ZERROR_INVALID_OPTION; } /* Determine codeword bitlength - Table 3 */ if((layers >= 0) && (layers <= 2)) { codeword_size = 6; } if((layers >= 3) && (layers <= 8)) { codeword_size = 8; } if((layers >= 9) && (layers <= 22)) { codeword_size = 10; } if(layers >= 23) { codeword_size = 12; } j = 0; i = 0; do { if((j + 1) % codeword_size == 0) { /* Last bit of codeword */ int t, done = 0; count = 0; /* Discover how many '1's in current codeword */ for(t = 0; t < (codeword_size - 1); t++) { if(binary_string[(i - (codeword_size - 1)) + t] == '1') count++; } if(count == (codeword_size - 1)) { adjusted_string[j] = '0'; j++; done = 1; } if(count == 0) { adjusted_string[j] = '1'; j++; done = 1; } if(done == 0) { adjusted_string[j] = binary_string[i]; j++; i++; } } adjusted_string[j] = binary_string[i]; j++; i++; } while (i <= (data_length + 1)); adjusted_string[j] = '\0'; adjusted_length = strlen(adjusted_string); remainder = adjusted_length % codeword_size; padbits = codeword_size - remainder; if(padbits == codeword_size) { padbits = 0; } for(i = 0; i < padbits; i++) { concat(adjusted_string, "1"); } adjusted_length = strlen(adjusted_string); count = 0; for(i = (adjusted_length - codeword_size); i < adjusted_length; i++) { if(adjusted_string[i] == '1') { count++; } } if(count == codeword_size) { adjusted_string[adjusted_length - 1] = '0'; } /* Check if the data actually fits into the selected symbol size */ if (compact) { data_maxsize = codeword_size * (AztecCompactSizes[layers - 1] - 3); } else { data_maxsize = codeword_size * (AztecSizes[layers - 1] - 3); } if(adjusted_length > data_maxsize) { strcpy(symbol->errtxt, "Data too long for specified Aztec Code symbol size"); return ZERROR_TOO_LONG; } if(debug) { printf("Codewords:\n"); for(i = 0; i < (adjusted_length / codeword_size); i++) { for(j = 0; j < codeword_size; j++) { printf("%c", adjusted_string[(i * codeword_size) + j]); } printf("\n"); } } } if(reader && (layers > 22)) { strcpy(symbol->errtxt, "Data too long for reader initialisation symbol"); return ZERROR_TOO_LONG; } data_blocks = adjusted_length / codeword_size; if(compact) { ecc_blocks = AztecCompactSizes[layers - 1] - data_blocks; } else { ecc_blocks = AztecSizes[layers - 1] - data_blocks; } if(debug) { printf("Generating a "); if(compact) { printf("compact"); } else { printf("full-size"); } printf(" symbol with %d layers\n", layers); printf("Requires "); if(compact) { printf("%d", AztecCompactSizes[layers - 1]); } else { printf("%d", AztecSizes[layers - 1]); } printf(" codewords of %d-bits\n", codeword_size); printf(" (%d data words, %d ecc words)\n", data_blocks, ecc_blocks); } unsigned int data_part[data_blocks + 3], ecc_part[ecc_blocks + 3]; /* Copy across data into separate integers */ memset(data_part,0,(data_blocks + 2)*sizeof(int)); memset(ecc_part,0,(ecc_blocks + 2)*sizeof(int)); /* Split into codewords and calculate reed-colomon error correction codes */ switch(codeword_size) { case 6: for(i = 0; i < data_blocks; i++) { if(adjusted_string[i * codeword_size] == '1') { data_part[i] += 32; } if(adjusted_string[(i * codeword_size) + 1] == '1') { data_part[i] += 16; } if(adjusted_string[(i * codeword_size) + 2] == '1') { data_part[i] += 8; } if(adjusted_string[(i * codeword_size) + 3] == '1') { data_part[i] += 4; } if(adjusted_string[(i * codeword_size) + 4] == '1') { data_part[i] += 2; } if(adjusted_string[(i * codeword_size) + 5] == '1') { data_part[i] += 1; } } rs_init_gf(0x43); rs_init_code(ecc_blocks, 1); rs_encode_long(data_blocks, data_part, ecc_part); for (i = (ecc_blocks - 1); i >= 0; i--) { bscan(adjusted_string, ecc_part[i], 0x20); } rs_free(); break; case 8: for(i = 0; i < data_blocks; i++) { if(adjusted_string[i * codeword_size] == '1') { data_part[i] += 128; } if(adjusted_string[(i * codeword_size) + 1] == '1') { data_part[i] += 64; } if(adjusted_string[(i * codeword_size) + 2] == '1') { data_part[i] += 32; } if(adjusted_string[(i * codeword_size) + 3] == '1') { data_part[i] += 16; } if(adjusted_string[(i * codeword_size) + 4] == '1') { data_part[i] += 8; } if(adjusted_string[(i * codeword_size) + 5] == '1') { data_part[i] += 4; } if(adjusted_string[(i * codeword_size) + 6] == '1') { data_part[i] += 2; } if(adjusted_string[(i * codeword_size) + 7] == '1') { data_part[i] += 1; } } rs_init_gf(0x12d); rs_init_code(ecc_blocks, 1); rs_encode_long(data_blocks, data_part, ecc_part); for (i = (ecc_blocks - 1); i >= 0; i--) { bscan(adjusted_string, ecc_part[i], 0x80); } rs_free(); break; case 10: for(i = 0; i < data_blocks; i++) { if(adjusted_string[i * codeword_size] == '1') { data_part[i] += 512; } if(adjusted_string[(i * codeword_size) + 1] == '1') { data_part[i] += 256; } if(adjusted_string[(i * codeword_size) + 2] == '1') { data_part[i] += 128; } if(adjusted_string[(i * codeword_size) + 3] == '1') { data_part[i] += 64; } if(adjusted_string[(i * codeword_size) + 4] == '1') { data_part[i] += 32; } if(adjusted_string[(i * codeword_size) + 5] == '1') { data_part[i] += 16; } if(adjusted_string[(i * codeword_size) + 6] == '1') { data_part[i] += 8; } if(adjusted_string[(i * codeword_size) + 7] == '1') { data_part[i] += 4; } if(adjusted_string[(i * codeword_size) + 8] == '1') { data_part[i] += 2; } if(adjusted_string[(i * codeword_size) + 9] == '1') { data_part[i] += 1; } } rs_init_gf(0x409); rs_init_code(ecc_blocks, 1); rs_encode_long(data_blocks, data_part, ecc_part); for(i = (ecc_blocks - 1); i >= 0; i--) { bscan(adjusted_string, ecc_part[i], 0x200); } rs_free(); break; case 12: for(i = 0; i < data_blocks; i++) { if(adjusted_string[i * codeword_size] == '1') { data_part[i] += 2048; } if(adjusted_string[(i * codeword_size) + 1] == '1') { data_part[i] += 1024; } if(adjusted_string[(i * codeword_size) + 2] == '1') { data_part[i] += 512; } if(adjusted_string[(i * codeword_size) + 3] == '1') { data_part[i] += 256; } if(adjusted_string[(i * codeword_size) + 4] == '1') { data_part[i] += 128; } if(adjusted_string[(i * codeword_size) + 5] == '1') { data_part[i] += 64; } if(adjusted_string[(i * codeword_size) + 6] == '1') { data_part[i] += 32; } if(adjusted_string[(i * codeword_size) + 7] == '1') { data_part[i] += 16; } if(adjusted_string[(i * codeword_size) + 8] == '1') { data_part[i] += 8; } if(adjusted_string[(i * codeword_size) + 9] == '1') { data_part[i] += 4; } if(adjusted_string[(i * codeword_size) + 10] == '1') { data_part[i] += 2; } if(adjusted_string[(i * codeword_size) + 11] == '1') { data_part[i] += 1; } } rs_init_gf(0x1069); rs_init_code(ecc_blocks, 1); rs_encode_long(data_blocks, data_part, ecc_part); for(i = (ecc_blocks - 1); i >= 0; i--) { bscan(adjusted_string, ecc_part[i], 0x800); } rs_free(); break; } /* Invert the data so that actual data is on the outside and reed-solomon on the inside */ memset(bit_pattern,'0',20045); total_bits = (data_blocks + ecc_blocks) * codeword_size; for(i = 0; i < total_bits; i++) { bit_pattern[i] = adjusted_string[total_bits - i - 1]; } /* Now add the symbol descriptor */ memset(desc_data,0,4); memset(desc_ecc,0,6); memset(descriptor,0,42); if(compact) { /* The first 2 bits represent the number of layers minus 1 */ descriptor[0] = ((layers - 1) & 2) ? '1' : '0'; descriptor[1] = ((layers - 1) & 1) ? '1' : '0'; /* The next 6 bits represent the number of data blocks minus 1 */ if(reader) { descriptor[2] = '1'; } else { descriptor[2] = ((data_blocks - 1) & 0x20) ? '1' : '0'; } for (i = 3, v = 0x10; v; v >>= 1) descriptor[i++] = ((data_blocks - 1) & v) ? '1' : '0'; descriptor[8] = '\0'; if(debug) printf("Mode Message = %s\n", descriptor); } else { /* The first 5 bits represent the number of layers minus 1 */ for (i = 0, v = 0x10; v; v >>= 1)