mirror of
https://github.com/zint/zint
synced 2024-11-16 20:57:25 +13:00
Ultracode: Add FNC1 and 06 Macro support and calculate ECC capacity
This commit is contained in:
parent
edf7f9248e
commit
7216202f06
107
backend/ultra.c
107
backend/ultra.c
@ -78,7 +78,7 @@ int ultra_find_fragment(unsigned char source[], int source_length, int position)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Encode characters in 8-bit mode */
|
/* Encode characters in 8-bit mode */
|
||||||
float look_ahead_eightbit(unsigned char source[], int in_length, int in_posn, char current_mode, int end_char, int cw[], int* cw_len)
|
float look_ahead_eightbit(unsigned char source[], int in_length, int in_posn, char current_mode, int end_char, int cw[], int* cw_len, int gs1)
|
||||||
{
|
{
|
||||||
int codeword_count = 0;
|
int codeword_count = 0;
|
||||||
int i;
|
int i;
|
||||||
@ -91,7 +91,11 @@ float look_ahead_eightbit(unsigned char source[], int in_length, int in_posn, ch
|
|||||||
|
|
||||||
i = in_posn;
|
i = in_posn;
|
||||||
do {
|
do {
|
||||||
cw[codeword_count] = source[i];
|
if ((source[i] == '[') && gs1) {
|
||||||
|
cw[codeword_count] = 268; // FNC1
|
||||||
|
} else {
|
||||||
|
cw[codeword_count] = source[i];
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
codeword_count++;
|
codeword_count++;
|
||||||
} while ((i < in_length) && (i < end_char));
|
} while ((i < in_length) && (i < end_char));
|
||||||
@ -115,7 +119,7 @@ float look_ahead_eightbit(unsigned char source[], int in_length, int in_posn, ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Encode character in the ASCII mode/submode (including numeric compression) */
|
/* Encode character in the ASCII mode/submode (including numeric compression) */
|
||||||
float look_ahead_ascii(unsigned char source[], int in_length, int in_posn, char current_mode, int symbol_mode, int end_char, int cw[], int* cw_len){
|
float look_ahead_ascii(unsigned char source[], int in_length, int in_posn, char current_mode, int symbol_mode, int end_char, int cw[], int* cw_len, int gs1){
|
||||||
int codeword_count = 0;
|
int codeword_count = 0;
|
||||||
int i;
|
int i;
|
||||||
int first_digit, second_digit;
|
int first_digit, second_digit;
|
||||||
@ -173,7 +177,11 @@ float look_ahead_ascii(unsigned char source[], int in_length, int in_posn, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (source[i] < 0x7F) {
|
if (source[i] < 0x7F) {
|
||||||
cw[codeword_count] = source[i];
|
if ((source[i] == '[') && gs1) {
|
||||||
|
cw[codeword_count] = 272; // FNC1
|
||||||
|
} else {
|
||||||
|
cw[codeword_count] = source[i];
|
||||||
|
}
|
||||||
codeword_count++;
|
codeword_count++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -222,7 +230,7 @@ int get_subset(unsigned char source[], int in_length, int in_posn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Encode characters in the C43 compaction submode */
|
/* Encode characters in the C43 compaction submode */
|
||||||
float look_ahead_c43(unsigned char source[], int in_length, int in_posn, char current_mode, int end_char, int cw[], int* cw_len){
|
float look_ahead_c43(unsigned char source[], int in_length, int in_posn, char current_mode, int end_char, int cw[], int* cw_len, int gs1){
|
||||||
int codeword_count = 0;
|
int codeword_count = 0;
|
||||||
int subcodeword_count = 0;
|
int subcodeword_count = 0;
|
||||||
int i;
|
int i;
|
||||||
@ -234,6 +242,7 @@ float look_ahead_c43(unsigned char source[], int in_length, int in_posn, char cu
|
|||||||
int base43_value;
|
int base43_value;
|
||||||
int letters_encoded = 0;
|
int letters_encoded = 0;
|
||||||
int pad;
|
int pad;
|
||||||
|
int gs1_latch = 0;
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
int subcw[in_length];
|
int subcw[in_length];
|
||||||
@ -358,6 +367,7 @@ float look_ahead_c43(unsigned char source[], int in_length, int in_posn, char cu
|
|||||||
new_subset = get_subset(source, in_length, subposn);
|
new_subset = get_subset(source, in_length, subposn);
|
||||||
|
|
||||||
if (((subset == 1) && (new_subset == 2)) && ((source[subposn] == '.') || (source[subposn] == ','))) {
|
if (((subset == 1) && (new_subset == 2)) && ((source[subposn] == '.') || (source[subposn] == ','))) {
|
||||||
|
/* <period> and <comma> characters available in both subsets */
|
||||||
new_subset = 1;
|
new_subset = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,7 +379,14 @@ float look_ahead_c43(unsigned char source[], int in_length, int in_posn, char cu
|
|||||||
|
|
||||||
subset = new_subset;
|
subset = new_subset;
|
||||||
}
|
}
|
||||||
} while ((subposn < in_length) && (subposn < end_char) && (subset != 0));
|
|
||||||
|
/* Check for FNC1 */
|
||||||
|
if (subposn < (in_length - 1)) {
|
||||||
|
if ((source[subposn + 1] == '[') && gs1) {
|
||||||
|
gs1_latch = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((subposn < in_length) && (subposn < end_char) && (subset != 0) && (gs1_latch == 0));
|
||||||
|
|
||||||
pad = 3 - (subcodeword_count % 3);
|
pad = 3 - (subcodeword_count % 3);
|
||||||
if (pad == 3) {
|
if (pad == 3) {
|
||||||
@ -428,6 +445,7 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
|
|||||||
int block_length;
|
int block_length;
|
||||||
int fragment_length;
|
int fragment_length;
|
||||||
int fragno;
|
int fragno;
|
||||||
|
int gs1 = 0;
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
unsigned char crop_source[in_length];
|
unsigned char crop_source[in_length];
|
||||||
@ -512,23 +530,45 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
|
|||||||
|
|
||||||
codeword_count++;
|
codeword_count++;
|
||||||
|
|
||||||
/* TODO: Check for 06 Macro Sequence and crop accordingly */
|
/* Check for 06 Macro Sequence and crop accordingly */
|
||||||
|
if (in_length >= 9
|
||||||
|
&& source[0] == '[' && source[1] == ')' && source[2] == '>' && source[3] == '\x1e'
|
||||||
|
&& source[4] == '0' && source[5] == '6' && source[6] == '\x1d'
|
||||||
|
&& source[in_length - 2] == '\x1e' && source[in_length - 1] == '\x04') {
|
||||||
|
|
||||||
/* Make a cropped version of input data - removes http:// and https:// if needed */
|
if (symbol_mode == EIGHTBIT_MODE) {
|
||||||
for (i = input_posn; i < in_length; i++) {
|
codewords[codeword_count] = 271; // 06 Macro
|
||||||
crop_source[i - input_posn] = source[i];
|
} else {
|
||||||
|
codewords[codeword_count] = 273; // 06 Macro
|
||||||
|
}
|
||||||
|
codeword_count++;
|
||||||
|
|
||||||
|
for (i = input_posn + 7; i < (in_length - 2); i++) {
|
||||||
|
crop_source[i - input_posn] = source[i];
|
||||||
|
}
|
||||||
|
crop_length = in_length - 9;
|
||||||
|
crop_source[crop_length] = '\0';
|
||||||
|
} else {
|
||||||
|
/* Make a cropped version of input data - removes http:// and https:// if needed */
|
||||||
|
for (i = input_posn; i < in_length; i++) {
|
||||||
|
crop_source[i - input_posn] = source[i];
|
||||||
|
}
|
||||||
|
crop_length = in_length - input_posn;
|
||||||
|
crop_source[crop_length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((symbol->input_mode & 0x07) == GS1_MODE) {
|
||||||
|
gs1 = 1;
|
||||||
}
|
}
|
||||||
crop_length = in_length - input_posn;
|
|
||||||
crop_source[crop_length] = '\0';
|
|
||||||
|
|
||||||
/* Attempt encoding in all three modes to see which offers best compaction and store results */
|
/* Attempt encoding in all three modes to see which offers best compaction and store results */
|
||||||
current_mode = symbol_mode;
|
current_mode = symbol_mode;
|
||||||
input_posn = 0;
|
input_posn = 0;
|
||||||
do {
|
do {
|
||||||
end_char = input_posn + PREDICT_WINDOW;
|
end_char = input_posn + PREDICT_WINDOW;
|
||||||
eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_posn, current_mode, end_char, cw_fragment, &fragment_length);
|
eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_posn, current_mode, end_char, cw_fragment, &fragment_length, gs1);
|
||||||
ascii_score = look_ahead_ascii(crop_source, crop_length, input_posn, current_mode, symbol_mode, end_char, cw_fragment, &fragment_length);
|
ascii_score = look_ahead_ascii(crop_source, crop_length, input_posn, current_mode, symbol_mode, end_char, cw_fragment, &fragment_length, gs1);
|
||||||
c43_score = look_ahead_c43(crop_source, crop_length, input_posn, current_mode, end_char, cw_fragment, &fragment_length);
|
c43_score = look_ahead_c43(crop_source, crop_length, input_posn, current_mode, end_char, cw_fragment, &fragment_length, gs1);
|
||||||
|
|
||||||
mode[input_posn] = 'a';
|
mode[input_posn] = 'a';
|
||||||
current_mode = ASCII_MODE;
|
current_mode = ASCII_MODE;
|
||||||
@ -557,11 +597,11 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
|
|||||||
|
|
||||||
switch(mode[input_posn]) {
|
switch(mode[input_posn]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
ascii_score = look_ahead_ascii(crop_source, crop_length, input_posn, current_mode, symbol_mode, input_posn + block_length, cw_fragment, &fragment_length);
|
ascii_score = look_ahead_ascii(crop_source, crop_length, input_posn, current_mode, symbol_mode, input_posn + block_length, cw_fragment, &fragment_length, gs1);
|
||||||
current_mode = ASCII_MODE;
|
current_mode = ASCII_MODE;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
c43_score = look_ahead_c43(crop_source, crop_length, input_posn, current_mode, input_posn + block_length, cw_fragment, &fragment_length);
|
c43_score = look_ahead_c43(crop_source, crop_length, input_posn, current_mode, input_posn + block_length, cw_fragment, &fragment_length, gs1);
|
||||||
|
|
||||||
/* Substitute temporary latch if possible */
|
/* Substitute temporary latch if possible */
|
||||||
if ((current_mode == EIGHTBIT_MODE) && (cw_fragment[0] == 261) && (fragment_length >= 5) && (fragment_length <= 11)) {
|
if ((current_mode == EIGHTBIT_MODE) && (cw_fragment[0] == 261) && (fragment_length >= 5) && (fragment_length <= 11)) {
|
||||||
@ -578,7 +618,7 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '8':
|
case '8':
|
||||||
eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_posn, current_mode, input_posn + block_length, cw_fragment, &fragment_length);
|
eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_posn, current_mode, input_posn + block_length, cw_fragment, &fragment_length, gs1);
|
||||||
current_mode = EIGHTBIT_MODE;
|
current_mode = EIGHTBIT_MODE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -599,6 +639,9 @@ int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char sou
|
|||||||
|
|
||||||
int ultracode(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length) {
|
int ultracode(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length) {
|
||||||
int data_cw_count = 0;
|
int data_cw_count = 0;
|
||||||
|
int ecc_cw;
|
||||||
|
int ecc_level; // = Q in section 7.7.1
|
||||||
|
int misdecode_cw; // = P in section 7.7.1
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
int data_codewords[in_length * 2];
|
int data_codewords[in_length * 2];
|
||||||
@ -615,6 +658,34 @@ int ultracode(struct zint_symbol *symbol, const unsigned char source[], const si
|
|||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
/* Default ECC level is EC2 */
|
||||||
|
if ((symbol->option_1 <= 0) || (symbol->option_1 > 6)) {
|
||||||
|
ecc_level = 2;
|
||||||
|
} else {
|
||||||
|
ecc_level = symbol->option_1 - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecc_level == 0) {
|
||||||
|
misdecode_cw = 0;
|
||||||
|
} else {
|
||||||
|
misdecode_cw = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ECC calculation from section 7.7.2 */
|
||||||
|
if ((data_cw_count % 25) == 0) {
|
||||||
|
ecc_cw = (ecc_level * (data_cw_count / 25)) + misdecode_cw + 2;
|
||||||
|
} else {
|
||||||
|
ecc_cw = (ecc_level * ((data_cw_count / 25) + 1)) + misdecode_cw + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("ECC codewords: %d\n", ecc_cw);
|
||||||
|
|
||||||
|
/* Maximum capacity is 282 codewords */
|
||||||
|
if (data_cw_count + ecc_cw > 282) {
|
||||||
|
strcpy(symbol->errtxt, "Data too long for selected error correction capacity");
|
||||||
|
return ZINT_ERROR_TOO_LONG;
|
||||||
|
}
|
||||||
|
|
||||||
strcpy(symbol->errtxt, "1000: Ultracode has not been implemented - yet!");
|
strcpy(symbol->errtxt, "1000: Ultracode has not been implemented - yet!");
|
||||||
return ZINT_ERROR_INVALID_OPTION;
|
return ZINT_ERROR_INVALID_OPTION;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user