From 5beb59e3b46b77251e19481bd5339decaf8f3df6 Mon Sep 17 00:00:00 2001 From: Claudio Felber Date: Mon, 21 Sep 2020 16:54:55 +0200 Subject: [PATCH 1/4] Support horizontally flipped QR-codes according to ISO 18004:2015 --- lib/decode.c | 16 ++++++++++++++++ lib/quirc.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/lib/decode.c b/lib/decode.c index 6266611..244ade3 100644 --- a/lib/decode.c +++ b/lib/decode.c @@ -916,3 +916,19 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code, return QUIRC_SUCCESS; } + +void quirc_flip(struct quirc_code *code) +{ + struct quirc_code flipped; + memset(&flipped, 0, sizeof(flipped)); + int offset = 0; + for (int y = 0, sx = 0; y < code->size; y++, sx++) { + for (int x = 0, sy = 0; x < code->size; x++, sy++) { + if (grid_bit(code, sx, sy)) { + flipped.cell_bitmap[offset >> 3] |= (1 << (offset & 7)); + } + offset++; + } + } + memcpy(&code->cell_bitmap, &flipped.cell_bitmap, sizeof(flipped.cell_bitmap)); +} \ No newline at end of file diff --git a/lib/quirc.h b/lib/quirc.h index 97b4bbe..d8d250d 100644 --- a/lib/quirc.h +++ b/lib/quirc.h @@ -168,6 +168,9 @@ void quirc_extract(const struct quirc *q, int index, quirc_decode_error_t quirc_decode(const struct quirc_code *code, struct quirc_data *data); +/* Flip a QR-code according to optional mirror feature of ISO 18004:2015 */ +void quirc_flip(struct quirc_code *code); + #ifdef __cplusplus } #endif From 4bc17cf8c679690d89ac2774f6acecabb2b01099 Mon Sep 17 00:00:00 2001 From: Claudio Felber Date: Tue, 22 Sep 2020 12:14:09 +0200 Subject: [PATCH 2/4] Optimize quirc_flip() --- lib/decode.c | 25 ++++++++++++------------- lib/identify.c | 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/decode.c b/lib/decode.c index 244ade3..0d654c5 100644 --- a/lib/decode.c +++ b/lib/decode.c @@ -919,16 +919,15 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code, void quirc_flip(struct quirc_code *code) { - struct quirc_code flipped; - memset(&flipped, 0, sizeof(flipped)); - int offset = 0; - for (int y = 0, sx = 0; y < code->size; y++, sx++) { - for (int x = 0, sy = 0; x < code->size; x++, sy++) { - if (grid_bit(code, sx, sy)) { - flipped.cell_bitmap[offset >> 3] |= (1 << (offset & 7)); - } - offset++; - } - } - memcpy(&code->cell_bitmap, &flipped.cell_bitmap, sizeof(flipped.cell_bitmap)); -} \ No newline at end of file + struct quirc_code flipped = {0}; + unsigned int offset = 0; + for (int y = 0; y < code->size; y++) { + for (int x = 0; x < code->size; x++) { + if (grid_bit(code, y, x)) { + flipped.cell_bitmap[offset >> 3u] |= (1u << (offset & 7u)); + } + offset++; + } + } + memcpy(&code->cell_bitmap, &flipped.cell_bitmap, sizeof(flipped.cell_bitmap)); +} diff --git a/lib/identify.c b/lib/identify.c index d33f3d7..b725fea 100644 --- a/lib/identify.c +++ b/lib/identify.c @@ -1140,7 +1140,7 @@ void quirc_extract(const struct quirc *q, int index, int x; for (x = 0; x < qr->grid_size; x++) { if (read_cell(q, index, x, y) > 0) { - code->cell_bitmap[i >> 3] |= (1 << (i & 7)); + code->cell_bitmap[i >> 3] |= (1 << (i & 7)); } i++; } From 2fd06df8de80cbe8cec119642558a6254e5773e7 Mon Sep 17 00:00:00 2001 From: Claudio Felber Date: Tue, 22 Sep 2020 12:18:23 +0200 Subject: [PATCH 3/4] Add support for flipped QR-codes in inspect and qrtest tools --- tests/inspect.c | 4 ++++ tests/qrtest.c | 19 ++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/inspect.c b/tests/inspect.c index 866ee16..ce5357a 100644 --- a/tests/inspect.c +++ b/tests/inspect.c @@ -34,6 +34,10 @@ static void dump_info(struct quirc *q) quirc_extract(q, i, &code); err = quirc_decode(&code, &data); + if (err == QUIRC_ERROR_DATA_ECC) { + quirc_flip(&code); + err = quirc_decode(&code, &data); + } dump_cells(&code); printf("\n"); diff --git a/tests/qrtest.c b/tests/qrtest.c index 2e50698..1bb178e 100644 --- a/tests/qrtest.c +++ b/tests/qrtest.c @@ -125,8 +125,15 @@ static int scan_file(const char *path, const char *filename, quirc_extract(decoder, i, &code); - if (!quirc_decode(&code, &data)) + quirc_decode_error_t err = quirc_decode(&code, &data); + if (err == QUIRC_ERROR_DATA_ECC) { + quirc_flip(&code); + err = quirc_decode(&code, &data); + } + + if (!err) { info->decode_count++; + } } (void)clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp); @@ -150,12 +157,14 @@ static int scan_file(const char *path, const char *filename, if (want_verbose) { struct quirc_data data; - quirc_decode_error_t err = - quirc_decode(&code, &data); + quirc_decode_error_t err = quirc_decode(&code, &data); + if (err == QUIRC_ERROR_DATA_ECC) { + quirc_flip(&code); + err = quirc_decode(&code, &data); + } if (err) { - printf(" ERROR: %s\n\n", - quirc_strerror(err)); + printf(" ERROR: %s\n\n", quirc_strerror(err)); } else { printf(" Decode successful:\n"); dump_data(&data); From 8e8a638a5f2a4eb58de0e017cce5a990baadd52c Mon Sep 17 00:00:00 2001 From: Claudio Felber Date: Tue, 22 Sep 2020 12:22:06 +0200 Subject: [PATCH 4/4] Update README.md with how to use quirc_flip() --- .gitignore | 1 + README.md | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.gitignore b/.gitignore index a7494bc..54855db 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ libquirc.so* .*.swp *~ .DS_Store +.idea \ No newline at end of file diff --git a/README.md b/README.md index d70c5c3..78051ad 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,23 @@ for (i = 0; i < num_codes; i++) { `quirc_code` and `quirc_data` are flat structures which don't need to be initialized or freed after use. +In case you also need to support horizontally flipped QR-codes (mirrored +images according to ISO 18004:2015, pages 6 and 62), you can make a second +decode attempt with the flipped image data whenever you get an ECC failure: + +```C + err = quirc_decode(&code, &data); + if (err == QUIRC_ERROR_DATA_ECC) { + quirc_flip(&code); + err = quirc_decode(&code, &data); + } + + if (err) + printf("DECODE FAILED: %s\n", quirc_strerror(err)); + else + printf("Data: %s\n", data.payload); +``` + Copyright --------- Copyright (C) 2010-2012 Daniel Beer <>