dlbeer / quirc

QR decoder library
Other
882 stars 286 forks source link

Support horizontally flipped QR-codes according to ISO 18004:2015 #89

Closed claudiofelber closed 4 years ago

claudiofelber commented 4 years ago

The QR-code specification supports various optional features. A newer one is "mirror imaging". I don't know in which version of the specification (2006, 2009 or 2015) it was added, but it certainly is mentioned in ISO 18004:2015:

ISO 18004: 2015, page 6, "Mirror lmaging":

The arrangement of modules defined in this International Standard represents the "normal" orientation of the symbol. lt ls, however, possible to achieve a valid decode of a symbol in which the arrangement of the modules has been laterally transposed. When viewed with the finder patterns at the top left, top right and bottom left corners of the symbol, the effect of mirror imaging is to interchange the row and column positions of the modules.

ISO 18004: 2015, page 62, "Decoding procedure overview":

  1. Read the format Information. Release the masking pattem and perform error correction on the format information modules as necessary; if successful, symbol is in normal orientation, otherwise attempt mirror image decoding of format Information. ldentify Error Correction Level, either directly, in QR Code symbols, or from Micro QR Code symbol number, and data mask pattern reference. …

For the moment I decided on making the flipped detection optional by providing a new function quirc_flip(). It flips the modules pixmap and rotates it back to the normalized position. Then a second decode attempt can be initiated. A typical call sequence would look like this:

struct quirc_data 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) {
    // handle error
} else {
    // use decoded payload
}

The following two QR-codes represent a normal and a horizontally flipped one. Both can be correctly decoded with this small extension:

qrcodes

This resolves the problem I reported in issue https://github.com/dlbeer/quirc/issues/88.

claudiofelber commented 4 years ago

Thanks for your feedback. I have added support for flipped QR-codes to the inspect and qrtest tools, optimized quirc_flip() according to your suggestions and described its usage in the README file. You were absolutely right with sx and sy not being necessary. They were a relic of some earlier experiments and I forgot to clean up the code prior to committing it – shame on me!

kaworu commented 4 years ago

LGTM, thank you!