From 3af4ffd175dcaf8aaf735f3f9564da54c4f29403 Mon Sep 17 00:00:00 2001 From: Leo Uino Date: Thu, 14 Jul 2011 11:36:58 +0900 Subject: Create common header --- lpg/libqr/qr/common.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 lpg/libqr/qr/common.h (limited to 'lpg/libqr/qr/common.h') diff --git a/lpg/libqr/qr/common.h b/lpg/libqr/qr/common.h new file mode 100644 index 0000000..9caf3e0 --- /dev/null +++ b/lpg/libqr/qr/common.h @@ -0,0 +1,14 @@ +#ifndef QR_COMMON_H +#define QR_COMMON_H + +#include + +struct qr_bitmap * qr_mask_apply(const struct qr_bitmap * orig, + unsigned int mask); + +size_t qr_code_total_capacity(int version); + +int qr_code_width(const struct qr_code *); + +#endif + -- cgit v1.2.3-70-g09d2 From 9f4843d686bca0d75bee174d8249fbf72527b94a Mon Sep 17 00:00:00 2001 From: Leo Uino Date: Thu, 14 Jul 2011 14:31:07 +0900 Subject: Move RS block size calculation to a separate function --- lpg/libqr/code-common.c | 35 ++++++++++++++++++++++++++++++++++- lpg/libqr/code-create.c | 37 +++++++++++++++++++------------------ lpg/libqr/code-parse.c | 33 +++++++++++---------------------- lpg/libqr/constants.h | 2 +- lpg/libqr/qr/common.h | 11 +++++++++++ 5 files changed, 76 insertions(+), 42 deletions(-) (limited to 'lpg/libqr/qr/common.h') diff --git a/lpg/libqr/code-common.c b/lpg/libqr/code-common.c index a0b8fcc..422f2ac 100644 --- a/lpg/libqr/code-common.c +++ b/lpg/libqr/code-common.c @@ -2,9 +2,11 @@ #include #include -#include #include #include +#include +#include +#include "constants.h" void qr_code_destroy(struct qr_code * code) { @@ -41,6 +43,37 @@ size_t qr_code_total_capacity(int version) return side * side - function_bits; } +void qr_get_rs_block_sizes(int version, + enum qr_ec_level ec, + int block_count[2], + int data_length[2], + int ec_length[2]) +{ + /* FIXME: rather than using a big static table, better to + * calculate these values. + */ + int total_words = qr_code_total_capacity(version) / 8; + int data_words = QR_DATA_WORD_COUNT[version - 1][ec ^ 0x1]; + int ec_words = total_words - data_words; + int total_blocks; + + block_count[0] = QR_RS_BLOCK_COUNT[version - 1][ec ^ 0x1][0]; + block_count[1] = QR_RS_BLOCK_COUNT[version - 1][ec ^ 0x1][1]; + total_blocks = block_count[0] + block_count[1]; + + data_length[0] = data_words / total_blocks; + data_length[1] = data_length[0] + 1; + + assert(data_length[0] * block_count[0] + + data_length[1] * block_count[1] == data_words); + + ec_length[0] = ec_length[1] = ec_words / total_blocks; + + assert(ec_length[0] * block_count[0] + + ec_length[1] * block_count[1] == ec_words); + assert(data_words + ec_words == total_words); +} + struct qr_bitmap * qr_mask_apply(const struct qr_bitmap * orig, unsigned int mask) { diff --git a/lpg/libqr/code-create.c b/lpg/libqr/code-create.c index 1da7845..680b405 100644 --- a/lpg/libqr/code-create.c +++ b/lpg/libqr/code-create.c @@ -172,7 +172,8 @@ static struct qr_bitstream * make_data(int version, const size_t total_bits = qr_code_total_capacity(version); const size_t total_words = total_bits / 8; const size_t total_data = QR_DATA_WORD_COUNT[version - 1][ec ^ 0x1]; - size_t total_blocks, block_count[2], data_words, rs_words; + int block_count[2], data_length[2], ec_length[2]; + int total_blocks; size_t i, w; struct qr_bitstream * dcopy = 0; struct qr_bitstream * out = 0; @@ -186,14 +187,8 @@ static struct qr_bitstream * make_data(int version, if (qr_bitstream_resize(out, total_bits) != 0) goto fail; - /* XXX: 14-M will be incorrect */ - block_count[0] = QR_RS_BLOCK_COUNT[version - 1][ec ^ 0x1][0]; - block_count[1] = QR_RS_BLOCK_COUNT[version - 1][ec ^ 0x1][1]; + qr_get_rs_block_sizes(version, ec, block_count, data_length, ec_length); total_blocks = block_count[0] + block_count[1]; - data_words = total_data / total_blocks; - rs_words = total_words / total_blocks - data_words; - assert((data_words + rs_words) * block_count[0] + - (data_words + rs_words + 1) * block_count[1] == total_words); /* Make a copy of the data and pad it */ dcopy = qr_bitstream_dup(data); @@ -207,17 +202,20 @@ static struct qr_bitstream * make_data(int version, x_dump(dcopy); /* Make space for the RS blocks */ - blocks = calloc(total_blocks, sizeof(*blocks)); + blocks = malloc(total_blocks * sizeof(*blocks)); if (!blocks) goto fail; + for (i = 0; i < total_blocks; ++i) + blocks[i] = NULL; /* Generate RS codewords */ qr_bitstream_seek(dcopy, 0); fputs("Generate RS blocks:\n", stderr); for (i = 0; i < total_blocks; ++i) { - size_t dw = data_words + (i >= block_count[0]); - - blocks[i] = rs_generate_words(dcopy, dw, rs_words); + int type = (i >= block_count[0]); + blocks[i] = rs_generate_words(dcopy, + data_length[type], + ec_length[type]); if (!blocks[i]) { while (i--) qr_bitstream_destroy(blocks[i]); @@ -229,11 +227,13 @@ static struct qr_bitstream * make_data(int version, } /* Finally, write everything out in the correct order */ - for (w = 0; w < data_words + 1; ++w) { - for (i = (w == data_words ? block_count[0] : 0); i < total_blocks; ++i) { - size_t di = w + (i < block_count[0] ? - i * data_words : - i * (data_words + 1) - block_count[0]); + assert(block_count[1] == 0 || data_length[1] >= data_length[0]); + for (w = 0; w < data_length[block_count[1] ? 1 : 0]; ++w) { + for (i = (w >= data_length[0] ? block_count[0] : 0); i < total_blocks; ++i) { + long di = w + i * data_length[0] + + (i > block_count[0] ? + (i - block_count[0]) * (data_length[1] - data_length[0]) + : 0); qr_bitstream_seek(dcopy, di * 8); qr_bitstream_write(out, @@ -242,7 +242,8 @@ static struct qr_bitstream * make_data(int version, } for (i = 0; i < total_blocks; ++i) qr_bitstream_seek(blocks[i], 0); - for (w = 0; w < rs_words; ++w) + assert(block_count[1] == 0 || ec_length[1] == ec_length[0]); + for (w = 0; w < ec_length[0]; ++w) for (i = 0; i < total_blocks; ++i) qr_bitstream_write(out, qr_bitstream_read(blocks[i], 8), 8); diff --git a/lpg/libqr/code-parse.c b/lpg/libqr/code-parse.c index f84dcfe..29d96bb 100644 --- a/lpg/libqr/code-parse.c +++ b/lpg/libqr/code-parse.c @@ -31,24 +31,19 @@ static int unpack_bits(int version, /* FIXME: less math here (get the values from a common helper fn) */ /* FIXME: more comments to explain the algorithm */ - const size_t total_bits = qr_code_total_capacity(version); - const size_t total_words = total_bits / 8; - const size_t total_data = QR_DATA_WORD_COUNT[version - 1][ec ^ 0x1]; - int total_blocks, block_count[2], row_length[2], data_words, rs_words; + int total_words = qr_code_total_capacity(version) / 8; + int block_count[2], data_length[2], ec_length[2]; + int total_blocks; int i, w, block; struct qr_bitstream ** blocks = 0; - /* copied from make_data */ - block_count[0] = QR_RS_BLOCK_COUNT[version - 1][ec ^ 0x1][0]; - block_count[1] = QR_RS_BLOCK_COUNT[version - 1][ec ^ 0x1][1]; + qr_get_rs_block_sizes(version, ec, block_count, data_length, ec_length); total_blocks = block_count[0] + block_count[1]; - data_words = total_data / total_blocks; - rs_words = total_words / total_blocks - data_words; - assert((data_words + rs_words) * block_count[0] + - (data_words + rs_words + 1) * block_count[1] == total_words); - blocks = calloc(total_blocks, sizeof(*blocks)); + blocks = malloc(total_blocks * sizeof(*blocks)); /* XXX: check return (and below) */ + for (i = 0; i < total_blocks; ++i) + blocks[i] = NULL; for (i = 0; i < total_blocks; ++i) blocks[i] = qr_bitstream_create(); @@ -57,16 +52,12 @@ static int unpack_bits(int version, qr_bitstream_seek(raw_bits, 0); - /* XXX: 14-M will be incorrect */ - row_length[0] = data_words; - row_length[1] = block_count[1] > 0 ? (total_data - row_length[0] * block_count[0]) / block_count[1] : 0; - fprintf(stderr, "block counts %d and %d\n", block_count[0], block_count[1]); - fprintf(stderr, "row lengths %d and %d\n", row_length[0], row_length[1]); + fprintf(stderr, "row lengths %d and %d\n", data_length[0], data_length[1]); block = 0; for (w = 0; w < total_words; ++w) { - if (block == 0 && w / total_blocks == row_length[0] && block_count[1] != 0) { + if (block == 0 && w / total_blocks >= data_length[0] && block_count[1] != 0) { /* Skip the short blocks, if there are any */ block += block_count[0]; } @@ -77,12 +68,10 @@ static int unpack_bits(int version, /* XXX: apply ec */ for (block = 0; block < total_blocks; ++block) { + int type = (block >= block_count[0]); struct qr_bitstream * stream = blocks[block]; qr_bitstream_seek(stream, 0); - for (w = 0; w < row_length[block >= block_count[0]]; ++w) - qr_bitstream_write(bits_out, - qr_bitstream_read(stream, 8), - 8); + qr_bitstream_copy(bits_out, stream, data_length[type] * 8); qr_bitstream_destroy(stream); } free(blocks); diff --git a/lpg/libqr/constants.h b/lpg/libqr/constants.h index 5ae9256..fbfadc8 100644 --- a/lpg/libqr/constants.h +++ b/lpg/libqr/constants.h @@ -5,7 +5,7 @@ extern const int QR_ALIGNMENT_LOCATION[40][7]; extern const int QR_DATA_WORD_COUNT[40][4]; -/* See spec table 18 (also table 19 for application) */ +/* See qr_get_rs_block_sizes() */ extern const int QR_RS_BLOCK_COUNT[40][4][2]; extern const enum qr_data_type QR_TYPE_CODES[16]; diff --git a/lpg/libqr/qr/common.h b/lpg/libqr/qr/common.h index 9caf3e0..f2bd127 100644 --- a/lpg/libqr/qr/common.h +++ b/lpg/libqr/qr/common.h @@ -10,5 +10,16 @@ size_t qr_code_total_capacity(int version); int qr_code_width(const struct qr_code *); +/* See table 19 of the spec for the layout of EC data. There are at + * most two different block lengths, so the total number of data+ec + * blocks is the sum of block_count[]. The total number of 8-bit + * words in each kind of block is data_length + ec_length. + */ +void qr_get_rs_block_sizes(int version, + enum qr_ec_level ec, + int block_count[2], + int data_length[2], + int ec_length[2]); + #endif -- cgit v1.2.3-70-g09d2 From 4670274ec303082e0fb86ff3be1ea4170a17662f Mon Sep 17 00:00:00 2001 From: Leo Uino Date: Fri, 15 Jul 2011 14:20:41 +0900 Subject: qr_mask_apply() works in-place --- lpg/libqr/code-common.c | 14 +++----------- lpg/libqr/code-create.c | 3 ++- lpg/libqr/code-parse.c | 8 +++----- lpg/libqr/qr/common.h | 3 +-- 4 files changed, 9 insertions(+), 19 deletions(-) (limited to 'lpg/libqr/qr/common.h') diff --git a/lpg/libqr/code-common.c b/lpg/libqr/code-common.c index 422f2ac..1cb1745 100644 --- a/lpg/libqr/code-common.c +++ b/lpg/libqr/code-common.c @@ -74,18 +74,12 @@ void qr_get_rs_block_sizes(int version, assert(data_words + ec_words == total_words); } -struct qr_bitmap * qr_mask_apply(const struct qr_bitmap * orig, - unsigned int mask) +void qr_mask_apply(struct qr_bitmap * bmp, int mask) { - struct qr_bitmap * bmp; int i, j; - if (mask > 7) - return 0; - - bmp = qr_bitmap_clone(orig); - if (!bmp) - return 0; + assert((mask & 0x7) == mask); + mask &= 0x7; /* Slow version for now; we can optimize later */ @@ -111,7 +105,5 @@ struct qr_bitmap * qr_mask_apply(const struct qr_bitmap * orig, p[off] ^= (t == 0) << bit; } } - - return bmp; } diff --git a/lpg/libqr/code-create.c b/lpg/libqr/code-create.c index 680b405..f29778f 100644 --- a/lpg/libqr/code-create.c +++ b/lpg/libqr/code-create.c @@ -332,11 +332,12 @@ static int mask_data(struct qr_code * code) /* Generate bitmap for each mask and evaluate */ for (i = 0; i < 8; ++i) { - test = qr_mask_apply(code->modules, i); + test = qr_bitmap_clone(code->modules); if (!test) { qr_bitmap_destroy(mask); return -1; } + qr_mask_apply(test, i); score = score_mask(test); fprintf(stderr, "mask %d scored %d\n", i, score); if (!mask || score < best) { diff --git a/lpg/libqr/code-parse.c b/lpg/libqr/code-parse.c index 29d96bb..7a98280 100644 --- a/lpg/libqr/code-parse.c +++ b/lpg/libqr/code-parse.c @@ -212,11 +212,9 @@ int qr_code_parse(const void * buffer, fprintf(stderr, "detected ec type %d; mask %d\n", ec, mask); - code.modules = qr_mask_apply(&src_bmp, mask); - if (code.modules == NULL) { - fprintf(stderr, "failed to apply mask\n"); - return -1; - } + code.modules = qr_bitmap_clone(&src_bmp); + /* XXX: check return */ + qr_mask_apply(code.modules, mask); qr_layout_init_mask(&code); diff --git a/lpg/libqr/qr/common.h b/lpg/libqr/qr/common.h index f2bd127..640696a 100644 --- a/lpg/libqr/qr/common.h +++ b/lpg/libqr/qr/common.h @@ -3,8 +3,7 @@ #include -struct qr_bitmap * qr_mask_apply(const struct qr_bitmap * orig, - unsigned int mask); +void qr_mask_apply(struct qr_bitmap * bmp, int mask); size_t qr_code_total_capacity(int version); -- cgit v1.2.3-70-g09d2 From 779e729ad887c1cc967731a9634a11438d56b017 Mon Sep 17 00:00:00 2001 From: Leo Uino Date: Tue, 19 Jul 2011 12:08:33 +0900 Subject: Add C++ header protectors --- lpg/libqr/qr/bitmap.h | 8 ++++++++ lpg/libqr/qr/bitstream.h | 8 ++++++++ lpg/libqr/qr/code.h | 8 ++++++++ lpg/libqr/qr/common.h | 8 ++++++++ lpg/libqr/qr/data.h | 8 ++++++++ lpg/libqr/qr/layout.h | 8 ++++++++ lpg/libqr/qr/parse.h | 8 ++++++++ lpg/libqr/qr/types.h | 8 ++++++++ lpg/libqr/qr/version.h | 8 ++++++++ 9 files changed, 72 insertions(+) (limited to 'lpg/libqr/qr/common.h') diff --git a/lpg/libqr/qr/bitmap.h b/lpg/libqr/qr/bitmap.h index d4af471..72da07f 100644 --- a/lpg/libqr/qr/bitmap.h +++ b/lpg/libqr/qr/bitmap.h @@ -1,6 +1,10 @@ #ifndef QR_BITMAP_H #define QR_BITMAP_H +#ifdef __cplusplus +extern "C" { +#endif + struct qr_bitmap { unsigned char * bits; unsigned char * mask; @@ -25,5 +29,9 @@ void qr_bitmap_render(const struct qr_bitmap * bmp, unsigned long mark, unsigned long space); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/bitstream.h b/lpg/libqr/qr/bitstream.h index 9bd8261..aa431e8 100644 --- a/lpg/libqr/qr/bitstream.h +++ b/lpg/libqr/qr/bitstream.h @@ -3,6 +3,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** * Note: when writing / reading multiple bits, the * _most_ significant bits come first in the stream. @@ -45,5 +49,9 @@ int qr_bitstream_copy(struct qr_bitstream * dest, struct qr_bitstream * src, size_t count); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/code.h b/lpg/libqr/qr/code.h index e6eb47c..0f5d49c 100644 --- a/lpg/libqr/qr/code.h +++ b/lpg/libqr/qr/code.h @@ -4,6 +4,10 @@ #include #include "types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct qr_code { int version; struct qr_bitmap * modules; @@ -13,5 +17,9 @@ struct qr_code * qr_code_create(const struct qr_data * data); void qr_code_destroy(struct qr_code *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/common.h b/lpg/libqr/qr/common.h index 640696a..b7052ad 100644 --- a/lpg/libqr/qr/common.h +++ b/lpg/libqr/qr/common.h @@ -3,6 +3,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + void qr_mask_apply(struct qr_bitmap * bmp, int mask); size_t qr_code_total_capacity(int version); @@ -20,5 +24,9 @@ void qr_get_rs_block_sizes(int version, int data_length[2], int ec_length[2]); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/data.h b/lpg/libqr/qr/data.h index f2b4b45..06600ab 100644 --- a/lpg/libqr/qr/data.h +++ b/lpg/libqr/qr/data.h @@ -4,6 +4,10 @@ #include #include "types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct qr_data { int version; /* 1 ~ 40 */ enum qr_ec_level ec; @@ -29,5 +33,9 @@ enum qr_data_type qr_parse_data(const struct qr_data * input, char ** output, size_t * length); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/layout.h b/lpg/libqr/qr/layout.h index 49bebf6..e691bdb 100644 --- a/lpg/libqr/qr/layout.h +++ b/lpg/libqr/qr/layout.h @@ -1,6 +1,10 @@ #ifndef QR_CODE_LAYOUT_H #define QR_CODE_LAYOUT_H +#ifdef __cplusplus +extern "C" { +#endif + struct qr_iterator; void qr_layout_init_mask(struct qr_code *); @@ -10,5 +14,9 @@ unsigned int qr_layout_read(struct qr_iterator *); void qr_layout_write(struct qr_iterator *, unsigned int); void qr_layout_end(struct qr_iterator *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/parse.h b/lpg/libqr/qr/parse.h index 07a0424..0e08354 100644 --- a/lpg/libqr/qr/parse.h +++ b/lpg/libqr/qr/parse.h @@ -3,6 +3,10 @@ #include "data.h" +#ifdef __cplusplus +extern "C" { +#endif + int qr_code_parse(const void * buffer, size_t line_bits, size_t line_stride, @@ -12,5 +16,9 @@ int qr_code_parse(const void * buffer, int qr_decode_format(unsigned long bits, enum qr_ec_level * ec, int * mask); int qr_decode_version(unsigned long bits, int * version); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/types.h b/lpg/libqr/qr/types.h index 3615e3e..ae760ab 100644 --- a/lpg/libqr/qr/types.h +++ b/lpg/libqr/qr/types.h @@ -1,6 +1,10 @@ #ifndef QR_TYPES_H #define QR_TYPES_H +#ifdef __cplusplus +extern "C" { +#endif + struct qr_data; struct qr_code; @@ -22,5 +26,9 @@ enum qr_ec_level { QR_EC_LEVEL_H = 0x2 }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/lpg/libqr/qr/version.h b/lpg/libqr/qr/version.h index cd263c0..ce540f4 100644 --- a/lpg/libqr/qr/version.h +++ b/lpg/libqr/qr/version.h @@ -1,10 +1,18 @@ #ifndef QR_VERSION_H #define QR_VERSION_H +#ifdef __cplusplus +extern "C" { +#endif + #define QR_VERSION_MAJOR 0 #define QR_VERSION_MINOR 3 #define QR_VERSION "0.3" +#ifdef __cplusplus +} +#endif + #endif -- cgit v1.2.3-70-g09d2