lincolnloop / python-qrcode

Python QR Code image generator
https://pypi.python.org/pypi/qrcode
Other
4.39k stars 673 forks source link

`ValueError: glog(0)` when encoding binary data #330

Open bindreams opened 1 year ago

bindreams commented 1 year ago

I'm encoding a binary image file using a QR code. In the example below I'm creating a QR code version 20 with error correction H, which should allow me to pass 382 bytes in. After calling make I'm getting an error:

from qrcode import QRCode
from qrcode.constants import ERROR_CORRECT_H

data = b'         0\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00H\x00H\x00\x00\xff\xe1\x00@Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x01\x87i\x00\x04\x00\x00\x00\x01\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x02\xa0\x02\x00\x04\x00\x00\x00\x01\x00\x00\x00\x8c\xa0\x03\x00\x04\x00\x00\x00\x01\x00\x00\x00\xb4\x00\x00\x00\x00\xff\xed\x008Photoshop 3.0\x008BIM\x04\x04\x00\x00\x00\x00\x00\x008BIM\x04%\x00\x00\x00\x00\x00\x10\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\t\x98\xec\xf8B~\xff\xe2\x02(ICC_PROFILE\x00\x01\x01\x00\x00\x02\x18appl\x04\x00\x00\x00mntrRGB XYZ \x07\xe6\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00acspAPPL\x00\x00\x00\x00APPL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-appl\xec\xfd\xa3\x8e8\x85G\xc3m\xb4\xbdOz\xda\x18/\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ndesc\x00\x00\x00\xfc\x00\x00\x000cprt\x00\x00\x01,\x00\x00\x00Pwtpt\x00\x00\x01|\x00\x00\x00\x14rXYZ\x00\x00\x01\x90\x00\x00\x00\x14gXYZ\x00\x00\x01\xa4\x00\x00\x00\x14bXYZ\x00\x00\x01\xb8\x00\x00\x00\x14rTRC\x00\x00'

qr = QRCode(version=20, error_correction=ERROR_CORRECT_H, box_size=9, border=4)
qr.add_data(data)
qr.make()
Traceback (most recent call last):
  File "D:\OneDrive\Develop\vis-transfer\test.py", line 8, in <module>
    qr.make()
  File "C:\Users\andreasxp\AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\main.py", line 162, in make
    self.makeImpl(False, self.best_mask_pattern())
                         ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andreasxp\AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\main.py", line 252, in best_mask_pattern
    self.makeImpl(True, i)
  File "C:\Users\andreasxp\AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\main.py", line 189, in makeImpl
    self.data_cache = util.create_data(
                      ^^^^^^^^^^^^^^^^^
  File "C:\Users\andreasxp\AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\util.py", line 586, in create_data
    return create_bytes(buffer, rs_blocks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andreasxp\AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\util.py", line 528, in create_bytes
    modPoly = rawPoly % rsPoly
              ~~~~~~~~^~~~~~~~
  File "C:\Users\andreasxp\AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\base.py", line 279, in __mod__
    ratio = glog(self[0]) - glog(other[0])
            ^^^^^^^^^^^^^
  File "C:\Users\andreasxp\AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\base.py", line 236, in glog
    raise ValueError(f"glog({n})")
ValueError: glog(0)

Can you please help me out?

bindreams commented 1 year ago

Soon after posting I also discovered that the code above works on 7.3.1, but not on any 7.4.* version.

MayankFawkes commented 11 months ago

i am having same problem with 7.4.* its working with the strings but not with bytes

echoechoin commented 6 months ago

Maybe you can encode your data to base64 before add_data. It works in my scripts.

bindreams commented 2 months ago

OP here. For anyone encountering the problem, I eventually created my own QR encoder (also supports other barcodes). It's based on a very established C library and has very good support for any kind of data (binary included).

https://github.com/bindreams/zint-bindings

McOgurcik commented 1 month ago

I found a solution for myself: When using qr.make, I explicitly specify the fit=False parameter. (qr.make(fit=False))