| #include <stdio.h> |
| #include <string.h> |
| #include "common.h" |
| #include "../qrspec.h" |
| #include "../qrencode_inner.h" |
| #include "decoder.h" |
| |
| void print_eccTable(void) |
| { |
| int i, j; |
| int ecc; |
| int data; |
| int spec[5]; |
| |
| for(i=1; i<=QRSPEC_VERSION_MAX; i++) { |
| printf("Version %2d\n", i); |
| for(j=0; j<4; j++) { |
| QRspec_getEccSpec(i, (QRecLevel)j, spec); |
| data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec) |
| + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec); |
| ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec) |
| + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec); |
| printf("%3d\t", data); |
| printf("%3d\t", ecc); |
| printf("%2d\t", QRspec_rsBlockNum1(spec)); |
| printf("(%3d, %3d, %3d)\n", |
| QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), |
| QRspec_rsDataCodes1(spec), |
| QRspec_rsEccCodes1(spec)); |
| if(QRspec_rsBlockNum2(spec) > 0) { |
| printf("\t%2d\t", QRspec_rsBlockNum2(spec)); |
| printf("(%3d, %3d, %3d)\n", |
| QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), |
| QRspec_rsDataCodes2(spec), |
| QRspec_rsEccCodes2(spec)); |
| } |
| } |
| } |
| } |
| |
| void test_eccTable(void) |
| { |
| int i, j; |
| int ecc; |
| int data; |
| int err = 0; |
| int spec[5]; |
| |
| testStart("Checking ECC table."); |
| for(i=1; i<=QRSPEC_VERSION_MAX; i++) { |
| for(j=0; j<4; j++) { |
| QRspec_getEccSpec(i, (QRecLevel)j, spec); |
| data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec) |
| + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec); |
| ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec) |
| + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec); |
| if(data + ecc != QRspec_getDataLength(i, (QRecLevel)j) + QRspec_getECCLength(i, (QRecLevel)j)) { |
| printf("Error in version %d, level %d: invalid size\n", i, j); |
| printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]); |
| err++; |
| } |
| if(ecc != QRspec_getECCLength(i, (QRecLevel)j)) { |
| printf("Error in version %d, level %d: invalid data\n", i, j); |
| printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]); |
| err++; |
| } |
| } |
| } |
| testEnd(err); |
| } |
| |
| void test_eccTable2(void) |
| { |
| int i; |
| int spec[5]; |
| |
| const int correct[7][6] = { |
| { 8, 1, 0, 2, 60, 38}, |
| { 8, 1, 1, 2, 61, 39}, |
| {24, 2, 0, 11, 54, 24}, |
| {24, 2, 1, 16, 55, 25}, |
| {32, 0, 0, 17, 145, 115}, |
| {40, 3, 0, 20, 45, 15}, |
| {40, 3, 1, 61, 46, 16}, |
| }; |
| |
| testStart("Checking ECC table(2)"); |
| for(i=0; i<7; i++) { |
| QRspec_getEccSpec(correct[i][0], (QRecLevel)correct[i][1], spec); |
| if(correct[i][2] == 0) { |
| assert_equal(QRspec_rsBlockNum1(spec), correct[i][3], |
| "Error in version %d, level %d. rsBlockNum1 was %d, expected %d.\n", |
| correct[i][0], correct[i][1], |
| QRspec_rsBlockNum1(spec), correct[i][3]); |
| assert_equal(QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4], |
| "Error in version %d, level %d. rsDataCodes1 + rsEccCodes1 was %d, expected %d.\n", |
| correct[i][0], correct[i][1], |
| QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4]); |
| assert_equal(QRspec_rsDataCodes1(spec), correct[i][5], |
| "Error in version %d, level %d. rsDataCodes1 was %d, expected %d.\n", |
| correct[i][0], correct[i][1], |
| QRspec_rsDataCodes1(spec), correct[i][5]); |
| } else { |
| assert_equal(QRspec_rsBlockNum2(spec), correct[i][3], |
| "Error in version %d, level %d. rsBlockNum2 was %d, expected %d.\n", |
| correct[i][0], correct[i][1], |
| QRspec_rsBlockNum2(spec), correct[i][3]); |
| assert_equal(QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4], |
| "Error in version %d, level %d. rsDataCodes2 + rsEccCodes2 was %d, expected %d.\n", |
| correct[i][0], correct[i][1], |
| QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4]); |
| assert_equal(QRspec_rsDataCodes2(spec), correct[i][5], |
| "Error in version %d, level %d. rsDataCodes2 was %d, expected %d.\n", |
| correct[i][0], correct[i][1], |
| QRspec_rsDataCodes2(spec), correct[i][5]); |
| } |
| } |
| testFinish(); |
| } |
| |
| void test_newframe(void) |
| { |
| unsigned char buf[QRSPEC_WIDTH_MAX * QRSPEC_WIDTH_MAX]; |
| int i, width; |
| size_t len; |
| FILE *fp; |
| unsigned char *frame; |
| QRcode *qrcode; |
| unsigned int version; |
| |
| testStart("Checking newly created frame."); |
| fp = fopen("frame", "rb"); |
| if(fp == NULL) { |
| perror("Failed to open \"frame\":"); |
| abort(); |
| } |
| for(i=1; i<=QRSPEC_VERSION_MAX; i++) { |
| frame = QRspec_newFrame(i); |
| width = QRspec_getWidth(i); |
| len = fread(buf, 1, width * width, fp); |
| if((int)len != width * width) { |
| perror("Failed to read the pattern file:"); |
| abort(); |
| } |
| assert_zero(memcmp(frame, buf, len), "frame pattern mismatch (version %d)\n", i); |
| qrcode = QRcode_new(i, width, frame); |
| version = QRcode_decodeVersion(qrcode); |
| assert_equal(version, i, "Decoded version number is wrong: %d, expected %d.\n", version, i); |
| QRcode_free(qrcode); |
| } |
| |
| testFinish(); |
| fclose(fp); |
| } |
| |
| void test_newframe_invalid(void) |
| { |
| unsigned char *frame; |
| |
| testStart("Checking QRspec_newFrame with invalid version."); |
| frame = QRspec_newFrame(0); |
| assert_null(frame, "QRspec_newFrame(0) returns non-NULL."); |
| frame = QRspec_newFrame(QRSPEC_VERSION_MAX+1); |
| assert_null(frame, "QRspec_newFrame(0) returns non-NULL."); |
| testFinish(); |
| } |
| |
| #if 0 |
| /* This test is used to check positions of alignment pattern. See Appendix E |
| * (pp.71) of JIS X0510:2004 and compare to the output. Before comment out |
| * this test, change the value of the pattern marker's center dot from 0xa1 |
| * to 0xb1 (QRspec_putAlignmentMarker() : finder). |
| */ |
| void test_alignment(void) |
| { |
| unsigned char *frame; |
| int i, x, y, width, c; |
| |
| testStart("Checking alignment pattern."); |
| for(i=2; i<=QRSPEC_VERSION_MAX; i++) { |
| printf("%2d", i); |
| frame = QRspec_newFrame(i); |
| width = QRspec_getWidth(i); |
| c = 0; |
| for(x=0; x<width * width; x++) { |
| if(frame[x] == 0xb1) { |
| c++; |
| } |
| } |
| printf("|%2d| 6", c); |
| y = width - 7; |
| for(x=0; x < width; x++) { |
| if(frame[y * width + x] == 0xb1) { |
| printf(", %3d", x); |
| } |
| } |
| printf("\n"); |
| free(frame); |
| } |
| testFinish(); |
| } |
| #endif |
| |
| void test_verpat(void) |
| { |
| int version; |
| unsigned int pattern; |
| int err = 0; |
| unsigned int data; |
| unsigned int code; |
| int i, c; |
| unsigned int mask; |
| |
| for(version=7; version <= QRSPEC_VERSION_MAX; version++) { |
| pattern = QRspec_getVersionPattern(version); |
| if((pattern >> 12) != (unsigned int)version) { |
| printf("Error in version %d.\n", version); |
| err++; |
| continue; |
| } |
| mask = 0x40; |
| for(i=0; mask != 0; i++) { |
| if(version & mask) break; |
| mask = mask >> 1; |
| } |
| c = 6 - i; |
| data = version << 12; |
| code = 0x1f25 << c; |
| mask = 0x40000 >> (6 - c); |
| for(i=0; i<=c; i++) { |
| if(mask & data) { |
| data ^= code; |
| } |
| code = code >> 1; |
| mask = mask >> 1; |
| } |
| data = (version << 12) | (data & 0xfff); |
| if(data != pattern) { |
| printf("Error in version %d\n", version); |
| err++; |
| } |
| } |
| } |
| |
| void print_newFrame(void) |
| { |
| int width; |
| int x, y; |
| unsigned char *frame; |
| |
| frame = QRspec_newFrame(7); |
| width = QRspec_getWidth(7); |
| for(y=0; y<width; y++) { |
| for(x=0; x<width; x++) { |
| printf("%02x ", frame[y * width + x]); |
| } |
| printf("\n"); |
| } |
| free(frame); |
| } |
| |
| /* See Table 22 (pp.45) and Appendix C (pp. 65) of JIS X0510:2004 */ |
| static unsigned int levelIndicator[4] = {1, 0, 3, 2}; |
| static unsigned int calcFormatInfo(int mask, QRecLevel level) |
| { |
| unsigned int data, ecc, b, code; |
| int i, c; |
| |
| data = (levelIndicator[level] << 13) | (mask << 10); |
| ecc = data; |
| b = 1 << 14; |
| for(i=0; b != 0; i++) { |
| if(ecc & b) break; |
| b = b >> 1; |
| } |
| c = 4 - i; |
| code = 0x537 << c ; //10100110111 |
| b = 1 << (10 + c); |
| for(i=0; i<=c; i++) { |
| if(b & ecc) { |
| ecc ^= code; |
| } |
| code = code >> 1; |
| b = b >> 1; |
| } |
| |
| return (data | ecc) ^ 0x5412; |
| } |
| |
| void test_format(void) |
| { |
| unsigned int format; |
| int i, j; |
| int err = 0; |
| |
| testStart("Format info test"); |
| for(i=0; i<4; i++) { |
| for(j=0; j<8; j++) { |
| format = calcFormatInfo(j, (QRecLevel)i); |
| // printf("0x%04x, ", format); |
| if(format != QRspec_getFormatInfo(j, (QRecLevel)i)) { |
| printf("Level %d, mask %x\n", i, j); |
| err++; |
| } |
| } |
| // printf("\n"); |
| } |
| testEnd(err); |
| } |
| |
| int main(void) |
| { |
| test_eccTable(); |
| test_eccTable2(); |
| //print_eccTable(); |
| test_newframe(); |
| test_newframe_invalid(); |
| //test_alignment(); |
| test_verpat(); |
| //print_newFrame(); |
| test_format(); |
| |
| QRspec_clearCache(); |
| |
| report(); |
| |
| return 0; |
| } |