mirror of
https://github.com/zint/zint
synced 2024-11-16 20:57:25 +13:00
Implement new mask grading with forced corners in Dot Code
This commit is contained in:
parent
7409399438
commit
053c83d036
@ -105,6 +105,7 @@ const int score_array(char Dots[], int Hgt, int Wid) {
|
|||||||
int x, y, worstedge, first, last, sum;
|
int x, y, worstedge, first, last, sum;
|
||||||
int penalty_local = 0;
|
int penalty_local = 0;
|
||||||
int penalty = 0;
|
int penalty = 0;
|
||||||
|
int t = 0, b = 0, l = 0, r = 0;
|
||||||
|
|
||||||
// first, guard against "pathelogical" gaps in the array
|
// first, guard against "pathelogical" gaps in the array
|
||||||
if (Hgt & 1) {
|
if (Hgt & 1) {
|
||||||
@ -165,6 +166,10 @@ const int score_array(char Dots[], int Hgt, int Wid) {
|
|||||||
worstedge = sum + last - first;
|
worstedge = sum + last - first;
|
||||||
worstedge *= Hgt;
|
worstedge *= Hgt;
|
||||||
|
|
||||||
|
if (sum == 0) {
|
||||||
|
t = 1;
|
||||||
|
}
|
||||||
|
|
||||||
sum = 0;
|
sum = 0;
|
||||||
first = -1;
|
first = -1;
|
||||||
last = -1;
|
last = -1;
|
||||||
@ -184,6 +189,10 @@ const int score_array(char Dots[], int Hgt, int Wid) {
|
|||||||
worstedge = sum;
|
worstedge = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sum == 0) {
|
||||||
|
b = 2;
|
||||||
|
}
|
||||||
|
|
||||||
sum = 0;
|
sum = 0;
|
||||||
first = -1;
|
first = -1;
|
||||||
last = -1;
|
last = -1;
|
||||||
@ -203,6 +212,10 @@ const int score_array(char Dots[], int Hgt, int Wid) {
|
|||||||
worstedge = sum;
|
worstedge = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sum == 0) {
|
||||||
|
l = 4;
|
||||||
|
}
|
||||||
|
|
||||||
sum = 0;
|
sum = 0;
|
||||||
first = -1;
|
first = -1;
|
||||||
last = -1;
|
last = -1;
|
||||||
@ -222,6 +235,12 @@ const int score_array(char Dots[], int Hgt, int Wid) {
|
|||||||
worstedge = sum;
|
worstedge = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sum == 0) {
|
||||||
|
r = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
penalty += (t + b + l + r) * 100000;
|
||||||
|
|
||||||
// throughout the array, count the # of unprinted 5-somes (cross patterns)
|
// throughout the array, count the # of unprinted 5-somes (cross patterns)
|
||||||
// plus the # of printed dots surrounded by 8 unprinted neighbors
|
// plus the # of printed dots surrounded by 8 unprinted neighbors
|
||||||
sum = 0;
|
sum = 0;
|
||||||
@ -1057,7 +1076,7 @@ int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
printf("\n\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_length;
|
return array_length;
|
||||||
@ -1190,19 +1209,76 @@ void fold_dotstream(char dot_stream[], int width, int height, char dot_array[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void apply_mask(int mask, int data_length, unsigned char *masked_codeword_array, unsigned char *codeword_array, int ecc_length, char *dot_stream) {
|
||||||
|
int weight = 0;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
switch (mask) {
|
||||||
|
case 0:
|
||||||
|
masked_codeword_array[0] = 0;
|
||||||
|
for (j = 0; j < data_length; j++) {
|
||||||
|
masked_codeword_array[j + 1] = codeword_array[j];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
masked_codeword_array[0] = 1;
|
||||||
|
for (j = 0; j < data_length; j++) {
|
||||||
|
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
||||||
|
weight += 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
masked_codeword_array[0] = 2;
|
||||||
|
for (j = 0; j < data_length; j++) {
|
||||||
|
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
||||||
|
weight += 7;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
masked_codeword_array[0] = 3;
|
||||||
|
for (j = 0; j < data_length; j++) {
|
||||||
|
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
||||||
|
weight += 17;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsencode(data_length + 1, ecc_length, masked_codeword_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
void force_corners(int width, int height, char *dot_array) {
|
||||||
|
if (width % 2) {
|
||||||
|
// "Vertical" symbol
|
||||||
|
dot_array[0] = '1';
|
||||||
|
dot_array[width - 1] = '1';
|
||||||
|
dot_array[(height - 2) * width] = '1';
|
||||||
|
dot_array[((height - 1) * width) - 1] = '1';
|
||||||
|
dot_array[((height - 1) * width) + 1] = '1';
|
||||||
|
dot_array[(height * width) - 2] = '1';
|
||||||
|
} else {
|
||||||
|
// "Horizontal" symbol
|
||||||
|
dot_array[0] = '1';
|
||||||
|
dot_array[width - 2] = '1';
|
||||||
|
dot_array[(2 * width) - 1] = '1';
|
||||||
|
dot_array[((height - 1) * width) - 1] = '1';
|
||||||
|
dot_array[(height - 1) * width] = '1';
|
||||||
|
dot_array[(height * width) - 2] = '1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length) {
|
int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length) {
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
size_t jc, n_dots;
|
size_t jc, n_dots;
|
||||||
int data_length, ecc_length;
|
int data_length, ecc_length;
|
||||||
int min_dots, min_area;
|
int min_dots, min_area;
|
||||||
int height, width;
|
int height, width;
|
||||||
int mask_score[4];
|
int mask_score[8];
|
||||||
int weight;
|
|
||||||
size_t dot_stream_length;
|
size_t dot_stream_length;
|
||||||
int high_score, best_mask;
|
int high_score, best_mask;
|
||||||
int binary_finish = 0;
|
int binary_finish = 0;
|
||||||
int debug = 0;
|
int debug = symbol->debug;
|
||||||
int padding_dots, is_first;
|
int padding_dots, is_first;
|
||||||
|
int corners_forced = 0;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
unsigned char* masked_codeword_array;
|
unsigned char* masked_codeword_array;
|
||||||
#endif
|
#endif
|
||||||
@ -1226,6 +1302,11 @@ int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length
|
|||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
printf("Codeword length = %d, ECC length = %d\n", data_length, ecc_length);
|
printf("Codeword length = %d, ECC length = %d\n", data_length, ecc_length);
|
||||||
|
printf("Codewords: ");
|
||||||
|
for (i = 0; i < data_length; i++) {
|
||||||
|
printf("[%d] ",codeword_array[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
min_dots = 9 * (data_length + 3 + (data_length / 2)) + 2;
|
min_dots = 9 * (data_length + 3 + (data_length / 2)) + 2;
|
||||||
@ -1339,40 +1420,8 @@ int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length
|
|||||||
|
|
||||||
/* Evaluate data mask options */
|
/* Evaluate data mask options */
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
masked_codeword_array[0] = 0;
|
|
||||||
for (j = 0; j < data_length; j++) {
|
|
||||||
masked_codeword_array[j + 1] = codeword_array[j];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
weight = 0;
|
|
||||||
masked_codeword_array[0] = 1;
|
|
||||||
for (j = 0; j < data_length; j++) {
|
|
||||||
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
|
||||||
weight += 3;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
weight = 0;
|
|
||||||
masked_codeword_array[0] = 2;
|
|
||||||
for (j = 0; j < data_length; j++) {
|
|
||||||
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
|
||||||
weight += 7;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
weight = 0;
|
|
||||||
masked_codeword_array[0] = 3;
|
|
||||||
for (j = 0; j < data_length; j++) {
|
|
||||||
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
|
||||||
weight += 17;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsencode(data_length + 1, ecc_length, masked_codeword_array);
|
apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length, dot_stream);
|
||||||
|
|
||||||
dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
|
dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
|
||||||
|
|
||||||
@ -1400,34 +1449,14 @@ int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best_mask != 3) {
|
/* Re-evaluate using forced corners if needed */
|
||||||
/* Reprocess to get symbol with best mask */
|
if (best_mask <= (height * width) / 2) {
|
||||||
switch (best_mask) {
|
corners_forced = 1;
|
||||||
case 0:
|
|
||||||
masked_codeword_array[0] = 0;
|
for (i = 0; i < 4; i++) {
|
||||||
for (j = 0; j < data_length; j++) {
|
|
||||||
masked_codeword_array[j + 1] = codeword_array[j];
|
apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length, dot_stream);
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
weight = 0;
|
|
||||||
masked_codeword_array[0] = 1;
|
|
||||||
for (j = 0; j < data_length; j++) {
|
|
||||||
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
|
||||||
weight += 3;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
weight = 0;
|
|
||||||
masked_codeword_array[0] = 2;
|
|
||||||
for (j = 0; j < data_length; j++) {
|
|
||||||
masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
|
|
||||||
weight += 7;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsencode(data_length + 1, ecc_length, masked_codeword_array);
|
|
||||||
dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
|
dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
|
||||||
|
|
||||||
/* Add pad bits */
|
/* Add pad bits */
|
||||||
@ -1436,15 +1465,38 @@ int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length
|
|||||||
}
|
}
|
||||||
|
|
||||||
fold_dotstream(dot_stream, width, height, dot_array);
|
fold_dotstream(dot_stream, width, height, dot_array);
|
||||||
} /* else { the version with the best mask is already in memory } */
|
|
||||||
|
force_corners(width, height, dot_array);
|
||||||
|
|
||||||
|
mask_score[i] = score_array(dot_array, height, width);
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
for (k = 0; k < height; k++) {
|
printf("Mask %d score is %d\n", i, mask_score[i]);
|
||||||
for (j = 0; j < width; j++) {
|
|
||||||
printf("%c", dot_array[(k * width) + j]);
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (mask_score[i] > high_score) {
|
||||||
|
high_score = mask_score[i];
|
||||||
|
best_mask = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply best mask */
|
||||||
|
apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length, dot_stream);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (corners_forced) {
|
||||||
|
force_corners(width, height, dot_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy values to symbol */
|
/* Copy values to symbol */
|
||||||
|
Loading…
Reference in New Issue
Block a user