]> git.sur5r.net Git - glabels/blob - qrencode-3.1.0/tests/test_qrspec.c
Organized master branch to be top-level directory for glabels, instead of
[glabels] / qrencode-3.1.0 / tests / test_qrspec.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "common.h"
4 #include "../qrspec.h"
5
6 void print_eccTable(void)
7 {
8         int i, j;
9         int ecc;
10         int data;
11         int spec[5];
12
13         for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
14                 printf("Version %2d\n", i);
15                 for(j=0; j<4; j++) {
16                         QRspec_getEccSpec(i, (QRecLevel)j, spec);
17                         data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
18                              + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
19                         ecc  = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
20                              + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
21                         printf("%3d\t", ecc);
22                         printf("%2d\t", QRspec_rsBlockNum1(spec));
23                         printf("(%3d, %3d, %3d)\n",
24                                    QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec),
25                                    QRspec_rsDataCodes1(spec),
26                                    QRspec_rsEccCodes1(spec));
27                         if(QRspec_rsBlockNum2(spec) > 0) {
28                                 printf("\t%2d\t", QRspec_rsBlockNum2(spec));
29                                 printf("(%3d, %3d, %3d)\n",
30                                            QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec),
31                                            QRspec_rsDataCodes2(spec),
32                                            QRspec_rsEccCodes2(spec));
33                         }
34                 }
35         }
36 }
37
38 void test_eccTable(void)
39 {
40         int i, j;
41         int ecc;
42         int data;
43         int err = 0;
44         int spec[5];
45
46         testStart("Checking ECC table.");
47         for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
48                 for(j=0; j<4; j++) {
49                         QRspec_getEccSpec(i, (QRecLevel)j, spec);
50                         data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
51                              + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
52                         ecc  = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
53                              + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
54                         if(data + ecc != QRspec_getDataLength(i, (QRecLevel)j) + QRspec_getECCLength(i, (QRecLevel)j)) {
55                                 printf("Error in version %d, level %d: invalid size\n", i, j);
56                                 printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
57                                 err++;
58                         }
59                         if(ecc != QRspec_getECCLength(i, (QRecLevel)j)) {
60                                 printf("Error in version %d, level %d: invalid data\n", i, j);
61                                 printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
62                                 err++;
63                         }
64                 }
65         }
66         testEnd(err);
67 }
68
69 void test_eccTable2(void)
70 {
71         int i;
72         int spec[5];
73
74         const int correct[7][6] = {
75                 { 8,  1, 0,  2, 60, 38},
76                 { 8,  1, 1,  2, 61, 39},
77                 {24,  2, 0, 11, 54, 24},
78                 {24,  2, 1, 16, 55, 25},
79                 {32,  0, 0, 17, 145, 115},
80                 {40,  3, 0, 20, 45, 15},
81                 {40,  3, 1, 61, 46, 16},
82         };
83
84         testStart("Checking ECC table(2)");
85         for(i=0; i<7; i++) {
86                 QRspec_getEccSpec(correct[i][0], (QRecLevel)correct[i][1], spec);
87                 if(correct[i][2] == 0) {
88                         assert_equal(QRspec_rsBlockNum1(spec), correct[i][3],
89                                 "Error in version %d, level %d. rsBlockNum1 was %d, expected %d.\n",
90                                 correct[i][0], correct[i][1],
91                                 QRspec_rsBlockNum1(spec), correct[i][3]);
92                         assert_equal(QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4],
93                                 "Error in version %d, level %d. rsDataCodes1 + rsEccCodes1 was %d, expected %d.\n",
94                                 correct[i][0], correct[i][1],
95                                 QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4]);
96                         assert_equal(QRspec_rsDataCodes1(spec), correct[i][5],
97                                 "Error in version %d, level %d. rsDataCodes1 was %d, expected %d.\n",
98                                 correct[i][0], correct[i][1],
99                                 QRspec_rsDataCodes1(spec), correct[i][5]);
100                 } else {
101                         assert_equal(QRspec_rsBlockNum2(spec), correct[i][3],
102                                 "Error in version %d, level %d. rsBlockNum2 was %d, expected %d.\n",
103                                 correct[i][0], correct[i][1],
104                                 QRspec_rsBlockNum2(spec), correct[i][3]);
105                         assert_equal(QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4],
106                                 "Error in version %d, level %d. rsDataCodes2 + rsEccCodes2 was %d, expected %d.\n",
107                                 correct[i][0], correct[i][1],
108                                 QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4]);
109                         assert_equal(QRspec_rsDataCodes2(spec), correct[i][5],
110                                 "Error in version %d, level %d. rsDataCodes2 was %d, expected %d.\n",
111                                 correct[i][0], correct[i][1],
112                                 QRspec_rsDataCodes2(spec), correct[i][5]);
113                 }
114         }
115         testFinish();
116 }
117
118 void test_newframe(void)
119 {
120         unsigned char buf[QRSPEC_WIDTH_MAX * QRSPEC_WIDTH_MAX];
121         int i, width;
122         size_t len;
123         FILE *fp;
124         unsigned char *frame;
125
126         testStart("Checking newly created frame.");
127         fp = fopen("frame", "rb");
128         if(fp == NULL) {
129                 perror("Failed to open \"frame\":");
130                 abort();
131         }
132         for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
133                 frame = QRspec_newFrame(i);
134                 width = QRspec_getWidth(i);
135                 len = fread(buf, 1, width * width, fp);
136                 if((int)len != width * width) {
137                         perror("Failed to read the pattern file:");
138                         abort();
139                 }
140                 assert_zero(memcmp(frame, buf, len), "frame pattern mismatch (version %d)\n", i);
141                 free(frame);
142         }
143
144         testFinish();
145         fclose(fp);
146 }
147
148 #if 0
149 /* This test is used to check positions of alignment pattern. See Appendix E
150  * (pp.71) of JIS X0510:2004 and compare to the output. Before comment out
151  * this test, change the value of the pattern marker's center dot from 0xa1
152  * to 0xb1 (QRspec_putAlignmentMarker() : finder).
153  */
154 void test_alignment(void)
155 {
156         unsigned char *frame;
157         int i, x, y, width, c;
158
159         testStart("Checking alignment pattern.");
160         for(i=2; i<=QRSPEC_VERSION_MAX; i++) {
161                 printf("%2d", i);
162                 frame = QRspec_newFrame(i);
163                 width = QRspec_getWidth(i);
164                 c = 0;
165                 for(x=0; x<width * width; x++) {
166                         if(frame[x] == 0xb1) {
167                                 c++;
168                         }
169                 }
170                 printf("|%2d|   6", c);
171                 y = width - 7;
172                 for(x=0; x < width; x++) {
173                         if(frame[y * width + x] == 0xb1) {
174                                 printf(", %3d", x);
175                         }
176                 }
177                 printf("\n");
178                 free(frame);
179         }
180         testFinish();
181 }
182 #endif
183
184 void test_verpat(void)
185 {
186         int version;
187         unsigned int pattern;
188         int err = 0;
189         unsigned int data;
190         unsigned int code;
191         int i, c;
192         unsigned int mask;
193
194         for(version=7; version <= QRSPEC_VERSION_MAX; version++) {
195                 pattern = QRspec_getVersionPattern(version);
196                 if((pattern >> 12) != (unsigned int)version) {
197                         printf("Error in version %d.\n", version);
198                         err++;
199                         continue;
200                 }
201                 mask = 0x40;
202                 for(i=0; mask != 0; i++) {
203                         if(version & mask) break;
204                         mask = mask >> 1;
205                 }
206                 c = 6 - i;
207                 data = version << 12;
208                 code = 0x1f25 << c;
209                 mask = 0x40000 >> (6 - c);
210                 for(i=0; i<=c; i++) {
211                         if(mask & data) {
212                                 data ^= code;
213                         }
214                         code = code >> 1;
215                         mask = mask >> 1;
216                 }
217                 data = (version << 12) | (data & 0xfff);
218                 if(data != pattern) {
219                         printf("Error in version %d\n", version);
220                         err++;
221                 }
222         }
223 }
224
225 void print_newFrame(void)
226 {
227         int width;
228         int x, y;
229         unsigned char *frame;
230
231         frame = QRspec_newFrame(7);
232         width = QRspec_getWidth(7);
233         for(y=0; y<width; y++) {
234                 for(x=0; x<width; x++) {
235                         printf("%02x ", frame[y * width + x]);
236                 }
237                 printf("\n");
238         }
239         free(frame);
240 }
241
242 /* See Table 22 (pp.45) and Appendix C (pp. 65) of JIS X0510:2004 */
243 static unsigned int levelIndicator[4] = {1, 0, 3, 2};
244 static unsigned int calcFormatInfo(int mask, QRecLevel level)
245 {
246         unsigned int data, ecc, b, code;
247         int i, c;
248
249         data = (levelIndicator[level] << 13) | (mask << 10);
250         ecc = data;
251         b = 1 << 14;
252         for(i=0; b != 0; i++) {
253                 if(ecc & b) break;
254                 b = b >> 1;
255         }
256         c = 4 - i;
257         code = 0x537 << c ; //10100110111
258         b = 1 << (10 + c);
259         for(i=0; i<=c; i++) {
260                 if(b & ecc) {
261                         ecc ^= code;
262                 }
263                 code = code >> 1;
264                 b = b >> 1;
265         }
266         
267         return (data | ecc) ^ 0x5412;
268 }
269
270 void test_format(void)
271 {
272         unsigned int format;
273         int i, j;
274         int err = 0;
275
276         testStart("Format info test");
277         for(i=0; i<4; i++) {
278                 for(j=0; j<8; j++) {
279                         format = calcFormatInfo(j, (QRecLevel)i);
280 //                      printf("0x%04x, ", format);
281                         if(format != QRspec_getFormatInfo(j, (QRecLevel)i)) {
282                                 printf("Level %d, mask %x\n", i, j);
283                                 err++;
284                         }
285                 }
286 //              printf("\n");
287         }
288         testEnd(err);
289 }
290
291 int main(int argc, char **argv)
292 {
293         test_eccTable();
294         test_eccTable2();
295         //print_eccTable();
296         test_newframe();
297         //test_alignment();
298         test_verpat();
299         //print_newFrame();
300         test_format();
301
302         QRspec_clearCache();
303
304         report();
305
306         return 0;
307 }