Beispiel #1
0
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();
}
Beispiel #2
0
// 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;
}
Beispiel #3
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();
}
Beispiel #4
0
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();
}
Beispiel #5
0
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();
}
Beispiel #6
0
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;
}
Beispiel #7
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)