Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QR code can't be decode when qr size is 49x49 #19

Open
CrazyZfp opened this issue Dec 4, 2017 · 3 comments
Open

QR code can't be decode when qr size is 49x49 #19

CrazyZfp opened this issue Dec 4, 2017 · 3 comments

Comments

@CrazyZfp
Copy link

CrazyZfp commented Dec 4, 2017

python 3.4 (virtualenv)
zbarlight 1.2
PIL 1.1.7
qrcode 5.3

I use qrcode module to generate QR codes. These sizes of QR codes can be 49x49 or 98x98 or 147x147.
49x49 QR code can't be decode, but larger can.

@fbochu fbochu added the bug label Dec 13, 2017
@fbochu
Copy link
Contributor

fbochu commented Dec 13, 2017

Thanks for the report.

I don't use qrcode and don't know how it works. Do you have examples of QR codes that can not be decoded or a script that allow create one?

@CrazyZfp
Copy link
Author

CrazyZfp commented Dec 18, 2017

@fbochu

import qrcode
import zbarlight
from PIL import Image

img = qrcode.make("alalalal", version=1,
                  error_correction=qrcode.constants.ERROR_CORRECT_L,
                  box_size=1,
                  border=10, )
img.save("t.png")

with open('t.png', 'rb') as img_file:
    image = Image.open(img_file)
    a = zbarlight.scan_codes("qrcode", image)
    print(a)

While box_size=1 and border is an even number, QR generated can't be recognized.
While box_size larger than 1 or border is an odd number, this bug never occurs.

@fbochu
Copy link
Contributor

fbochu commented Jan 3, 2018

@CrazyZfp

I wrote a small script to check the results of zbarlight compared to those of an online QRcode reader (the first I found with an API).

import io
import pprint

import qrcode
import requests
import zbarlight

token = 'zbarlight'
versions = [8, 20, 32]  # range(1, 41)
box_sizes = range(1, 10)
border_sizes = range(0, 10)

failed = {
    'zbarlight': [],
    'all': [],
}
error_corrections = {
    'L': qrcode.constants.ERROR_CORRECT_L,
    'M': qrcode.constants.ERROR_CORRECT_M,
    'Q': qrcode.constants.ERROR_CORRECT_Q,
    'H': qrcode.constants.ERROR_CORRECT_H,
}

indent = '\t{}'.format(' ' * 8)
print('\t border:', *['{v:>{l}}'.format(v=i, l=len(error_corrections)) for i in border_sizes])
print('\t errors:', *[''.join(k for k in error_corrections) for _i in border_sizes])

for version in versions:
    print('\nversion={v:>02} ({m}x{m}): '.format(v=version, m=21 + (version - 1) * 4), end='')
    for box_size in box_sizes:
        print('\n\tbox={:>02}: '.format(box_size), end='')
        for border_size in border_sizes:
            print(end=' ')
            for correction_kind, error_correction_code in error_corrections.items():
                image_info = {
                    'version': version,
                    'box': box_size,
                    'border': border_size,
                    'correction': correction_kind
                }

                image = qrcode.make(
                    token,
                    version=version,
                    error_correction=error_correction_code,
                    box_size=box_size,
                    border=border_size,
                )
                tokens = zbarlight.scan_codes("qrcode", image)

                if tokens != [token.encode()]:
                    with io.BytesIO() as fp:
                        image.save(fp, format='png')
                        fp.seek(0)
                        response = requests.post(
                            'http://api.qrserver.com/v1/read-qr-code/',
                            files={'file': fp},
                        )
                    if response.json()[0]['symbol'][0]['data']:
                        failed['zbarlight'].append(image_info)
                        print('E', end='', flush=True)
                    else:
                        failed['all'].append(image_info)
                        print('!', end='', flush=True)
                else:
                    print('.', end='', flush=True)

print('\n\n{:=^100}'.format(' failed '))
pprint.pprint(failed)

The output of this script is below.

  • a . means that zbarlight has decoded the QRcode
  • a ! means that zbarlight and the online QR code reader have failed to decode the QRcode
  • and an E means that only zbarlight failed to decode the QRcode

The script is slow, so I only run it for the QR code sizes that interest you.

	 border:    0    1    2    3    4    5    6    7    8    9
	 errors: LMQH LMQH LMQH LMQH LMQH LMQH LMQH LMQH LMQH LMQH

version=08 (49x49): 
	box=01:  !!!! .... ..!! .... ..!! .... ..!! .... ..!! ....
	box=02:  .... .... .... .... .... .... .... .... .... ....
	box=03:  .... .... .... .... .... .... .... .... .... ....
	box=04:  .... .... .... .... .... .... .... .... .... ....
	box=05:  .... .... .... .... .... .... .... .... .... ....
	box=06:  .... .... .... .... .... .... .... .... .... ....
	box=07:  .... .... .... .... .... .... .... .... .... ....
	box=08:  .... .... .... .... .... .... .... .... .... ....
	box=09:  .... .... .... .... .... .... .... .... .... ....
version=20 (97x97): 
	box=01:  !!!! .... !!!! .... !!!! .... !!!! .... !!!! ....
	box=02:  .... .... .... .... .... .... .... .... .... ....
	box=03:  .... .... .... .... .... .... .... .... .... ....
	box=04:  .... .... .... .... .... .... .... .... .... ....
	box=05:  .... .... .... .... .... .... .... .... .... ....
	box=06:  .... .... .... .... .... .... .... .... .... ....
	box=07:  .... .... .... .... .... .... .... .... .... ....
	box=08:  .... .... .... .... .... .... .... .... .... ....
	box=09:  .... .... .... .... .... .... .... .... .... EEEE
version=32 (145x145): 
	box=01:  !!!! .... .!!! .... .!!! .... .!!! .... .!!! ....
	box=02:  .!!. .... .... .... .... .... .... .... .... ....
	box=03:  .... .... .... .... .... .... .... .... .... ....
	box=04:  .... .... .... .... .... .... .... .... .... ....
	box=05:  .... .... .... .... .... .... .... .... .... ....
	box=06:  .... .... .... .... .... .... .... .... .... ....
	box=07:  .... .... .... .... .... .... .... .... .... ....
	box=08:  EEEE EEEE EEEE EEEE EEEE EEEE EEEE EEEE EEEE EEEE
	box=09:  EEEE EEEE EEEE EEEE EEEE EEEE EEEE EEEE EEEE EEEE

Has you can see there are many cases where both scanners can not decode the QRcode (and some other where only zbarlight fail). I have test some QRcode with my phone QRcode scanner and those I have tested are correctly decoded. So the bug seams to be on the side of zbarlight.

Zbarlight is based on the zbar library which is not maintained any more (the last commit was in 2012) and debugging zbar is beyond my expertise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants