Merge pull request #89 from claudiofelber/master
Support horizontally flipped QR-codes according to ISO 18004:2015
This commit is contained in:
commit
7e7ab596e4
7 changed files with 55 additions and 6 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@ libquirc.so*
|
||||||
.*.swp
|
.*.swp
|
||||||
*~
|
*~
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.idea
|
17
README.md
17
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
|
`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>>
|
||||||
|
|
15
lib/decode.c
15
lib/decode.c
|
@ -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));
|
||||||
|
}
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue