Merge pull request #89 from claudiofelber/master

Support horizontally flipped QR-codes according to ISO 18004:2015
This commit is contained in:
Alexandre Perrin 2020-09-23 22:09:39 +02:00 committed by GitHub
commit 7e7ab596e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 55 additions and 6 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@ libquirc.so*
.*.swp .*.swp
*~ *~
.DS_Store .DS_Store
.idea

View file

@ -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 `quirc_code` and `quirc_data` are flat structures which don't need to be
initialized or freed after use. 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
--------- ---------
Copyright (C) 2010-2012 Daniel Beer <<dlbeer@gmail.com>> Copyright (C) 2010-2012 Daniel Beer <<dlbeer@gmail.com>>

View file

@ -916,3 +916,18 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code,
return QUIRC_SUCCESS; return QUIRC_SUCCESS;
} }
void quirc_flip(struct quirc_code *code)
{
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));
}

View file

@ -1140,7 +1140,7 @@ void quirc_extract(const struct quirc *q, int index,
int x; int x;
for (x = 0; x < qr->grid_size; x++) { for (x = 0; x < qr->grid_size; x++) {
if (read_cell(q, index, x, y) > 0) { 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++; i++;
} }

View file

@ -168,6 +168,9 @@ void quirc_extract(const struct quirc *q, int index,
quirc_decode_error_t quirc_decode(const struct quirc_code *code, quirc_decode_error_t quirc_decode(const struct quirc_code *code,
struct quirc_data *data); 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 #ifdef __cplusplus
} }
#endif #endif

View file

@ -34,6 +34,10 @@ static void dump_info(struct quirc *q)
quirc_extract(q, i, &code); quirc_extract(q, i, &code);
err = quirc_decode(&code, &data); err = quirc_decode(&code, &data);
if (err == QUIRC_ERROR_DATA_ECC) {
quirc_flip(&code);
err = quirc_decode(&code, &data);
}
dump_cells(&code); dump_cells(&code);
printf("\n"); printf("\n");

View file

@ -125,8 +125,15 @@ static int scan_file(const char *path, const char *filename,
quirc_extract(decoder, i, &code); 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++; info->decode_count++;
}
} }
(void)clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp); (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) { if (want_verbose) {
struct quirc_data data; struct quirc_data data;
quirc_decode_error_t err = quirc_decode_error_t err = quirc_decode(&code, &data);
quirc_decode(&code, &data); if (err == QUIRC_ERROR_DATA_ECC) {
quirc_flip(&code);
err = quirc_decode(&code, &data);
}
if (err) { if (err) {
printf(" ERROR: %s\n\n", printf(" ERROR: %s\n\n", quirc_strerror(err));
quirc_strerror(err));
} else { } else {
printf(" Decode successful:\n"); printf(" Decode successful:\n");
dump_data(&data); dump_data(&data);