DOTCODE: Fix best_mask -> high_score prime test; manual mask

This commit is contained in:
gitlost 2021-01-22 18:07:59 +00:00
parent fb12fe4e79
commit f6bed3acb2
11 changed files with 872 additions and 195 deletions

View File

@ -32,7 +32,8 @@
/* vim: set ts=4 sw=4 et : */
/*
* Attempts to encode DotCode according to (AIMD013) ISS DotCode Rev. 4.0, DRAFT 0.15, TSC Pre-PR #5, dated May 28, 2019
* Attempts to encode DotCode according to (AIMD013) ISS DotCode Rev. 4.0, DRAFT 0.15, TSC Pre-PR #5,
* dated May 28, 2019
* Incorporating suggestions from Terry Burton at BWIPP
*/
@ -69,7 +70,7 @@ static const unsigned short int dot_patterns[113] = {
};
// Printed() routine from Annex A adapted to char array of ASCII 1's and 0's
static int get_dot(char Dots[], const int Hgt, const int Wid, const int x, const int y) {
static int get_dot(const char Dots[], const int Hgt, const int Wid, const int x, const int y) {
int retval = 0;
if ((x >= 0) && (x < Wid) && (y >= 0) && (y < Hgt)) {
@ -81,7 +82,7 @@ static int get_dot(char Dots[], const int Hgt, const int Wid, const int x, const
return retval;
}
static int clr_col(char *Dots, const int Hgt, const int Wid, const int x) {
static int clr_col(const char *Dots, const int Hgt, const int Wid, const int x) {
int y;
for (y = x & 1; y < Hgt; y += 2) {
if (get_dot(Dots, Hgt, Wid, x, y)) {
@ -92,7 +93,7 @@ static int clr_col(char *Dots, const int Hgt, const int Wid, const int x) {
return 1;
}
static int clr_row(char *Dots, const int Hgt, const int Wid, const int y) {
static int clr_row(const char *Dots, const int Hgt, const int Wid, const int y) {
int x;
for (x = y & 1; x < Wid; x += 2) {
if (get_dot(Dots, Hgt, Wid, x, y)) {
@ -104,7 +105,7 @@ static int clr_row(char *Dots, const int Hgt, const int Wid, const int y) {
}
// calc penalty for empty interior columns
static int col_penalty(char *Dots, int Hgt, int Wid) {
static int col_penalty(const char *Dots, const int Hgt, const int Wid) {
int x, penalty = 0, penalty_local = 0;
for (x = 1; x < Wid - 1; x++) {
@ -126,7 +127,7 @@ static int col_penalty(char *Dots, int Hgt, int Wid) {
}
// calc penalty for empty interior rows
static int row_penalty(char *Dots, int Hgt, int Wid) {
static int row_penalty(const char *Dots, const int Hgt, const int Wid) {
int y, penalty = 0, penalty_local = 0;
for (y = 1; y < Hgt - 1; y++) {
@ -148,7 +149,7 @@ static int row_penalty(char *Dots, int Hgt, int Wid) {
}
/* Dot pattern scoring routine from Annex A */
static int score_array(char Dots[], int Hgt, int Wid) {
static int score_array(const char Dots[], const int Hgt, const int Wid) {
int x, y, worstedge, first, last, sum;
int penalty = 0;
@ -278,7 +279,7 @@ static int score_array(char Dots[], int Hgt, int Wid) {
// employing Galois Field GF, where GF is prime, with a prime modulus of PM
//-------------------------------------------------------------------------
static void rsencode(int nd, int nc, unsigned char *wd) {
static void rsencode(const int nd, const int nc, unsigned char *wd) {
// roots (antilogs): root[0] = 1; for (i = 1; i < GF - 1; i++) root[i] = (PM * root[i - 1]) % GF;
static int root[GF - 1] = {
1, 3, 9, 27, 81, 17, 51, 40, 7, 21,
@ -307,7 +308,9 @@ static void rsencode(int nd, int nc, unsigned char *wd) {
int NC = NW - ND;
// first compute the generator polynomial "c" of order "NC":
memset(c, 0, GF * sizeof(int)); // Keep clang-tidy happy (as far as UndefinedBinaryOperatorResult warning below at least)
// Keep clang-tidy happy (as far as UndefinedBinaryOperatorResult warning below at least)
memset(c, 0, GF * sizeof(int));
c[0] = 1;
for (i = 1; i <= NC; i++) {
@ -335,7 +338,7 @@ static void rsencode(int nd, int nc, unsigned char *wd) {
}
/* Check if the next character is directly encodable in code set A (Annex F.II.D) */
static int datum_a(const unsigned char source[], int position, int length) {
static int datum_a(const unsigned char source[], const int position, const int length) {
int retval = 0;
if (position < length) {
@ -347,8 +350,9 @@ static int datum_a(const unsigned char source[], int position, int length) {
return retval;
}
/* Check if the next character is directly encodable in code set B (Annex F.II.D). Note changed to return 2 if CR/LF */
static int datum_b(const unsigned char source[], int position, int length) {
/* Check if the next character is directly encodable in code set B (Annex F.II.D).
* Note changed to return 2 if CR/LF */
static int datum_b(const unsigned char source[], const int position, const int length) {
int retval = 0;
if (position < length) {
@ -375,10 +379,10 @@ static int datum_b(const unsigned char source[], int position, int length) {
}
/* Check if the next characters are directly encodable in code set C (Annex F.II.D) */
static int datum_c(const unsigned char source[], int position, int length) {
static int datum_c(const unsigned char source[], const int position, const int length) {
int retval = 0;
if (position <= length - 2) {
if (position + 1 < length) {
if (((source[position] >= '0') && (source[position] <= '9'))
&& ((source[position + 1] >= '0') && (source[position + 1] <= '9')))
retval = 1;
@ -388,7 +392,7 @@ static int datum_c(const unsigned char source[], int position, int length) {
}
/* Returns how many consecutive digits lie immediately ahead (Annex F.II.A) */
static int n_digits(const unsigned char source[], int position, int length) {
static int n_digits(const unsigned char source[], const int position, const int length) {
int i;
for (i = position; (i < length) && ((source[i] >= '0') && (source[i] <= '9')); i++);
@ -397,7 +401,7 @@ static int n_digits(const unsigned char source[], int position, int length) {
}
/* checks ahead for 10 or more digits starting "17xxxxxx10..." (Annex F.II.B) */
static int seventeen_ten(const unsigned char source[], int position, int length) {
static int seventeen_ten(const unsigned char source[], const int position, const int length) {
int found = 0;
if (n_digits(source, position, length) >= 10) {
@ -413,7 +417,7 @@ static int seventeen_ten(const unsigned char source[], int position, int length)
/* checks how many characters ahead can be reached while datum_c is true,
* returning the resulting number of codewords (Annex F.II.E)
*/
static int ahead_c(const unsigned char source[], int position, int length) {
static int ahead_c(const unsigned char source[], const int position, const int length) {
int count = 0;
int i;
@ -425,7 +429,7 @@ static int ahead_c(const unsigned char source[], int position, int length) {
}
/* Annex F.II.F */
static int try_c(const unsigned char source[], int position, int length) {
static int try_c(const unsigned char source[], const int position, const int length) {
int retval = 0;
if (n_digits(source, position, length) > 0) {
@ -438,7 +442,7 @@ static int try_c(const unsigned char source[], int position, int length) {
}
/* Annex F.II.G */
static int ahead_a(const unsigned char source[], int position, int length) {
static int ahead_a(const unsigned char source[], const int position, const int length) {
int count = 0;
int i;
@ -451,7 +455,7 @@ static int ahead_a(const unsigned char source[], int position, int length) {
}
/* Annex F.II.H Note: changed to return number of chars encodable. Number of codewords returned in *p_nx. */
static int ahead_b(const unsigned char source[], int position, int length, int *p_nx) {
static int ahead_b(const unsigned char source[], const int position, const int length, int *p_nx) {
int count = 0;
int i, incr;
@ -468,7 +472,7 @@ static int ahead_b(const unsigned char source[], int position, int length, int *
}
/* checks if the next character is in the range 128 to 255 (Annex F.II.I) */
static int binary(const unsigned char source[], int length, int position) {
static int binary(const unsigned char source[], const int length, const int position) {
int retval = 0;
if (position < length && source[position] >= 128) {
@ -479,7 +483,8 @@ static int binary(const unsigned char source[], int length, int position) {
}
/* Analyse input data stream and encode using algorithm from Annex F */
static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char source[], int length, unsigned char *codeword_array, int *binary_finish) {
static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char source[], const int length,
unsigned char *codeword_array, int *binary_finish) {
static char lead_specials[] = "\x09\x1C\x1D\x1E"; // HT, FS, GS, RS
int input_position, array_length, i;
@ -644,11 +649,11 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha
if (seventeen_ten(source, input_position, length)) {
codeword_array[array_length] = 100; // (17)...(10)
array_length++;
codeword_array[array_length] = ((source[input_position + 2] - '0') * 10) + (source[input_position + 3] - '0');
codeword_array[array_length] = to_int(source + input_position + 2, 2);
array_length++;
codeword_array[array_length] = ((source[input_position + 4] - '0') * 10) + (source[input_position + 5] - '0');
codeword_array[array_length] = to_int(source + input_position + 4, 2);
array_length++;
codeword_array[array_length] = ((source[input_position + 6] - '0') * 10) + (source[input_position + 7] - '0');
codeword_array[array_length] = to_int(source + input_position + 6, 2);
array_length++;
input_position += 10;
done = 1;
@ -659,12 +664,13 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha
}
if ((!done) && (encoding_mode == 'C')) {
if (datum_c(source, input_position, length) || ((source[input_position] == '[') && ((symbol->input_mode & 0x07) == GS1_MODE))) {
if (datum_c(source, input_position, length)
|| ((source[input_position] == '[') && ((symbol->input_mode & 0x07) == GS1_MODE))) {
if (source[input_position] == '[') {
codeword_array[array_length] = 107; // FNC1
input_position++;
} else {
codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
codeword_array[array_length] = to_int(source + input_position, 2);
input_position += 2;
}
array_length++;
@ -754,7 +760,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha
codeword_array[array_length] = 103 + (n - 2); // nx Shift C
array_length++;
for (i = 0; i < n; i++) {
codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
codeword_array[array_length] = to_int(source + input_position, 2);
array_length++;
input_position += 2;
}
@ -794,7 +800,8 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha
done = 1;
} else if (input_position != 0) {
/* HT, FS, GS and RS in the first data position would be interpreted as a macro (see table 2) */
/* HT, FS, GS and RS in the first data position would be interpreted as a macro
* (see table 2) */
switch(source[input_position]) {
case 9: // HT
codeword_array[array_length] = 97;
@ -882,7 +889,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha
codeword_array[array_length] = 103 + (n - 2); // nx Shift C
array_length++;
for (i = 0; i < n; i++) {
codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
codeword_array[array_length] = to_int(source + input_position, 2);
array_length++;
input_position += 2;
}
@ -1011,7 +1018,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha
codeword_array[array_length] = 101 + n; // Interrupt for nx Shift C
array_length++;
for (i = 0; i < n; i++) {
codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
codeword_array[array_length] = to_int(source + input_position, 2);
array_length++;
input_position += 2;
}
@ -1136,7 +1143,7 @@ static int make_dotstream(const unsigned char masked_array[], const int array_le
/* Determines if a given dot is a reserved corner dot
* to be used by one of the last six bits
*/
static int is_corner(int column, int row, int width, int height) {
static int is_corner(const int column, const int row, const int width, const int height) {
int corner = 0;
/* Top Left */
@ -1178,7 +1185,7 @@ static int is_corner(int column, int row, int width, int height) {
}
/* Place the dots in the symbol*/
static void fold_dotstream(char dot_stream[], int width, int height, char dot_array[]) {
static void fold_dotstream(const char dot_stream[], const int width, const int height, char dot_array[]) {
int column, row;
int input_position = 0;
@ -1243,10 +1250,12 @@ static void fold_dotstream(char dot_stream[], int width, int height, char dot_ar
}
}
static void apply_mask(int mask, int data_length, unsigned char *masked_codeword_array, unsigned char *codeword_array, int ecc_length) {
static void apply_mask(const int mask, const int data_length, unsigned char *masked_codeword_array,
const unsigned char *codeword_array, const int ecc_length) {
int weight = 0;
int j;
assert(mask >= 0 && mask <= 3); /* Suppress clang-analyzer taking default branch */
switch (mask) {
case 0:
masked_codeword_array[0] = 0;
@ -1280,7 +1289,7 @@ static void apply_mask(int mask, int data_length, unsigned char *masked_codeword
rsencode(data_length + 1, ecc_length, masked_codeword_array);
}
static void force_corners(int width, int height, char *dot_array) {
static void force_corners(const int width, const int height, char *dot_array) {
if (width % 2) {
// "Vertical" symbol
dot_array[0] = '1';
@ -1307,22 +1316,22 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len
int min_dots, min_area;
int height, width;
int mask_score[8];
int user_mask;
int dot_stream_length;
int high_score, best_mask;
int binary_finish = 0;
int debug = symbol->debug;
int padding_dots, is_first;
int codeword_array_len = length * 4 + 8; /* Allow up to 4 codewords per input + 2 (FNC) + 4 (ECI) + 2 (special char 1st position) */
#ifdef _MSC_VER
unsigned char* masked_codeword_array;
#endif
/* Allow up to 4 codewords per input + 2 (FNC) + 4 (ECI) + 2 (special char 1st position) */
int codeword_array_len = length * 4 + 8;
#ifndef _MSC_VER
unsigned char codeword_array[codeword_array_len];
#else
char* dot_stream;
char* dot_array;
unsigned char* codeword_array = (unsigned char *) _alloca(codeword_array_len);
unsigned char *codeword_array = (unsigned char *) _alloca(codeword_array_len);
char *dot_stream;
char *dot_array;
unsigned char *masked_codeword_array;
#endif /* _MSC_VER */
if (symbol->eci > 811799) {
@ -1330,9 +1339,15 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len
return ZINT_ERROR_INVALID_OPTION;
}
user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is mask + 1, so >= 1 and <= 8 */
if (user_mask > 8) {
user_mask = 0; /* Ignore */
}
data_length = dotcode_encode_message(symbol, source, length, codeword_array, &binary_finish);
/* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.ArraySubscript warnings */
/* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.ArraySubscript
* warnings */
assert(data_length > 0);
ecc_length = 3 + (data_length / 2);
@ -1422,13 +1437,10 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len
#ifndef _MSC_VER
char dot_stream[height * width * 3];
char dot_array[width * height * sizeof (char) ];
char dot_array[width * height];
#else
dot_stream = (char *) _alloca(height * width * 3);
if (!dot_stream) return ZINT_ERROR_MEMORY;
dot_array = (char *) _alloca(width * height * sizeof (char));
if (!dot_array) return ZINT_ERROR_MEMORY;
dot_array = (char *) _alloca(width * height);
#endif
/* Add pad characters */
@ -1458,46 +1470,19 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len
ecc_length = 3 + (data_length / 2);
#ifndef _MSC_VER
unsigned char masked_codeword_array[data_length + 1 + ecc_length];
#else
masked_codeword_array = (unsigned char *) _alloca((data_length + 1 + ecc_length) * sizeof (unsigned char));
masked_codeword_array = (unsigned char *) _alloca(data_length + 1 + ecc_length);
#endif /* _MSC_VER */
/* Evaluate data mask options */
for (i = 0; i < 4; i++) {
apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length);
dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
/* Add pad bits */
for (jc = dot_stream_length; jc < n_dots; jc++) {
strcat(dot_stream, "1");
}
fold_dotstream(dot_stream, width, height, dot_array);
mask_score[i] = score_array(dot_array, height, width);
if (user_mask) {
best_mask = user_mask - 1;
if (debug & ZINT_DEBUG_PRINT) {
printf("Mask %d score is %d\n", i, mask_score[i]);
printf("Applying mask %d (specified)\n", best_mask);
}
}
high_score = mask_score[0];
best_mask = 0;
for (i = 1; i < 4; i++) {
if (mask_score[i] >= high_score) {
high_score = mask_score[i];
best_mask = i;
}
}
/* Re-evaluate using forced corners if needed */
if (best_mask <= (height * width) / 2) {
} else {
/* Evaluate data mask options */
for (i = 0; i < 4; i++) {
apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length);
@ -1511,25 +1496,62 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len
fold_dotstream(dot_stream, width, height, dot_array);
force_corners(width, height, dot_array);
mask_score[i + 4] = score_array(dot_array, height, width);
mask_score[i] = score_array(dot_array, height, width);
if (debug & ZINT_DEBUG_PRINT) {
printf("Mask %d score is %d\n", i + 4, mask_score[i + 4]);
printf("Mask %d score is %d\n", i, mask_score[i]);
}
}
for (i = 4; i < 8; i++) {
high_score = mask_score[0];
best_mask = 0;
for (i = 1; i < 4; i++) {
if (mask_score[i] >= high_score) {
high_score = mask_score[i];
best_mask = i;
}
}
}
if (debug & ZINT_DEBUG_PRINT) {
printf("Applying mask %d, high_score %d\n", best_mask, high_score);
/* Re-evaluate using forced corners if needed */
if (high_score <= (height * width) / 2) {
if (debug & ZINT_DEBUG_PRINT) {
printf("High score %d <= %d (height * width) / 2\n", high_score, (height * width) / 2);
}
for (i = 0; i < 4; i++) {
apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length);
dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
/* Add pad bits */
for (jc = dot_stream_length; jc < n_dots; jc++) {
strcat(dot_stream, "1");
}
fold_dotstream(dot_stream, width, height, dot_array);
force_corners(width, height, dot_array);
mask_score[i + 4] = score_array(dot_array, height, width);
if (debug & ZINT_DEBUG_PRINT) {
printf("Mask %d score is %d\n", i + 4, mask_score[i + 4]);
}
}
for (i = 4; i < 8; i++) {
if (mask_score[i] >= high_score) {
high_score = mask_score[i];
best_mask = i;
}
}
}
if (debug & ZINT_DEBUG_PRINT) {
printf("Applying mask %d, high_score %d\n", best_mask, high_score);
}
}
/* Apply best mask */

View File

@ -677,6 +677,7 @@ unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) {
case BARCODE_QRCODE:
case BARCODE_MICROQR:
case BARCODE_HANXIN:
case BARCODE_DOTCODE:
result |= ZINT_CAP_MASK;
break;
}

View File

@ -83,7 +83,7 @@ static void test_input(int index, int generate, int debug) {
/* 34*/ { DATA_MODE, -1, "\001\200\201\202\203\204\200\201\202\203\204", -1, 0, "65 41 70 31 5A 35 21 5A 5F 31 5A 35 21 5A 5F", "LatchA (0x65) SOH BinaryLatch (0x70) 0x80 0x81 0x82 0x83 0x80 0x81 0x82 0x83" },
/* 35*/ { UNICODE_MODE, -1, "\001abc\011\015\012\036", -1, 0, "65 41 65 41 42 43 61 60 64", "LatchA (0x65) SOH 6xShiftB (0x65) a b c HT CR/LF RS" },
};
int data_size = sizeof(data) / sizeof(struct item);
int data_size = ARRAY_SIZE(data);
char escaped[1024];
@ -94,15 +94,9 @@ static void test_input(int index, int generate, int debug) {
struct zint_symbol *symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = BARCODE_DOTCODE;
symbol->input_mode = data[i].input_mode;
if (data[i].eci != -1) {
symbol->eci = data[i].eci;
}
symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt
symbol->debug |= debug;
debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt
int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
int length = testUtilSetSymbol(symbol, BARCODE_DOTCODE, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
@ -112,7 +106,7 @@ static void test_input(int index, int generate, int debug) {
i, testUtilInputModeName(data[i].input_mode), data[i].eci, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
data[i].length, testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment);
} else {
if (ret < 5) {
if (ret < ZINT_ERROR) {
assert_zero(strcmp((char *) symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected);
}
}
@ -127,33 +121,26 @@ static void test_encode(int index, int generate, int debug) {
testStart("");
int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise
int ret;
struct item {
int input_mode;
int option_2;
int option_3;
char *data;
int length;
int ret;
int expected_rows;
int expected_width;
int bwipp_cmp;
char *comment;
char *expected;
};
// ISS DotCode, Rev 4.0, DRAFT 0.15, TSC Pre-PR #5, MAY 28, 2019
struct item data[] = {
/* 0*/ { UNICODE_MODE, -1, "2741", -1, 0, 10, 13, "ISS DotCode Rev 4.0 Figure 7B Mask = 2 prime (5)",
"1010001010101"
"0001000000000"
"1000100010101"
"0100000101000"
"0000101000100"
"0100010000010"
"1000101010001"
"0101010001000"
"1000100010101"
"0101000100010"
},
/* 1*/ { GS1_MODE, 64, "[01]00012345678905[17]201231[10]ABC123456", -1, 0, 9, 64, "ISS DotCode Rev 4.0 Figure 1 (left)",
/* 0*/ { GS1_MODE, 64, -1, "[01]00012345678905[17]201231[10]ABC123456", -1, 0, 9, 64, 1, "ISS DotCode Rev 4.0 Figure 1 (left), same",
"1010000000101000101010000010000010001010100010101000101000001010"
"0100010001010001010001000001010100010100010001000100010101000001"
"1010001010000000101010100010001010000010101000000010100010100000"
@ -163,8 +150,8 @@ static void test_encode(int index, int generate, int debug) {
"1000000010100010001000001000100010101000100010000010101000100000"
"0001010100010001010100010001010000010001010000000101010001010101"
"1000100010001000100010100010001010001000101000101000100010000010"
},
/* 2*/ { GS1_MODE, -1, "[01]00012345678905[17]201231[10]ABC123456", -1, 0, 20, 29, "ISS DotCode Rev 4.0 Figure 1 (right)",
},
/* 1*/ { GS1_MODE, -1, -1, "[01]00012345678905[17]201231[10]ABC123456", -1, 0, 20, 29, 1, "ISS DotCode Rev 4.0 Figure 1 (right) (and Figure 10), same",
"10101000101010100010101000101"
"00010100010100010100000001010"
"00001010100010000000101010000"
@ -185,8 +172,26 @@ static void test_encode(int index, int generate, int debug) {
"00010101000001010100010100010"
"10000010101000100000001000001"
"01000100010101010000000101010"
},
/* 3*/ { GS1_MODE, -1, "[17]070620[10]ABC123456", -1, 0, 16, 23, "ISS DotCode Rev 4.0 Figure 6, Mask = 1",
},
/* 2*/ { GS1_MODE, -1, 1 << 8, "[17]070620[10]ABC123456", -1, 0, 16, 23, 1, "ISS DotCode Rev 4.0 Figure 5 (and Figure 6 top-left) when Mask = 0, same",
"10101000100010000000001"
"01000101010001010000000"
"00100010001000101000100"
"01010001010000000101010"
"00001000100010100010101"
"00000101010101010000010"
"00100010101000000010001"
"00010100000101000100010"
"00001000001000001010101"
"01010101010001000001010"
"10100000100010001000101"
"01000100000100010101000"
"10000010000010100010001"
"00010000010100010101010"
"10101000001000101010001"
"01000001010101010000010"
},
/* 3*/ { GS1_MODE, -1, 2 << 8, "[17]070620[10]ABC123456", -1, 0, 16, 23, 1, "ISS DotCode Rev 4.0 Figure 6 top-right Mask = 1, same",
"10000000001010001000101"
"01010101000100000101000"
"00100010000000100000001"
@ -203,17 +208,179 @@ static void test_encode(int index, int generate, int debug) {
"01010001010001000001010"
"10000010101010100010101"
"01000101000101010101010"
},
/* 4*/ { GS1_MODE, 40, "[01]00012345678905", -1, 0, 7, 40, "ISS DotCode Rev 4.0 Figure 8, 7x40 **NOT SAME** but same if force mask 1 instead of mask 6",
"1010000010001010000010100000001010100010"
"0101010001000100010100000101010000010101"
"0000001010100010001010001000100000100010"
"0001000001000101010100000100010100010001"
"1000101010100000100000101000000010101010"
"0100010000010001000101000101010001000001"
"1010000010001000100010101000101000100010"
},
/* 5*/ { GS1_MODE, 18, "[01]00012345678905", -1, 0, 17, 18, "ISS DotCode Rev 4.0 Figure 8, 17x18 **NOT SAME** no matter what mask; but verified manually against bwipp and tec-it",
},
/* 4*/ { GS1_MODE, -1, 3 << 8, "[17]070620[10]ABC123456", -1, 0, 16, 23, 1, "ISS DotCode Rev 4.0 Figure 6 bottom-left Mask = 2, same",
"10100000101010100010001"
"01000101000100000000010"
"10101010001010000010000"
"01010100010000010101010"
"00001000101000001000101"
"00000000000001010000010"
"00100010101010101000001"
"00010101010100010000000"
"00001000100010101010001"
"01000000010101010101000"
"10100010100000101000101"
"00000000000101000001010"
"10000010000010100010101"
"01010100010100010001010"
"10101010000000001010001"
"01010101000001000101010"
},
/* 5*/ { GS1_MODE, -1, 4 << 8, "[17]070620[10]ABC123456", -1, 0, 16, 23, 1, "ISS DotCode Rev 4.0 Figure 6 bottom-right Mask = 3, same",
"10000000100000001010101"
"01010001010100010001000"
"10001000001010101010100"
"01010101000101010000010"
"10101010001000000010101"
"00000100000100010101000"
"00001000101010101000101"
"00000001010000000101010"
"00100010000000000000001"
"01010100010101010101010"
"10000000101010100010001"
"01010101000001010000010"
"10101010100000001000001"
"01000001010001000001010"
"10001000001010001000001"
"01010100000101000100010"
},
/* 6*/ { GS1_MODE, -1, -1, "[17]070620[10]ABC123456", -1, 0, 16, 23, 1, "ISS DotCode Rev 4.0 Figure 6 top-right, auto Mask = 1, same",
"10000000001010001000101"
"01010101000100000101000"
"00100010000000100000001"
"01010001000001000001000"
"10101010100000001010101"
"00000100010100000100010"
"00000000001010101010001"
"00010001010001000001000"
"00101010101000001010001"
"01000100000001010000000"
"10101000101000101000001"
"00010101000100010101010"
"10001000001010100000101"
"01010001010001000001010"
"10000010101010100010101"
"01000101000101010101010"
},
/* 7*/ { UNICODE_MODE, -1, 1 << 8, "2741", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Figure 7A top-left Mask = 0, same; BWIPP automatically primes mask",
"1010101010100"
"0000010001010"
"0000101000101"
"0101000000000"
"0000101010100"
"0100010101000"
"1000001000001"
"0101000101010"
"1000100010001"
"0000000000000"
},
/* 8*/ { UNICODE_MODE, -1, 2 << 8, "2741", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Figure 7A top-right Mask = 1, same; BWIPP automatically primes mask",
"1010001000101"
"0000000100010"
"0000100000001"
"0101010001000"
"1000101000000"
"0101010101010"
"1000101000101"
"0100010101010"
"0000000010001"
"0001000001000"
},
/* 9*/ { UNICODE_MODE, -1, 3 << 8, "2741", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Figure 7A bottom-left Mask = 2, same; BWIPP automatically primes mask",
"1010001010100"
"0001000000000"
"1000100010101"
"0100000101000"
"0000101000100"
"0100010000010"
"1000101010001"
"0101010001000"
"1000100010101"
"0001000100000"
},
/* 10*/ { UNICODE_MODE, -1, 4 << 8, "2741", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Figure 7A bottom-right Mask = 3, same; BWIPP automatically primes mask",
"1010001000100"
"0001000001010"
"1000001000000"
"0101000100010"
"1000101010100"
"0101010000010"
"1000100000000"
"0100000101000"
"1000001010001"
"0101010101010"
},
/* 11*/ { UNICODE_MODE, -1, 5 << 8, "2741", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Figure 7B top-left Mask = 0' (4), same",
"1010101010101"
"0000010001010"
"0000101000101"
"0101000000000"
"0000101010100"
"0100010101000"
"1000001000001"
"0101000101010"
"1000100010001"
"0100000000010"
},
/* 12*/ { UNICODE_MODE, -1, 6 << 8, "2741", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Figure 7B top-right Mask = 1' (5), same",
"1010001000101"
"0000000100010"
"0000100000001"
"0101010001000"
"1000101000000"
"0101010101010"
"1000101000101"
"0100010101010"
"1000000010001"
"0101000001010"
},
/* 13*/ { UNICODE_MODE, -1, 7 << 8, "2741", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Figure 7B bottom-left Mask = 2' (6), same",
"1010001010101"
"0001000000000"
"1000100010101"
"0100000101000"
"0000101000100"
"0100010000010"
"1000101010001"
"0101010001000"
"1000100010101"
"0101000100010"
},
/* 14*/ { UNICODE_MODE, -1, 8 << 8, "2741", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Figure 7B bottom-right Mask = 3' (7), same",
"1010001000101"
"0001000001010"
"1000001000000"
"0101000100010"
"1000101010100"
"0101010000010"
"1000100000000"
"0100000101000"
"1000001010001"
"0101010101010"
},
/* 15*/ { UNICODE_MODE, -1, -1, "2741", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Figure 7B bottom-left auto Mask = 2' (6), same",
"1010001010101"
"0001000000000"
"1000100010101"
"0100000101000"
"0000101000100"
"0100010000010"
"1000101010001"
"0101010001000"
"1000100010101"
"0101000100010"
},
/* 16*/ { GS1_MODE, 40, -1, "[01]00012345678905", -1, 0, 7, 40, 1, "ISS DotCode Rev 4.0 Figure 8 top-left 7x40, Mask = 1, same",
"1010101010001000100010100010101000001000"
"0000010101000100010100010000010001000001"
"1010001000001000001000101010001000101000"
"0001010101000000010100010001000001010001"
"1010100010001010000010001010000000101010"
"0001010001010001000100000001010100010001"
"1000100010001000100010100010001010001000"
},
/* 17*/ { GS1_MODE, 18, -1, "[01]00012345678905", -1, 0, 17, 18, 1, "ISS DotCode Rev 4.0 Figure 8 top-right 17x18 **NOT SAME** no matter what mask; but same as BWIPP and verified manually against tec-it",
"101000001000101010"
"010100000101010001"
"000000101000001010"
@ -231,8 +398,8 @@ static void test_encode(int index, int generate, int debug) {
"100010001010001010"
"010001010001000101"
"100010001000100010"
},
/* 6*/ { GS1_MODE, 35, "[01]00012345678905", -1, 0, 8, 35, "ISS DotCode Rev 4.0 Figure 8, 8x35; **NOT SAME** using mask 3 prime (7) not 3 so extra dot in bottom right corner compared to figure",
},
/* 18*/ { GS1_MODE, 35, -1, "[01]00012345678905", -1, 0, 8, 35, 1, "ISS DotCode Rev 4.0 Figure 8 bottom-left 8x35, Mask = 3, same",
"10100010000000000010100000100010101"
"00010101010001000000010100010100000"
"10001000101010101010001010000010101"
@ -240,9 +407,9 @@ static void test_encode(int index, int generate, int debug) {
"10101000100000101000100010001000001"
"00010100010000010001010001010000000"
"10000010101010101010000010000010001"
"01000001000101000100010100010001010"
},
/* 7*/ { GS1_MODE, 17, "[01]00012345678905", -1, 0, 18, 17, "ISS DotCode Rev 4.0 Figure 8, 18x17 **NOT SAME** no matter what mask; verified manually against bwipp and tec-it",
"01000001000101000100010100010001000"
},
/* 19*/ { GS1_MODE, 17, -1, "[01]00012345678905", -1, 0, 18, 17, 1, "ISS DotCode Rev 4.0 Figure 8 bottom-right 18x17 **NOT SAME** no matter what mask; same as BWIPP; verified manually against tec-it",
"10101000001000001"
"01000001010100010"
"00000000100010001"
@ -261,8 +428,8 @@ static void test_encode(int index, int generate, int debug) {
"01010100010101000"
"10101010101010101"
"01010101000101010"
},
/* 8*/ { UNICODE_MODE, 35, "Dots can be Square!", -1, 0, 18, 35, "ISS DotCode Rev 4.0 Figure 11 **NOT SAME**; verified manually against bwipp and tec-it",
},
/* 20*/ { UNICODE_MODE, 35, -1, "Dots can be Square!", -1, 0, 18, 35, 1, "ISS DotCode Rev 4.0 Figure 11 **NOT SAME**; same as BWIPP; verified manually against tec-it",
"10000010101000000000000000101010101"
"01010101000101000100010100000001000"
"00001000000010101000101010101010000"
@ -281,8 +448,56 @@ static void test_encode(int index, int generate, int debug) {
"01000101010101000100000100010101000"
"10101000101000001000100010101000101"
"01000001000001000101010001000000010"
},
/* 9*/ { GS1_MODE, -1, "[99]8766", -1, 0, 10, 13, "ISS DotCode Rev 4.0 Table G.1 Mask 0 prime (4); all mask scores match Table G.1",
},
/* 21*/ { GS1_MODE, -1, 1 << 8, "[99]8766", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Table G.1 Mask 0, same; BWIPP automatically primes mask",
"0000001010000"
"0001010000010"
"0000000010001"
"0100010101000"
"0010101000101"
"0100010101010"
"0010000010000"
"0101010000010"
"0010000000101"
"0101000101010"
},
/* 22*/ { GS1_MODE, -1, 2 << 8, "[99]8766", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Table G.1 Mask 1, same; BWIPP automatically primes mask",
"0000100000001"
"0001010000000"
"0000000000001"
"0101010000010"
"1010101010101"
"0100000101010"
"0010000010100"
"0100010101000"
"0010101000101"
"0100010101000"
},
/* 23*/ { GS1_MODE, -1, 3 << 8, "[99]8766", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Table G.1 Mask 2, same; BWIPP automatically primes mask",
"0000100010100"
"0000000000000"
"1000101010101"
"0100010101010"
"0010101000101"
"0101010101010"
"0010100000000"
"0101010100000"
"0000000010001"
"0100000001010"
},
/* 24*/ { GS1_MODE, -1, 4 << 8, "[99]8766", -1, 0, 10, 13, 0, "ISS DotCode Rev 4.0 Table G.1 Mask 3, same; BWIPP automatically primes mask",
"0000000000000"
"0001010001000"
"1000001010000"
"0101010100010"
"1010101000101"
"0101010101010"
"0010001000101"
"0101010101010"
"1000000010000"
"0100000000010"
},
/* 25*/ { GS1_MODE, -1, 5 << 8, "[99]8766", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Table G.1 Mask 0' (4), same",
"1000001010001"
"0001010000010"
"0000000010001"
@ -293,9 +508,57 @@ static void test_encode(int index, int generate, int debug) {
"0101010000010"
"1010000000101"
"0101000101010"
},
/* 10*/ { UNICODE_MODE, 6, "A", -1, 0, 19, 6, "ISS DotCode Rev 4.0 5.2.1.4 2) Table 4, 1 padding dot available; same as bwipp and tec-it except corners lit",
"101010"
},
/* 26*/ { GS1_MODE, -1, 6 << 8, "[99]8766", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Table G.1 Mask 1' (5), same",
"1000100000001"
"0001010000000"
"0000000000001"
"0101010000010"
"1010101010101"
"0100000101010"
"0010000010100"
"0100010101000"
"1010101000101"
"0100010101010"
},
/* 27*/ { GS1_MODE, -1, 7 << 8, "[99]8766", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Table G.1 Mask 2' (6), same",
"1000100010101"
"0000000000000"
"1000101010101"
"0100010101010"
"0010101000101"
"0101010101010"
"0010100000000"
"0101010100000"
"1000000010001"
"0100000001010"
},
/* 28*/ { GS1_MODE, -1, 8 << 8, "[99]8766", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Table G.1 Mask 3' (7), same",
"1000000000001"
"0001010001000"
"1000001010000"
"0101010100010"
"1010101000101"
"0101010101010"
"0010001000101"
"0101010101010"
"1000000010001"
"0100000000010"
},
/* 29*/ { GS1_MODE, -1, -1, "[99]8766", -1, 0, 10, 13, 1, "ISS DotCode Rev 4.0 Table G.1 auto Mask 0' (4); all mask scores match Table G.1",
"1000001010001"
"0001010000010"
"0000000010001"
"0100010101000"
"0010101000101"
"0100010101010"
"0010000010000"
"0101010000010"
"1010000000101"
"0101000101010"
},
/* 30*/ { UNICODE_MODE, 6, -1, "A", -1, 0, 19, 6, 1, "ISS DotCode Rev 4.0 5.2.1.4 2) Table 4, 1 padding dot available; verified manually against tec-it",
"101000"
"000101"
"101010"
"000001"
@ -312,12 +575,12 @@ static void test_encode(int index, int generate, int debug) {
"101010"
"000001"
"101000"
"010001"
"101010"
},
/* 11*/ { UNICODE_MODE, 94, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS", -1, 0, 37, 94, "Interleaved R-S; same as bwipp and tec-it except corners lit",
"010000"
"101000"
},
/* 31*/ { UNICODE_MODE, 94, -1, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS", -1, 0, 37, 94, 1, "Interleaved R-S; verified manually against tec-it",
"1000001010000000100010000010101010101000001000100000001010101000001000001000101010001000101010"
"0101010000000101000001010001010001010100010001000001000000010101010000000101010100010001010101"
"0101010000000101000001010001010001010100010001000001000000010101010000000101010100010001010100"
"0010101000100010000010101010000000101010000010101000001000100010100000100010100010001000101000"
"0000000100010101000001010000010000010101010100010100000100000101000100010001000001010001010001"
"0010100000100010101000001000101010000010001000001010100000101000101010000010001000101010100010"
@ -352,12 +615,23 @@ static void test_encode(int index, int generate, int debug) {
"0101010000010100010000010100000101010100000101000001000000010101000101000101010000000101010101"
"1000001010001010001000101000001000101010000010101000100010100000101000100000001000101010100000"
"0001000101010100000001010101000001010000010001010001000100010000010001000101010001010001000001"
"1010001000001010101000000010101000101000001000001010100000101010001000000010100000001010101010"
},
"0010001000001010101000000010101000101000001000001010100000101010001000000010100000001010101000"
},
/* 32*/ { GS1_MODE, 50, -1, "[17]070620[10]ABC123456", -1, 0, 7, 50, 1, "GS1 Gen Spec Figure 5.1-8.",
"10000010101000100010101010001000000010100000100000"
"01000101000101010100000100010000010001000001010101"
"00001010001000101000101000100010001010100000000010"
"01000001000100000101010101010001000001000101000001"
"10001000001010100010001010100000100010100010000010"
"00010001010000000100010101000100010001010001000101"
"10001000001010101000001000100010100010100000101010"
},
};
int data_size = sizeof(data) / sizeof(struct item);
int data_size = ARRAY_SIZE(data);
char escaped[1024];
char bwipp_buf[8192];
char bwipp_msg[1024];
for (int i = 0; i < data_size; i++) {
@ -366,33 +640,38 @@ static void test_encode(int index, int generate, int debug) {
struct zint_symbol *symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = BARCODE_DOTCODE;
symbol->input_mode = data[i].input_mode;
if (data[i].option_2 != -1) {
symbol->option_2 = data[i].option_2;
}
symbol->debug |= debug;
int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
int length = testUtilSetSymbol(symbol, BARCODE_DOTCODE, data[i].input_mode, -1 /*eci*/, -1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, data[i].length, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
if (generate) {
printf(" /*%3d*/ { %s, %d, \"%s\", %d, %s, %d, %d, \"%s\",\n",
i, testUtilInputModeName(data[i].input_mode), data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length,
testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment);
printf(" /*%3d*/ { %s, %d, %s, \"%s\", %d, %s, %d, %d, %d, \"%s\",\n",
i, testUtilInputModeName(data[i].input_mode), data[i].option_2, testUtilOption3Name(data[i].option_3),
testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length,
testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment);
testUtilModulesDump(symbol, " ", "\n");
printf(" },\n");
printf(" },\n");
} else {
if (ret < 5) {
if (ret < ZINT_ERROR) {
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
if (ret == 0) {
int width, row;
ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row);
assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data);
int width, row;
ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row);
assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data);
if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, data[i].option_3, debug)) {
if (!data[i].bwipp_cmp) {
if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not BWIPP compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment);
} else {
ret = testUtilBwipp(i, symbol, -1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf));
assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected);
assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n",
i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected);
}
}
}
}
@ -440,7 +719,7 @@ static void test_fuzz(int index, int debug) {
/* 5*/ { "\237\032", -1, DATA_MODE, 0 }, // As above L904
/* 6*/ { "\237", -1, DATA_MODE, 0 }, // As above L1090
};
int data_size = sizeof(data) / sizeof(struct item);
int data_size = ARRAY_SIZE(data);
for (int i = 0; i < data_size; i++) {
@ -449,13 +728,7 @@ static void test_fuzz(int index, int debug) {
struct zint_symbol *symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = BARCODE_DOTCODE;
if (data[i].input_mode != -1) {
symbol->input_mode = data[i].input_mode;
}
symbol->debug |= debug;
int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
int length = testUtilSetSymbol(symbol, BARCODE_DOTCODE, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
@ -484,7 +757,7 @@ static void test_large(int index, int debug) {
/* 2*/ { 200, '9', 200, 0 }, // Changes a number of mask scores re pre-Rev. 4 version, but best score still the same (7)
/* 3*/ { 30, '\001', 71, 0 }, // Codeword length 72, ECC length 39, for ND + 1 == 112
};
int data_size = sizeof(data) / sizeof(struct item);
int data_size = ARRAY_SIZE(data);
char data_buf[4096];
@ -495,14 +768,9 @@ static void test_large(int index, int debug) {
struct zint_symbol *symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = BARCODE_DOTCODE;
symbol->input_mode = DATA_MODE;
symbol->option_2 = data[i].option_2;
symbol->debug |= debug;
memset(data_buf, data[i].datum, data[i].length);
int length = data[i].length;
memset(data_buf, data[i].datum, length);
int length = testUtilSetSymbol(symbol, BARCODE_DOTCODE, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data_buf, data[i].length, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);

View File

@ -1,6 +1,6 @@
/*
libzint - the open source barcode library
Copyright (C) 2019 - 2020 Robin Stuart <rstuart114@gmail.com>
Copyright (C) 2019 - 2021 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -1800,7 +1800,7 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol
{ "hibcazteccode", BARCODE_HIBC_AZTEC, 112, 1, 0, 1, 0, 0, },
{ "", -1, 113, 0, 0, 0, 0, 0, },
{ "", -1, 114, 0, 0, 0, 0, 0, },
{ "dotcode", BARCODE_DOTCODE, 115, 0, 0, 0, 0, 0, },
{ "dotcode", BARCODE_DOTCODE, 115, 0, 1, 1, 0, 0, },
{ "hanxin", BARCODE_HANXIN, 116, 0, 0, 0, 0, 0, },
{ "", -1, 117, 0, 0, 0, 0, 0, },
{ "", -1, 118, 0, 0, 0, 0, 0, },
@ -1898,6 +1898,11 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol
printf("i:%d %s not BWIPP compatible, GS1_MODE not supported\n", index, testUtilBarcodeName(symbology));
}
return NULL;
} else if (symbology == BARCODE_DOTCODE) {
if (gs1_cvt) {
*gs1_cvt = 1;
}
return "gs1dotcode";
}
}
@ -2034,6 +2039,7 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int
int bwipp_row_height[symbol->rows];
int linear_row_height;
int gs1_cvt;
int user_mask;
FILE *fp = NULL;
int cnt;
@ -2312,6 +2318,18 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int
if (option_3 != -1) {
bwipp_opts = bwipp_opts_buf;
}
} else if (symbology == BARCODE_DOTCODE) {
if (option_2 > 0) {
sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%scolumns=%d", strlen(bwipp_opts_buf) ? " " : "", symbol->option_2);
bwipp_opts = bwipp_opts_buf;
}
if (option_3 != -1) {
user_mask = (option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 8 */
if (user_mask >= 1 && user_mask <= 8) {
sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%smask=%d", strlen(bwipp_opts_buf) ? " " : "", (user_mask - 1) % 4);
bwipp_opts = bwipp_opts_buf;
}
}
}
}

View File

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright (C) 2020 Robin Stuart <rstuart114@gmail.com>
# Copyright (C) 2020 - 2021 Robin Stuart <rstuart114@gmail.com>
# vim: set ts=4 sw=4 et :
set -e
@ -25,6 +25,7 @@ run_bwipp_test "test_code16k" "encode"
run_bwipp_test "test_code49" "encode"
run_bwipp_test "test_composite"
run_bwipp_test "test_dmatrix" "encode"
run_bwipp_test "test_dotcode" "encode"
run_bwipp_test "test_gs1" "gs1_reduce"
run_bwipp_test "test_imail" "encode"
run_bwipp_test "test_medical" "encode"

View File

@ -109,6 +109,8 @@
2021-01-14 HaO
- Added detection of presence of the Tk package and late initialization.
This is a preparation to add a TCL only mode to the DLL.
2021-01-22 GL
- -cols maximum changed from 67 to 108 (DotCode)
*/
#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
@ -431,7 +433,7 @@ static char help_message[] = "zint tcl(stub,obj) dll\n"
" -border integer: width of a border around the symbol. Use with -bind/-box 1\n"
" -box bool: box around bar code, size set be -border\n"
/* cli option --cmyk not supported as no corresponding output */
" -cols integer: PDF417, Codablock F: number of columns\n"
" -cols integer: PDF417, Codablock F, DotCode: number of columns\n"
/* cli option --data is standard parameter */
" -dmre bool: Allow Data Matrix Rectangular Extended\n"
" -dotsize number: radius ratio of dots from 0.01 to 1.0\n"
@ -449,9 +451,9 @@ static char help_message[] = "zint tcl(stub,obj) dll\n"
" -height integer: Symbol height in modules\n"
/* cli option --input not supported */
" -init bool: Create reader initialisation symbol (Code 128, Data Matrix)\n"
" number: Set encoding mode (MaxiCode/Composite)\n"
" -mask number: set masking pattern to use (QR/MicroQR/HanXin/DotCode)\n"
/* cli option --mirror not supported */
" -mode: Structured primary data mode (MaxiCode, Composite)\n"
" -mode number: set encoding mode (MaxiCode, Composite)\n"
" -nobackground bool: set background transparent\n"
" -notext bool: no interpretation line\n"
/* cli option --output not supported */
@ -977,7 +979,7 @@ static int Encode(Tcl_Interp *interp, int objc,
case iVers:
/* >> Int in Option 2 */
if (intValue < 1
|| (optionIndex==iCols && intValue > 67)
|| (optionIndex==iCols && intValue > 108)
|| (optionIndex==iVers && intValue > 47))
{
Tcl_SetObjResult(interp,

View File

@ -2561,11 +2561,17 @@ DotCode uses a grid of dots in a rectangular formation to encode characters up
to a maximum of approximately 450 characters (or 900 numeric digits). The
symbology supports ECI encoding and GS1 data encoding. By default Zint will
produce a symbol which is approximately square, however the width of the symbol
can be adjusted by using the --cols= option or by setting option_2. Outputting
DotCode to raster images (PNG, GIF, BMP, PCX) will require setting the scale of
the image to a larger value than the default (e.g. approx 10) for the dots to
be plotted correctly. Approximately 33% of the resulting symbol is comprised of
error correction codewords.
can be adjusted by using the --cols= option or by setting option_2 (maximum
108). Outputting DotCode to raster images (PNG, GIF, BMP, PCX) will require
setting the scale of the image to a larger value than the default (e.g. approx
10) for the dots to be plotted correctly. Approximately 33% of the resulting
symbol is comprised of error correction codewords.
DotCode has two sets of 4 masks, designated 0-3 and 0'-3', the second "prime"
set being the same as the first with corners lit. The best mask to use is
selected automatically by Zint but may be manually specified by using the
--mask= switch with values 0-7, where 4-7 denote 0'-3', or by setting option_3
to (N + 1) << 8 where N is 0-7.
6.6.12 Han Xin Code
-------------------

View File

@ -138,7 +138,7 @@ static void usage(void) {
" --height=NUMBER Set height of symbol in multiples of X-dimension\n"
" -i, --input=FILE Read input data from FILE\n"
" --init Create reader initialisation/programming symbol\n"
" --mask=NUMBER Set masking pattern to use (QR/Han Xin)\n"
" --mask=NUMBER Set masking pattern to use (QR/Han Xin/DotCode)\n"
" --mirror Use batch data to determine filename\n"
" --mode=NUMBER Set encoding mode (MaxiCode/Composite)\n"
" --nobackground Remove background (PNG/SVG/EPS only)\n"
@ -904,7 +904,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error 131: Invalid columns value\n");
return do_exit(1);
}
if ((val >= 1) && (val <= 67)) {
if ((val >= 1) && (val <= 108)) {
my_symbol->option_2 = val;
} else {
fprintf(stderr, "Warning 111: Number of columns out of range\n");

View File

@ -554,7 +554,7 @@ static void test_checks(int index, int debug) {
/* 4*/ { -1, 1001, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 108: Border width out of range" },
/* 5*/ { -1, -1, -1, 0.009, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 106: Invalid dot radius value" },
/* 6*/ { -1, -1, -2, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 131: Invalid columns value" },
/* 7*/ { -1, -1, 68, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 111: Number of columns out of range" },
/* 7*/ { -1, -1, 109, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 111: Number of columns out of range" },
/* 8*/ { -1, -1, -1, -1, -2, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 138: Invalid ECI value" },
/* 9*/ { -1, -1, -1, -1, 1000000, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 118: Invalid ECI code" },
/* 10*/ { -1, -1, -1, -1, -1, "jpg", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 142: File type 'jpg' not supported, ignoring" },

View File

@ -295,6 +295,358 @@
<string>50</string>
</property>
</item>
<item>
<property name="text">
<string>51</string>
</property>
</item>
<item>
<property name="text">
<string>52</string>
</property>
</item>
<item>
<property name="text">
<string>53</string>
</property>
</item>
<item>
<property name="text">
<string>54</string>
</property>
</item>
<item>
<property name="text">
<string>55</string>
</property>
</item>
<item>
<property name="text">
<string>56</string>
</property>
</item>
<item>
<property name="text">
<string>57</string>
</property>
</item>
<item>
<property name="text">
<string>58</string>
</property>
</item>
<item>
<property name="text">
<string>59</string>
</property>
</item>
<item>
<property name="text">
<string>60</string>
</property>
</item>
<item>
<property name="text">
<string>61</string>
</property>
</item>
<item>
<property name="text">
<string>62</string>
</property>
</item>
<item>
<property name="text">
<string>63</string>
</property>
</item>
<item>
<property name="text">
<string>64</string>
</property>
</item>
<item>
<property name="text">
<string>65</string>
</property>
</item>
<item>
<property name="text">
<string>66</string>
</property>
</item>
<item>
<property name="text">
<string>67</string>
</property>
</item>
<item>
<property name="text">
<string>68</string>
</property>
</item>
<item>
<property name="text">
<string>69</string>
</property>
</item>
<item>
<property name="text">
<string>70</string>
</property>
</item>
<item>
<property name="text">
<string>71</string>
</property>
</item>
<item>
<property name="text">
<string>72</string>
</property>
</item>
<item>
<property name="text">
<string>73</string>
</property>
</item>
<item>
<property name="text">
<string>74</string>
</property>
</item>
<item>
<property name="text">
<string>75</string>
</property>
</item>
<item>
<property name="text">
<string>76</string>
</property>
</item>
<item>
<property name="text">
<string>77</string>
</property>
</item>
<item>
<property name="text">
<string>78</string>
</property>
</item>
<item>
<property name="text">
<string>79</string>
</property>
</item>
<item>
<property name="text">
<string>80</string>
</property>
</item>
<item>
<property name="text">
<string>81</string>
</property>
</item>
<item>
<property name="text">
<string>82</string>
</property>
</item>
<item>
<property name="text">
<string>83</string>
</property>
</item>
<item>
<property name="text">
<string>84</string>
</property>
</item>
<item>
<property name="text">
<string>85</string>
</property>
</item>
<item>
<property name="text">
<string>86</string>
</property>
</item>
<item>
<property name="text">
<string>87</string>
</property>
</item>
<item>
<property name="text">
<string>88</string>
</property>
</item>
<item>
<property name="text">
<string>89</string>
</property>
</item>
<item>
<property name="text">
<string>90</string>
</property>
</item>
<item>
<property name="text">
<string>91</string>
</property>
</item>
<item>
<property name="text">
<string>92</string>
</property>
</item>
<item>
<property name="text">
<string>93</string>
</property>
</item>
<item>
<property name="text">
<string>94</string>
</property>
</item>
<item>
<property name="text">
<string>95</string>
</property>
</item>
<item>
<property name="text">
<string>96</string>
</property>
</item>
<item>
<property name="text">
<string>97</string>
</property>
</item>
<item>
<property name="text">
<string>98</string>
</property>
</item>
<item>
<property name="text">
<string>99</string>
</property>
</item>
<item>
<property name="text">
<string>100</string>
</property>
</item>
<item>
<property name="text">
<string>101</string>
</property>
</item>
<item>
<property name="text">
<string>102</string>
</property>
</item>
<item>
<property name="text">
<string>103</string>
</property>
</item>
<item>
<property name="text">
<string>104</string>
</property>
</item>
<item>
<property name="text">
<string>105</string>
</property>
</item>
<item>
<property name="text">
<string>106</string>
</property>
</item>
<item>
<property name="text">
<string>107</string>
</property>
</item>
<item>
<property name="text">
<string>108</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelDotMask">
<property name="text">
<string>&amp;Mask:</string>
</property>
<property name="buddy">
<cstring>cmbDotMask</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cmbDotMask">
<property name="maxVisibleItems">
<number>8</number>
</property>
<item>
<property name="text">
<string>Automatic</string>
</property>
</item>
<item>
<property name="text">
<string>0</string>
</property>
</item>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>0'</string>
</property>
</item>
<item>
<property name="text">
<string>1'</string>
</property>
</item>
<item>
<property name="text">
<string>2'</string>
</property>
</item>
<item>
<property name="text">
<string>3'</string>
</property>
</item>
</widget>
</item>
</layout>

View File

@ -664,6 +664,7 @@ void MainWindow::change_options()
file.close();
tabMain->insertTab(1,m_optionWidget,tr("DotCod&e"));
connect(m_optionWidget->findChild<QObject*>("cmbDotCols"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview()));
connect(m_optionWidget->findChild<QObject*>("cmbDotMask"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview()));
connect(m_optionWidget->findChild<QObject*>("radDotStand"), SIGNAL(clicked( bool )), SLOT(update_preview()));
connect(m_optionWidget->findChild<QObject*>("radDotGS1"), SIGNAL(clicked( bool )), SLOT(update_preview()));
}
@ -1297,6 +1298,10 @@ void MainWindow::update_preview()
case BARCODE_DOTCODE:
m_bc.bc.setSymbol(BARCODE_DOTCODE);
m_bc.bc.setOption2(m_optionWidget->findChild<QComboBox*>("cmbDotCols")->currentIndex());
item_val = m_optionWidget->findChild<QComboBox*>("cmbDotMask")->currentIndex();
if (item_val) {
m_bc.bc.setOption3((item_val << 8) | m_bc.bc.option3());
}
set_gs1_mode(m_optionWidget->findChild<QRadioButton*>("radDotGS1")->isChecked());
break;
@ -1941,6 +1946,7 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) {
case BARCODE_DOTCODE:
settings.setValue("studio/bc/dotcode/cols", get_combobox_index("cmbDotCols"));
settings.setValue("studio/bc/dotcode/mask", get_combobox_index("cmbDotMask"));
settings.setValue("studio/bc/dotcode/encoding_mode", get_button_group_index(QStringList() << "radDotStand" << "radDotGS1"));
break;
@ -2169,6 +2175,7 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) {
case BARCODE_DOTCODE:
set_combobox_from_setting(settings, "studio/bc/dotcode/cols", "cmbDotCols");
set_combobox_from_setting(settings, "studio/bc/dotcode/mask", "cmbDotMask");
set_radiobutton_from_setting(settings, "studio/bc/dotcode/encoding_mode", QStringList() << "radDotStand" << "radDotGS1");
break;