Han Xin: Plot finder and alignment patterns

This commit is contained in:
Robin Stuart 2016-04-09 17:01:21 +01:00
parent a5440244c4
commit 64396488e8
2 changed files with 450 additions and 34 deletions

View File

@ -41,11 +41,31 @@
#include "reedsol.h"
#include "hanxin.h"
/* Find which submode to use for a text character */
int getsubmode(char input) {
int submode = 2;
if ((input >= '0') && (input <= '9')) {
submode = 1;
}
if ((input >= 'A') && (input <= 'Z')) {
submode = 1;
}
if ((input >= 'a') && (input <= 'z')) {
submode = 1;
}
return submode;
}
/* Calculate the approximate length of the binary string */
int calculate_binlength(char mode[], int length) {
int calculate_binlength(char mode[], const unsigned char source[], int length) {
int i;
char lastmode = ' ';
int est_binlen = 0;
int submode = 1;
for (i = 0; i < length; i++) {
switch (mode[i]) {
@ -60,6 +80,11 @@ int calculate_binlength(char mode[], int length) {
if (lastmode != 't') {
est_binlen += 10;
lastmode = 't';
submode = 1;
}
if (getsubmode((char) source[i]) != submode) {
est_binlen += 6;
submode = getsubmode((char) source[i]);
}
est_binlen += 6;
case 'b':
@ -101,25 +126,6 @@ void hx_define_mode(char mode[], const unsigned char source[], int length) {
mode[length] = '\0';
}
/* Find which submode to use for a text character */
int getsubmode(char input) {
int submode = 2;
if ((input >= '0') && (input <= '9')) {
submode = 1;
}
if ((input >= 'A') && (input <= 'Z')) {
submode = 1;
}
if ((input >= 'a') && (input <= 'z')) {
submode = 1;
}
return submode;
}
/* Convert Text 1 sub-mode character to encoding value, as given in table 3 */
int lookup_text1(char input) {
int encoding_value = 0;
@ -341,22 +347,363 @@ void calculate_binary(char binary[], char mode[], const unsigned char source[],
} while (position < length);
}
/* Finder pattern for top left of symbol */
void hx_place_finder_top_left(unsigned char* grid, int size) {
int xp, yp;
int x = 0, y = 0;
int finder[] = {
1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0,
1, 0, 1, 1, 1, 1, 1,
1, 0, 1, 0, 0, 0, 0,
1, 0, 1, 0, 1, 1, 1,
1, 0, 1, 0, 1, 1, 1,
1, 0, 1, 0, 1, 1, 1
};
for (xp = 0; xp < 7; xp++) {
for (yp = 0; yp < 7; yp++) {
if (finder[xp + (7 * yp)] == 1) {
grid[((yp + y) * size) + (xp + x)] = 0x11;
} else {
grid[((yp + y) * size) + (xp + x)] = 0x10;
}
}
}
}
/* Finder pattern for top right and bottom left of symbol */
void hx_place_finder(unsigned char* grid, int size, int x, int y) {
int xp, yp;
int finder[] = {
1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 0, 1,
0, 0, 0, 0, 1, 0, 1,
1, 1, 1, 0, 1, 0, 1,
1, 1, 1, 0, 1, 0, 1,
1, 1, 1, 0, 1, 0, 1
};
for (xp = 0; xp < 7; xp++) {
for (yp = 0; yp < 7; yp++) {
if (finder[xp + (7 * yp)] == 1) {
grid[((yp + y) * size) + (xp + x)] = 0x11;
} else {
grid[((yp + y) * size) + (xp + x)] = 0x10;
}
}
}
}
/* Finder pattern for bottom right of symbol */
void hx_place_finder_bottom_right(unsigned char* grid, int size) {
int xp, yp;
int x = size - 7, y = size - 7;
int finder[] = {
1, 1, 1, 0, 1, 0, 1,
1, 1, 1, 0, 1, 0, 1,
1, 1, 1, 0, 1, 0, 1,
0, 0, 0, 0, 1, 0, 1,
1, 1, 1, 1, 1, 0, 1,
0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1
};
for (xp = 0; xp < 7; xp++) {
for (yp = 0; yp < 7; yp++) {
if (finder[xp + (7 * yp)] == 1) {
grid[((yp + y) * size) + (xp + x)] = 0x11;
} else {
grid[((yp + y) * size) + (xp + x)] = 0x10;
}
}
}
}
/* Avoid plotting outside symbol or over finder patterns */
void hx_safe_plot(unsigned char *grid, int size, int x, int y, int value) {
if ((x >= 0) && (x < size)) {
if ((y >= 0) && (y < size)) {
if (grid[(y * size) + x] == 0) {
grid[(y * size) + x] = value;
}
}
}
}
/* Plot an alignment pattern around top and right of a module */
void hx_plot_alignment(unsigned char *grid, int size, int x, int y, int w, int h) {
int i;
hx_safe_plot(grid, size, x, y, 0x11);
hx_safe_plot(grid, size, x - 1, y + 1, 0x10);
for (i = 1; i <= w; i++) {
/* Top */
hx_safe_plot(grid, size, x - i, y, 0x11);
hx_safe_plot(grid, size, x - i - 1, y + 1, 0x10);
}
for (i = 1; i < h; i++) {
/* Right */
hx_safe_plot(grid, size, x, y + i, 0x11);
hx_safe_plot(grid, size, x - 1, y + i + 1, 0x10);
}
}
/* Plot assistany alignment patterns */
void hx_plot_assistant(unsigned char *grid, int size, int x, int y) {
hx_safe_plot(grid, size, x - 1, y - 1, 0x10);
hx_safe_plot(grid, size, x, y - 1, 0x10);
hx_safe_plot(grid, size, x + 1, y - 1, 0x10);
hx_safe_plot(grid, size, x - 1, y, 0x10);
hx_safe_plot(grid, size, x, y, 0x11);
hx_safe_plot(grid, size, x + 1, y, 0x10);
hx_safe_plot(grid, size, x - 1, y + 1, 0x10);
hx_safe_plot(grid, size, x, y + 1, 0x10);
hx_safe_plot(grid, size, x + 1, y + 1, 0x10);
}
/* Put static elements in the grid */
void hx_setup_grid(unsigned char* grid, int size, int version) {
int i, j;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
grid[(i * size) + j] = 0;
}
}
/* Add finder patterns */
hx_place_finder_top_left(grid, size);
hx_place_finder(grid, size, 0, size - 7);
hx_place_finder(grid, size, size - 7, 0);
hx_place_finder_bottom_right(grid, size);
/* Add finder pattern separator region */
for (i = 0; i < 8; i++) {
/* Top left */
grid[(7 * size) + i] = 0x10;
grid[(i * size) + 7] = 0x10;
/* Top right */
grid[(7 * size) + (size - i - 1)] = 0x10;
grid[((size - i - 1) * size) + 7] = 0x10;
/* Bottom left */
grid[(i * size) + (size - 8)] = 0x10;
grid[((size - 8) * size) + i] = 0x10;
/* Bottom right */
grid[((size - 8) * size) + (size - i - 1)] = 0x10;
grid[((size - i - 1) * size) + (size - 8)] = 0x10;
}
/* Reserve function information region */
for (i = 0; i < 9; i++) {
/* Top left */
grid[(8 * size) + i] = 0x10;
grid[(i * size) + 8] = 0x10;
/* Top right */
grid[(8 * size) + (size - i - 1)] = 0x10;
grid[((size - i - 1) * size) + 8] = 0x10;
/* Bottom left */
grid[(i * size) + (size - 9)] = 0x10;
grid[((size - 9) * size) + i] = 0x10;
/* Bottom right */
grid[((size - 9) * size) + (size - i - 1)] = 0x10;
grid[((size - i - 1) * size) + (size - 9)] = 0x10;
}
if (version > 3) {
int k = hx_module_k[version - 1];
int r = hx_module_r[version - 1];
int m = hx_module_m[version - 1];
int x, y, row_switch, column_switch;
int module_height, module_width;
int mod_x, mod_y;
/* Add assistant alignment patterns to left and right */
y = 0;
mod_y = 0;
do {
if (mod_y < m) {
module_height = k;
} else {
module_height = r - 1;
}
if ((mod_y % 2) == 0) {
if ((m % 2) == 1) {
hx_plot_assistant(grid, size, 0, y);
}
} else {
if ((m % 2) == 0) {
hx_plot_assistant(grid, size, 0, y);
}
hx_plot_assistant(grid, size, size - 1, y);
}
mod_y++;
y += module_height;
} while (y < size);
/* Add assistant alignment patterns to top and bottom */
x = (size - 1);
mod_x = 0;
do {
if (mod_x < m) {
module_width = k;
} else {
module_width = r - 1;
}
if ((mod_x % 2) == 0) {
if ((m % 2) == 1) {
hx_plot_assistant(grid, size, x, (size - 1));
}
} else {
if ((m % 2) == 0) {
hx_plot_assistant(grid, size, x, (size - 1));
}
hx_plot_assistant(grid, size, x, 0);
}
mod_x++;
x -= module_width;
} while (x >= 0);
/* Add alignment pattern */
column_switch = 1;
y = 0;
mod_y = 0;
do {
if (mod_y < m) {
module_height = k;
} else {
module_height = r - 1;
}
if (column_switch == 1) {
row_switch = 1;
column_switch = 0;
} else {
row_switch = 0;
column_switch = 1;
}
x = (size - 1);
mod_x = 0;
do {
if (mod_x < m) {
module_width = k;
} else {
module_width = r - 1;
}
if (row_switch == 1) {
if (!(y == 0 && x == (size - 1))) {
hx_plot_alignment(grid, size, x, y, module_width, module_height);
}
row_switch = 0;
} else {
row_switch = 1;
}
mod_x++;
x -= module_width;
} while (x >= 0);
mod_y++;
y += module_height;
} while (y < size);
}
}
/* Han Xin Code - main */
int han_xin(struct zint_symbol *symbol, const unsigned char source[], int length) {
char mode[length + 1];
int est_binlen;
int ecc_level = 1;
int i, j, version;
int target_binlen, size;
hx_define_mode(mode, source, length);
est_binlen = calculate_binlength(mode, length);
est_binlen = calculate_binlength(mode, source, length);
char binary[est_binlen + 10];
binary[0] = '\0';
calculate_binary(binary, mode, source, length);
version = 85;
for (i = 84; i > 0; i--) {
switch (ecc_level) {
case 1:
if ((hx_data_codewords_L1[i - 1] * 8) > est_binlen) {
version = i;
target_binlen = hx_data_codewords_L1[i - 1] * 8;
}
break;
case 2:
if ((hx_data_codewords_L2[i - 1] * 8) > est_binlen) {
version = i;
target_binlen = hx_data_codewords_L2[i - 1] * 8;
}
break;
case 3:
if ((hx_data_codewords_L3[i - 1] * 8) > est_binlen) {
version = i;
target_binlen = hx_data_codewords_L3[i - 1] * 8;
}
break;
case 4:
if ((hx_data_codewords_L4[i - 1] * 8) > est_binlen) {
version = i;
target_binlen = hx_data_codewords_L4[i - 1] * 8;
}
break;
}
}
if (version == 85) {
strcpy(symbol->errtxt, "Input too long for selected error correction level");
return ZINT_ERROR_TOO_LONG;
}
size = (version * 2) + 21;
#ifndef _MSC_VER
int datastream[target_binlen + 1];
int fullstream[hx_total_codewords[version - 1] + 1];
unsigned char grid[size * size];
#else
datastream = (int *) _alloca((target_binlen + 1) * sizeof (int));
fullstream = (int *) _alloca((hx_total_codewords[version - 1] + 1) * sizeof (int));
grid = (unsigned char *) _alloca((size * size) * sizeof (unsigned char));
#endif
hx_setup_grid(grid, size, version);
printf("Binary: %s\n", binary);
strcpy(symbol->errtxt, "Under Construction!");
return ZINT_ERROR_INVALID_OPTION;
symbol->width = size;
symbol->rows = size;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
if (grid[(i * size) + j] & 0x01) {
set_module(symbol, i, j);
}
}
symbol->row_height[i] = 1;
}
return 0;
}

View File

@ -29,21 +29,90 @@
SUCH DAMAGE.
*/
#ifndef HANXIN_H
#define HANXIN_H
/* Data from table B1: Data capacity of Han Xin Code */
static int hx_total_codewords[] = {
25, 37, 50, 54, 69, 84, 100, 117, 136, 155, 161, 181, 203, 225, 249,
273, 299, 325, 353, 381, 411, 422, 453, 485, 518, 552, 587, 623, 660,
698, 737, 754, 794, 836, 878, 922, 966, 1011, 1058, 1105, 1126, 1175,
1224, 1275, 1327, 1380, 1434, 1489, 1513, 1569, 1628, 1686, 1745, 1805,
1867, 1929, 1992, 2021, 2086, 2151, 2218, 2286, 2355, 2425, 2496, 2528,
2600, 2673, 2749, 2824, 2900, 2977, 3056, 3135, 3171, 3252, 3334, 3416,
3500, 3585, 3671, 3758, 3798, 3886
};
#ifdef __cplusplus
extern "C" {
#endif
static int hx_data_codewords_L1[] = {
21, 31, 42, 46, 57, 70, 84, 99, 114, 131, 135, 153, 171, 189, 209, 229,
251, 273, 297, 321, 345, 354, 381, 407, 436, 464, 493, 523, 554, 586, 619,
634, 666, 702, 738, 774, 812, 849, 888, 929, 946, 987, 1028, 1071, 1115,
1160, 1204, 1251, 1271, 1317, 1368, 1416, 1465, 1517, 1569, 1621, 1674,
1697, 1752, 1807, 1864, 1920, 1979, 2037, 2096, 2124, 2184, 2245, 2309,
2372, 2436, 2501, 2568, 2140, 2633, 2663, 2732, 2800, 2870, 2940, 3011,
3083, 3156, 3190, 3264
};
static int hx_data_codewords_L2[] = {
17, 25, 34, 38, 49, 58, 70, 81, 96, 109, 113, 127, 143, 157, 175,191, 209,
227, 247, 267, 287, 296, 317, 339, 362, 386, 411, 437, 462, 488, 515, 528,
556, 586, 614, 646, 676, 707, 740, 773, 788, 823, 856, 893, 929, 966, 1004,
1043, 1059, 1099, 1140, 1180, 1221, 1263, 1307, 1351, 1394, 1415, 1460,
1505, 1552, 1600, 1649, 1697, 1748, 1770, 1820, 1871, 1925, 1976, 2030,
2083, 2140, 2195, 2219, 2276, 2334, 2392, 2450, 2509, 2569, 2630, 2658,
2720
};
static int hx_data_codewords_L3[] = {
13, 19, 26, 30, 37, 46, 54, 63, 74, 83, 87, 97, 109, 121, 135, 147, 161,
175, 191, 205, 221, 228, 245, 261, 280, 298, 317, 337, 358, 376, 397, 408,
428, 452, 474, 498, 522, 545, 572, 597, 608, 635, 660, 689, 717, 746, 774,
805, 817, 847, 880, 910, 943, 975, 1009, 1041, 1076, 1091, 1126, 1161, 1198,
1600, 1271, 1309, 1348, 1366, 1404, 1443, 1485, 1524, 1566, 1607,1650, 1693,
1713, 1756, 1800, 1844, 1890, 1935, 1983, 2030, 2050, 2098
};
static int hx_data_codewords_L4[] = {
9, 15, 20, 22, 27, 34, 40, 47, 54, 61, 65, 73, 81, 89, 99, 109, 119, 129,
141, 153, 165, 168, 181, 195, 208, 220, 235, 251, 264, 280, 295, 302, 318,
334, 352, 368, 386, 405, 424, 441, 450, 490, 509, 531, 552, 574, 595, 605,
627, 652, 674, 697, 721, 747, 771, 796, 809, 834, 861, 892, 914, 969, 998,
1012, 1040, 1069, 1099, 1130, 1160, 1191, 1222, 1253, 1269, 1300, 1334,
1366, 1433, 1469, 1504, 1520, 1554
};
#ifdef __cplusplus
}
#endif
#endif /* NEWFILE_H */
/* Value 'k' from Annex A */
static int hx_module_k[] = {
0, 0, 0, 14, 16, 16, 17, 18, 19, 20,
14, 15, 16, 16, 17, 17, 18, 19, 20, 20,
21, 16, 17, 17, 18, 18, 19, 19, 20, 20,
21, 17, 17, 18, 18, 19, 19, 19, 20, 20,
17, 17, 18, 18, 18, 19, 19, 19, 17, 17,
18, 18, 18, 18, 19, 19, 19, 17, 17, 18,
18, 18, 18, 19, 19, 17, 17, 17, 18, 18,
18, 18, 19, 19, 17, 17, 17, 18, 18, 18,
18, 18, 17, 17
};
/* Value 'r' from Annex A */
static int hx_module_r[] = {
0, 0, 0, 15, 15, 17, 18, 19, 20, 21,
15, 15, 15, 17, 17, 19, 19, 19, 19, 21,
21, 17, 16, 18, 17, 19, 18, 20, 19, 21,
20, 17, 19, 17, 19, 17, 19, 21, 19, 21,
18, 20, 17, 19, 21, 18, 20, 22, 17, 19,
15, 17, 19, 21, 17, 19, 21, 18, 20, 15,
17, 19, 21, 16, 18, 17, 19, 21, 15, 17,
19, 21, 15, 17, 18, 20, 22, 15, 17, 19,
21, 23, 17, 19
};
/* Value of 'm' from Annex A */
static int hx_module_m[] = {
0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
6, 6, 6, 6, 6, 6, 6, 7, 7, 7,
7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
9, 9, 10, 10
};