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)