quirc
quirc copied to clipboard
Detect mirrorred QR code
Not so much a bug report than a feature request.
Could 'inspect' be modified to attempt to mirror a reversed QR code & report it (as incompliant, it that is the case)?
Background: In debugging an "unscannable" batch of QR codes this week (about a 50% success rate between physical and Android-based barcode scanners as well as online web decoders) - I attempted to use quirc "inspect" to try to get more info on the faulty code.
quirc returns an error (internally "QUIRC_ERROR_FORMAT_ECC") for the bad QR code, not much else - and some useful info on the "good" series. It turns out, as testing with an actual physical mirror shows, that our bad QR codes were printed mirrored; which I assume is an error and probably not compliant QR code (http://qrcode.meetheed.com/question2.php).
However, it appears that some QR decoding libraries attempt to mirror the image and retry the decoding; this also includes a few of the tested Android implementations I have tested, and at least 1 java library (I would have to check on Monday which).
The fact that multiple implementations accept and decode these mirrored QR codes, means that unfortunately these types of codes will probably continue to propagate (due to incomplete understanding of the spec, and bad/or quality control processes due, I suppose, to using incompliant devices for testing). Perhaps there are also actual real-life situations where scanning a QR code through a mirror is useful (that, though, being outside the scope of this bugreport :-))
On Sat, Sep 22, 2018 at 02:43:50AM -0700, Gerrit Hannaert wrote:
Not so much a bug report than a feature request.
Could 'inspect' be modified to attempt to mirror a reversed QR code & report it (as incompliant, it that is the case)?
Background: In debugging an "unscannable" batch of QR codes this week (about a 50% success rate between physical and Android-based barcode scanners as well as online web decoders) - I attempted to use quirc "inspect" to try to get more info on the faulty code.
quirc returns an error (internally "QUIRC_ERROR_FORMAT_ECC") for the bad QR code, not much else - and some useful info on the "good" series. It turns out, as testing with an actual physical mirror shows, that our bad QR codes were printed mirrored; which I assume is an error and probably not compliant QR code (http://qrcode.meetheed.com/question2.php).
However, it appears the some QR libraries attempt to mirror the image and retry the decoding; this also includes a few of the tested Android implementations I have tested, and at least 1 java library (I would have to check on Monday which).
The fact that multiple implementations accept and decode these mirrored QR codes, means that unfortunately these types of codes will probably continue to propagate (due to incomplete understanding of the spec, and bad/or quality control processes due, I suppose, to using incompliant devices for testing). Perhaps there are also actual real-life situations where scanning a QR code through a mirror is useful (that, though, being outside the scope of this bugreport :-))
Would running the image through "convert -flip" solve the problem as well?
I guess you could always flip and re-process the image if you wanted to emulate the behaviour of the other libraries. I'd be hesitant to add this as a default though, because it would obviously double the processing time for everyone, regardless of whether they needed it.
I would be happy to take a patch for, say, a command-line argument for "inspect" if anyone wanted to implement a horizontal or vertical flip mode.
-- Daniel Beer [email protected] http://dlbeer.co.nz/ PGP: BA6E 0B26 1F89 246C E3F3 C910 1E58 C43A 160A 553B
Agreed with @dlbeer that we may not want this as the default, but the library could provide the mechanisms to do this easily.
At the moment load_png()
and load_jpeg()
are on "double duty" for simplicity's sake, i.e. they (a) decode the image and (b) load it into their struct quirc
argument.
A solution is to pass them a "flip" or "transform" flag and process the decoded image before loading it, but that would duplicate the processing logic and make them doing more than what they already do.
Another solution is to refactor them so that they only do (a), i.e. decode the image. They could return a buffer with the pixels, allowing the calling code (for ex. inspect
) to process the image. This would require much more memory allocation and correct implementation of both processing and loading from the caller.
Finally, one could write quirc_flip()
implementing the processing logic directly on the image
pointer. This should be easy to write and allow something like this:
/* ... */
q = quirc_new();
load_png(q, argv[1]);
quirc_end(q);
if (quirc_count(q) == 0) {
/* zero QR code identified, try with the mirrored version of the image. */
quirc_flip(q);
quirc_end(q);
}
/* ... */
Although calling quirc_end()
twice feels weird.
Thoughts?
On Tue, Sep 25, 2018 at 01:02:47AM -0700, Alexandre Perrin wrote:
Agreed with @dlbeer that we may not want this as the default, but the library could provide the mechanisms to do this easily.
At the moment
load_png()
andload_jpeg()
are on "double duty" for simplicity's sake, i.e. they (a) decode the image and (b) load it into theirstruct quirc
argument.A solution is to pass them a "flip" or "transform" flag and process the decoded image before loading it, but that would duplicate the processing logic and make them doing more than what they already do.
Another solution is to refactor them so that they only do (a), i.e. decode the image. They could return a buffer with the pixels, allowing the calling code (for ex.
inspect
) to process the image. This would require much more memory allocation and correct implementation of both processing and loading from the caller.Finally, one could write
quirc_flip()
implementing the processing logic directly on theimage
pointer. This should be easy to write and allow something like this:/* ... */ q = quirc_new(); load_png(q, argv[1]); quirc_end(q); if (quirc_count(q) == 0) { /* zero QR code identified, try with the mirrored version of the image. */ quirc_flip(q); quirc_end(q); } /* ... */
Although calling
quirc_end()
twice feels weird.Thoughts?
I think it'd be good to keep flipping separate from image loading, because it's conceivable that you may want to do other kinds of transforms in future or add more file formats, and you wouldn't want to implement every transform for every format.
Calling quirc_end() twice wouldn't work currently, because the binarization won't work twice on the same buffer (but that could be fixed -- you could make another quirc_ function to rebinarize by setting all non-zero pixels to QUIRC_BLACK, and then following through with everything that normally follows binarization).
How about just supplying, as part of the test/demo functions, a routine to flip a buffer horizontally? Users who need this could allocate an intermediate buffer to load the image into, then copy it into the quirc buffer both before and after flipping.
Either that or the in-place flip and rebinarization feature -- I guess it depends on how often you'd expect this to be useful.
-- Daniel Beer [email protected] http://dlbeer.co.nz/ PGP: BA6E 0B26 1F89 246C E3F3 C910 1E58 C43A 160A 553B
So, as a non-programmer and only a casual 'passer by' of quirc (looking for anything that could provide debugging info on a QR code) - I don't know what your typical users' use-cases for 'inspect' are: so if they are sensitive to speed/throughput then this does not make sense as a default.
But for what it's worth, I think the command-line argument option is not so bad. I would certainly, in my use-case, have opted for the inspect --try-mirrorred-too if there were such an option :-) If anything, even the existence of such an option raises awareness of real-life QR code issues.
I would not have considered pre-processing with ImageMagick/convert, if I had not known mirroring was a possible cause of a bad decoding.