Exemplo n.º 1
0
int reduced_charset(struct zint_symbol *symbol, uint8_t *source, int length)
{
	/* These are the "norm" standards which only support Latin-1 at most */
	int error_number = 0;

	uint8_t preprocessed[length + 1];

	if(symbol->symbology == BARCODE_CODE16K) {
		symbol->whitespace_width = 16;
		symbol->border_width = 2;
		symbol->output_options = BARCODE_BIND;
	}

	if(symbol->symbology == BARCODE_ITF14) {
		symbol->whitespace_width = 20;
		symbol->border_width = 8;
		symbol->output_options = BARCODE_BOX;
	}

	switch(symbol->input_mode) {
		case DATA_MODE:
		case GS1_MODE:
			memcpy(preprocessed, source, length);
			preprocessed[length] = '\0';
			break;
		case UNICODE_MODE:
			error_number = latin1_process(symbol, source, preprocessed, &length);
			if(error_number != 0) { return error_number; }
			break;
	}

	switch(symbol->symbology) {
		case BARCODE_PDF417: error_number = pdf417enc(symbol, preprocessed, length); break;
		case BARCODE_PDF417TRUNC: error_number = pdf417enc(symbol, preprocessed, length); break;
		case BARCODE_MICROPDF417: error_number = micro_pdf417(symbol, preprocessed, length); break;
	}

	return error_number;
}
int reduced_charset(struct zint_symbol *symbol, unsigned char *source, int length)
{
	/* These are the "norm" standards which only support Latin-1 at most */
	int error_number = 0;
	
#ifndef _MSC_VER
	unsigned char preprocessed[length + 1];
#else
        unsigned char* preprocessed = (unsigned char*)_alloca(length + 1);
#endif
	
	if(symbol->symbology == BARCODE_CODE16K) {
		symbol->whitespace_width = 16;
		symbol->border_width = 2;
		symbol->output_options = BARCODE_BIND;
	}
	
	if(symbol->symbology == BARCODE_ITF14) {
		symbol->whitespace_width = 20;
		symbol->border_width = 8;
		symbol->output_options = BARCODE_BOX;
	}
	
	switch(symbol->input_mode) {
		case DATA_MODE:
		case GS1_MODE:
			memcpy(preprocessed, source, length);
			preprocessed[length] = '\0';
			break;
		case UNICODE_MODE:
			error_number = latin1_process(symbol, source, preprocessed, &length);
			if(error_number != 0) { return error_number; }
			break;
	}

	switch(symbol->symbology) {
		case BARCODE_C25MATRIX: error_number = matrix_two_of_five(symbol, preprocessed, length); break;
		case BARCODE_C25IND: error_number = industrial_two_of_five(symbol, preprocessed, length); break;
		case BARCODE_C25INTER: error_number = interleaved_two_of_five(symbol, preprocessed, length); break;
		case BARCODE_C25IATA: error_number = iata_two_of_five(symbol, preprocessed, length); break;
		case BARCODE_C25LOGIC: error_number = logic_two_of_five(symbol, preprocessed, length); break;
		case BARCODE_DPLEIT: error_number = dpleit(symbol, preprocessed, length); break;
		case BARCODE_DPIDENT: error_number = dpident(symbol, preprocessed, length); break;
		case BARCODE_UPCA: error_number = eanx(symbol, preprocessed, length); break;
		case BARCODE_UPCE: error_number = eanx(symbol, preprocessed, length); break;
		case BARCODE_EANX: error_number = eanx(symbol, preprocessed, length); break;
		case BARCODE_EAN128: error_number = ean_128(symbol, preprocessed, length); break;
		case BARCODE_CODE39: error_number = c39(symbol, preprocessed, length); break;
		case BARCODE_PZN: error_number = pharmazentral(symbol, preprocessed, length); break;
		case BARCODE_EXCODE39: error_number = ec39(symbol, preprocessed, length); break;
		case BARCODE_CODABAR: error_number = codabar(symbol, preprocessed, length); break;
		case BARCODE_CODE93: error_number = c93(symbol, preprocessed, length); break;
		case BARCODE_LOGMARS: error_number = c39(symbol, preprocessed, length); break;
		case BARCODE_CODE128: error_number = code_128(symbol, preprocessed, length); break;
		case BARCODE_CODE128B: error_number = code_128(symbol, preprocessed, length); break;
		case BARCODE_NVE18: error_number = nve_18(symbol, preprocessed, length); break;
		case BARCODE_CODE11: error_number = code_11(symbol, preprocessed, length); break;
		case BARCODE_MSI_PLESSEY: error_number = msi_handle(symbol, preprocessed, length); break;
		case BARCODE_TELEPEN: error_number = telepen(symbol, preprocessed, length); break;
		case BARCODE_TELEPEN_NUM: error_number = telepen_num(symbol, preprocessed, length); break;
		case BARCODE_PHARMA: error_number = pharma_one(symbol, preprocessed, length); break;
		case BARCODE_PLESSEY: error_number = plessey(symbol, preprocessed, length); break;
		case BARCODE_ITF14: error_number = itf14(symbol, preprocessed, length); break;
		case BARCODE_FLAT: error_number = flattermarken(symbol, preprocessed, length); break;
		case BARCODE_FIM: error_number = fim(symbol, preprocessed, length); break;
		case BARCODE_POSTNET: error_number = post_plot(symbol, preprocessed, length); break;
		case BARCODE_PLANET: error_number = planet_plot(symbol, preprocessed, length); break;
		case BARCODE_RM4SCC: error_number = royal_plot(symbol, preprocessed, length); break;
		case BARCODE_AUSPOST: error_number = australia_post(symbol, preprocessed, length); break;
		case BARCODE_AUSREPLY: error_number = australia_post(symbol, preprocessed, length); break;
		case BARCODE_AUSROUTE: error_number = australia_post(symbol, preprocessed, length); break;
		case BARCODE_AUSREDIRECT: error_number = australia_post(symbol, preprocessed, length); break;
		case BARCODE_CODE16K: error_number = code16k(symbol, preprocessed, length); break;
		case BARCODE_PHARMA_TWO: error_number = pharma_two(symbol, preprocessed, length); break;
		case BARCODE_ONECODE: error_number = imail(symbol, preprocessed, length); break;
		case BARCODE_ISBNX: error_number = eanx(symbol, preprocessed, length); break;
		case BARCODE_RSS14: error_number = rss14(symbol, preprocessed, length); break;
		case BARCODE_RSS14STACK: error_number = rss14(symbol, preprocessed, length); break;
		case BARCODE_RSS14STACK_OMNI: error_number = rss14(symbol, preprocessed, length); break;
		case BARCODE_RSS_LTD: error_number = rsslimited(symbol, preprocessed, length); break;
		case BARCODE_RSS_EXP: error_number = rssexpanded(symbol, preprocessed, length); break;
		case BARCODE_RSS_EXPSTACK: error_number = rssexpanded(symbol, preprocessed, length); break;
		case BARCODE_EANX_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_EAN128_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_RSS14_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_RSS_LTD_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_RSS_EXP_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_UPCA_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_UPCE_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_RSS14STACK_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_RSS14_OMNI_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_RSS_EXPSTACK_CC: error_number = composite(symbol, preprocessed, length); break;
		case BARCODE_KIX: error_number = kix_code(symbol, preprocessed, length); break;
		case BARCODE_CODE32: error_number = code32(symbol, preprocessed, length); break;
		case BARCODE_DAFT: error_number = daft_code(symbol, preprocessed, length); break;
		case BARCODE_EAN14: error_number = ean_14(symbol, preprocessed, length); break;
		case BARCODE_AZRUNE: error_number = aztec_runes(symbol, preprocessed, length); break;
		case BARCODE_KOREAPOST: error_number = korea_post(symbol, preprocessed, length); break;
		case BARCODE_HIBC_128: error_number = hibc(symbol, preprocessed, length); break;
		case BARCODE_HIBC_39: error_number = hibc(symbol, preprocessed, length); break;
		case BARCODE_HIBC_DM: error_number = hibc(symbol, preprocessed, length); break;
		case BARCODE_HIBC_QR: error_number = hibc(symbol, preprocessed, length); break;
		case BARCODE_HIBC_PDF: error_number = hibc(symbol, preprocessed, length); break;
		case BARCODE_HIBC_MICPDF: error_number = hibc(symbol, preprocessed, length); break;
		case BARCODE_HIBC_AZTEC: error_number = hibc(symbol, preprocessed, length); break;
		case BARCODE_JAPANPOST: error_number = japan_post(symbol, preprocessed, length); break;
		case BARCODE_CODE49: error_number = code_49(symbol, preprocessed, length); break;
		case BARCODE_CHANNEL: error_number = channel_code(symbol, preprocessed, length); break;
		case BARCODE_CODEONE: error_number = code_one(symbol, preprocessed, length); break;
		case BARCODE_DATAMATRIX: error_number = dmatrix(symbol, preprocessed, length); break;
		case BARCODE_PDF417: error_number = pdf417enc(symbol, preprocessed, length); break;
		case BARCODE_PDF417TRUNC: error_number = pdf417enc(symbol, preprocessed, length); break;
		case BARCODE_MICROPDF417: error_number = micro_pdf417(symbol, preprocessed, length); break;
		case BARCODE_MAXICODE: error_number = maxicode(symbol, preprocessed, length); break;
		case BARCODE_AZTEC: error_number = aztec(symbol, preprocessed, length); break;
	}
	
	return error_number;
}
Exemplo n.º 3
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)