Ultra: Disable code compression by default

Ensures symbols are valid until better version of specification is available
This commit is contained in:
Robin Stuart 2020-03-29 22:23:07 +01:00
parent c57b74a7e6
commit b572bb513d
3 changed files with 107 additions and 104 deletions

View file

@ -1,7 +1,7 @@
/* ultra.c - Ultracode
libzint - the open source barcode library
Copyright (C) 2019 Robin Stuart <rstuart114@gmail.com>
Copyright (C) 2020 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -117,6 +117,18 @@ static const int tiles[] = {
* Dated 2001-03-09
* Corrected thanks to input from Terry Burton */
/*
* NOTE: Included here is an attempt to allow code compression within Ultracode. Unfortunately
* the copy of the standard this was written from was an early draft which includes self
* contradictions, so this is a "best guess" implementation. Because it is not guaranteed
* to be correct this compression is not applied by default. To enable compression set
*
* symbol->option_1 = ULTRA_COMPRESSION;
*
* Code compression should be enabled by default when is has been implemented according to
* a more reliable version of the specification.
*/
/* Generate divisor polynomial gQ(x) for GF283() given the required ECC size, 3 to 101 */
void ultra_genPoly(short EccSize, unsigned short gPoly[], unsigned short gfPwr[], unsigned short gfLog[]) {
int i, j;
@ -239,15 +251,8 @@ float look_ahead_eightbit(unsigned char source[], int in_length, int in_locn, ch
letters_encoded = i - in_locn;
//printf("8BIT FRAG: ");
//for (i = 0; i < codeword_count; i++) {
// printf("%d ", cw[i]);
//}
//printf("\n");
*cw_len = codeword_count;
//printf("%d letters in %d codewords\n", letters_encoded, codeword_count);
if (codeword_count == 0) {
return 0.0;
} else {
@ -326,15 +331,8 @@ float look_ahead_ascii(unsigned char source[], int in_length, int in_locn, char
letters_encoded = i - in_locn;
//printf("ASCII FRAG: ");
//for (i = 0; i < codeword_count; i++) {
// printf("%d ", cw[i]);
//}
//printf("\n");
*cw_len = codeword_count;
//printf("%d letters in %d codewords\n", letters_encoded, codeword_count);
if (codeword_count == 0) {
return 0.0;
} else {
@ -529,7 +527,7 @@ float look_ahead_c43(unsigned char source[], int in_length, int in_locn, char cu
if (pad == 3) {
pad = 0;
}
//printf("Pad = %d\n", pad);
for (i = 0; i < pad; i++) {
subcw[subcodeword_count] = 42; // Latch to other C43 set used as pad
subcodeword_count++;
@ -537,12 +535,6 @@ float look_ahead_c43(unsigned char source[], int in_length, int in_locn, char cu
letters_encoded = sublocn - in_locn;
//printf("C43 SUBFRAG: ");
//for (i = 0; i < subcodeword_count; i++) {
// printf("%d ", subcw[i]);
//}
//printf("\n");
for (i = 0; i < subcodeword_count; i += 3) {
base43_value = (43 * 43 * subcw[i]) + (43 * subcw[i + 1]) + subcw[i + 2];
cw[codeword_count] = base43_value / 282;
@ -551,15 +543,8 @@ float look_ahead_c43(unsigned char source[], int in_length, int in_locn, char cu
codeword_count++;
}
// printf("C43 FRAG: ");
//for (i = 0; i < codeword_count; i++) {
// printf("%d ", cw[i]);
//}
//printf("\n");
*cw_len = codeword_count;
//printf("%d letters in %d codewords\n", letters_encoded, codeword_count);
if (codeword_count == 0) {
return 0.0;
} else {
@ -585,13 +570,13 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
int gs1 = 0;
#ifndef _MSC_VER
unsigned char crop_source[in_length];
char mode[in_length];
int cw_fragment[in_length];
unsigned char crop_source[in_length + 1];
char mode[in_length + 1];
int cw_fragment[in_length + 1];
#else
unsigned char * crop_source = (unsigned char *) _alloca(in_length * sizeof (unsigned char));
char * mode = (char *) _alloca(in_length * sizeof (char));
int * cw_fragment = (int *) _alloca(in_length * sizeof (int));
unsigned char * crop_source = (unsigned char *) _alloca((in_length + 1) * sizeof (unsigned char));
char * mode = (char *) _alloca(in_length + 1 * sizeof (char));
int * cw_fragment = (int *) _alloca(in_length + 1 * sizeof (int));
#endif /* _MSC_VER */
/* Section 7.6.2 indicates that ECI \000003 to \811799 are supported */
@ -608,6 +593,11 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
symbol_mode = EIGHTBIT_MODE;
}
}
if (symbol->option_1 != ULTRA_COMPRESSION) {
// Force eight-bit mode by default as other modes are poorly documented
symbol_mode = EIGHTBIT_MODE;
}
if (symbol->output_options & READER_INIT) {
/* Reader Initialisation mode */
@ -715,28 +705,35 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
}
/* Attempt encoding in all three modes to see which offers best compaction and store results */
current_mode = symbol_mode;
input_locn = 0;
do {
end_char = input_locn + PREDICT_WINDOW;
eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1);
ascii_score = look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, end_char, cw_fragment, &fragment_length, gs1);
c43_score = look_ahead_c43(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1);
if (symbol->option_1 != ULTRA_COMPRESSION) {
current_mode = symbol_mode;
input_locn = 0;
do {
end_char = input_locn + PREDICT_WINDOW;
eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1);
ascii_score = look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, end_char, cw_fragment, &fragment_length, gs1);
c43_score = look_ahead_c43(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1);
mode[input_locn] = 'a';
current_mode = ASCII_MODE;
mode[input_locn] = 'a';
current_mode = ASCII_MODE;
if ((c43_score > ascii_score) && (c43_score > eightbit_score)) {
mode[input_locn] = 'c';
current_mode = C43_MODE;
}
if ((c43_score > ascii_score) && (c43_score > eightbit_score)) {
mode[input_locn] = 'c';
current_mode = C43_MODE;
}
if ((eightbit_score > ascii_score) && (eightbit_score > c43_score)) {
if ((eightbit_score > ascii_score) && (eightbit_score > c43_score)) {
mode[input_locn] = '8';
current_mode = EIGHTBIT_MODE;
}
input_locn++;
} while (input_locn < crop_length);
} else {
// Force eight-bit mode
for (input_locn = 0; input_locn < crop_length; input_locn++) {
mode[input_locn] = '8';
current_mode = EIGHTBIT_MODE;
}
input_locn++;
} while (input_locn < crop_length);
}
mode[input_locn] = '\0';
/* Use results from test to perform actual mode switching */
@ -784,9 +781,6 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
input_locn += block_length;
} while (input_locn < crop_length);
//printf("RED: %s\n", crop_source);
//printf("MOD: %s\n", mode);
return codeword_count;
}
@ -823,12 +817,9 @@ int ultracode(struct zint_symbol *symbol, const unsigned char source[], const si
data_cw_count = ultra_generate_codewords(symbol, source, in_length, data_codewords);
printf("Codewords returned = %d\n", data_cw_count);
//for (int i = 0; i < data_cw_count; i++) {
// printf("%d ", data_codewords[i]);
//}
//printf("\n");
if (symbol->debug) {
printf("Codewords returned = %d\n", data_cw_count);
}
/* Default ECC level is EC2 */
if ((symbol->option_1 <= 0) || (symbol->option_1 > 6)) {
@ -850,7 +841,9 @@ int ultracode(struct zint_symbol *symbol, const unsigned char source[], const si
}
acc = qcc - 3;
printf("ECC codewords: %d\n", qcc);
if (symbol->debug) {
printf("ECC codewords: %d\n", qcc);
}
/* Maximum capacity is 282 codewords */
total_cws = data_cw_count + qcc + 5;
@ -874,7 +867,9 @@ int ultracode(struct zint_symbol *symbol, const unsigned char source[], const si
columns = (total_cws / rows) + 1;
}
printf("Calculated size is %d rows by %d columns\n", rows, columns);
if (symbol->debug) {
printf("Calculated size is %d rows by %d columns\n", rows, columns);
}
/* Insert MCC and ACC into data codewords */
for (i = 282; i > 2; i--) {
@ -904,11 +899,13 @@ int ultracode(struct zint_symbol *symbol, const unsigned char source[], const si
}
codeword[locn++] = qcc; // QCC
printf("Rearranged codewords with ECC:\n");
for (i = 0; i < locn; i++) {
printf("%d ", codeword[i]);
if (symbol->debug) {
printf("Rearranged codewords with ECC:\n");
for (i = 0; i < locn; i++) {
printf("%d ", codeword[i]);
}
printf("\n");
}
printf("\n");
total_height = (rows * 6) + 1;
total_width = columns + 6 + (columns / 15);
@ -976,7 +973,7 @@ int ultracode(struct zint_symbol *symbol, const unsigned char source[], const si
tilex++;
}
}
//printf("[%d] = %s\n", codeword[i], tilepat);
for (j = 0; j < 5; j++) {
pattern[((tiley + j + 1) * total_width) + (tilex + 5)] = tilepat[j];
}
@ -1003,12 +1000,14 @@ int ultracode(struct zint_symbol *symbol, const unsigned char source[], const si
pattern[((tiley + j) * total_width) + tilex] = tilepat[j];
}
printf("DCC: %d\n", dcc);
if (symbol->debug) {
printf("DCC: %d\n", dcc);
for (i = 0; i < (total_height * total_width); i++) {
printf("%c", pattern[i]);
if ((i + 1) % total_width == 0) {
printf("\n");
for (i = 0; i < (total_height * total_width); i++) {
printf("%c", pattern[i]);
if ((i + 1) % total_width == 0) {
printf("\n");
}
}
}

View file

@ -267,6 +267,9 @@ extern "C" {
#define DM_SQUARE 100
#define DM_DMRE 101
// Ultracode specific option
#define ULTRA_COMPRESSION 128
// Warning and error conditions
#define ZINT_WARN_INVALID_OPTION 2
#define ZINT_WARN_USES_ECI 3

View file

@ -37,37 +37,38 @@
/* Print list of supported symbologies */
void types(void) {
printf( " 1: Code 11 51: Pharma One-Track 92: Aztec Code\n"
" 2: Standard 2of5 52: PZN 93: DAFT Code\n"
" 3: Interleaved 2of5 53: Pharma Two-Track 97: Micro QR Code\n"
" 4: IATA 2of5 55: PDF417 98: HIBC Code 128\n"
" 6: Data Logic 56: PDF417 Trunc 99: HIBC Code 39\n"
" 7: Industrial 2of5 57: Maxicode 102: HIBC Data Matrix\n"
" 8: Code 39 58: QR Code 104: HIBC QR Code\n"
" 9: Extended Code 39 60: Code 128-B 106: HIBC PDF417\n"
"13: EAN 63: AP Standard Customer 108: HIBC MicroPDF417\n"
"14: EAN + Check 66: AP Reply Paid 110: HIBC Codablock-F\n"
"16: GS1-128 67: AP Routing 112: HIBC Aztec Code\n"
"18: Codabar 68: AP Redirection 115: DotCode\n"
"20: Code 128 69: ISBN 116: Han Xin Code\n"
"21: Leitcode 70: RM4SCC 121: RM Mailmark\n"
"22: Identcode 71: Data Matrix 128: Aztec Runes\n"
"23: Code 16k 72: EAN-14 129: Code 32\n"
"24: Code 49 73: VIN (North America) 130: Comp EAN\n"
"25: Code 93 74: Codablock-F 131: Comp GS1-128\n"
"28: Flattermarken 75: NVE-18 132: Comp DataBar Omni\n"
"29: GS1 DataBar Omni 76: Japanese Post 133: Comp DataBar Ltd\n"
"30: GS1 DataBar Ltd 77: Korea Post 134: Comp DataBar ExpOm\n"
"31: GS1 DataBar ExpOm 79: GS1 DataBar Stack 135: Comp UPC-A\n"
"32: Telepen Alpha 80: GS1 DataBar Stack Omni 136: Comp UPC-E\n"
"34: UPC-A 81: GS1 DataBar ESO 137: Comp DataBar Stack\n"
"35: UPC-A + Check 82: Planet 138: Comp DataBar Stack Omni\n"
"37: UPC-E 84: MicroPDF 139: Comp DataBar ESO\n"
"38: UPC-E + Check 85: USPS OneCode 140: Channel Code\n"
"40: Postnet 86: UK Plessey 141: Code One\n"
"47: MSI Plessey 87: Telepen Numeric 142: Grid Matrix\n"
"49: FIM 89: ITF-14 143: UPNQR\n"
"50: Logmars 90: KIX Code 145: rMQR\n"
printf( " 1: Code 11 52: PZN 97: Micro QR Code\n"
" 2: Standard 2of5 53: Pharma Two-Track 98: HIBC Code 128\n"
" 3: Interleaved 2of5 55: PDF417 99: HIBC Code 39\n"
" 4: IATA 2of5 56: PDF417 Trunc 102: HIBC Data Matrix\n"
" 6: Data Logic 57: Maxicode 104: HIBC QR Code\n"
" 7: Industrial 2of5 58: QR Code 106: HIBC PDF417\n"
" 8: Code 39 60: Code 128-B 108: HIBC MicroPDF417\n"
" 9: Extended Code 39 63: AP Standard Customer 110: HIBC Codablock-F\n"
"13: EAN 66: AP Reply Paid 112: HIBC Aztec Code\n"
"14: EAN + Check 67: AP Routing 115: DotCode\n"
"16: GS1-128 68: AP Redirection 116: Han Xin Code\n"
"18: Codabar 69: ISBN 121: RM Mailmark\n"
"20: Code 128 70: RM4SCC 128: Aztec Runes\n"
"21: Leitcode 71: Data Matrix 129: Code 32\n"
"22: Identcode 72: EAN-14 130: Comp EAN\n"
"23: Code 16k 73: VIN (North America) 131: Comp GS1-128\n"
"24: Code 49 74: Codablock-F 132: Comp DataBar Omni\n"
"25: Code 93 75: NVE-18 133: Comp DataBar Ltd\n"
"28: Flattermarken 76: Japanese Post 134: Comp DataBar ExpOm\n"
"29: GS1 DataBar Omni 77: Korea Post 135: Comp UPC-A\n"
"30: GS1 DataBar Ltd 79: GS1 DataBar Stack 136: Comp UPC-E\n"
"31: GS1 DataBar ExpOm 80: GS1 DataBar Stack Omni 137: Comp DataBar Stack\n"
"32: Telepen Alpha 81: GS1 DataBar ESO 138: Comp DataBar Stack Omni\n"
"34: UPC-A 82: Planet 1139: Comp DataBar ESO\n"
"35: UPC-A + Check 84: MicroPDF 140: Channel Code\n"
"37: UPC-E 85: USPS OneCode 141: Code One\n"
"38: UPC-E + Check 86: UK Plessey 142: Grid Matrix\n"
"40: Postnet 87: Telepen Numeric 143: UPNQR\n"
"47: MSI Plessey 89: ITF-14 144: Ultracode\n"
"49: FIM 90: KIX Code 145: rMQR\n"
"50: Logmars 92: Aztec Code\n"
"51: Pharma One-Track 93: DAFT Code\n"
);
}