rmqrcode-python icon indicating copy to clipboard operation
rmqrcode-python copied to clipboard

Can not generate R17x43 code

Open tkamiya22 opened this issue 1 year ago • 3 comments

When I try to generate codes for version R17x43, the program crashed.

to Reproduce

  1. $ rmqr foo foo.png --version R17x43

error message

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "...\venv\Scripts\rmqr.exe\__main__.py", line 7, in <module>
  File "...\venv\Lib\site-packages\rmqrcode\console.py", line 57, in main
    qr = _make_qr(args.DATA, ecc=ecc, version=args.version, fit_strategy=fit_strategy)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\venv\Lib\site-packages\rmqrcode\console.py", line 29, in _make_qr
    qr.make()
  File "...\venv\Lib\site-packages\rmqrcode\rmqrcode.py", line 161, in make
    blocks = self._split_into_blocks(codewords, self._qr_version["blocks"][self._error_correction_level])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\venv\Lib\site-packages\rmqrcode\rmqrcode.py", line 357, in _split_into_blocks
    block.set_data_and_compute_ecc(codewords_in_block)
  File "...\venv\Lib\site-packages\rmqrcode\rmqrcode.py", line 861, in set_data_and_compute_ecc
    self._compute_ecc_codewords()
  File "...\venv\Lib\site-packages\rmqrcode\rmqrcode.py", line 897, in _compute_ecc_codewords
    g = GeneratorPolynomials[self._ecc_codewords_num]
        ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 21

Version

rmqrcode: 0.3.2 QRQR for Android: 3.0.32

tkamiya22 avatar Jul 09 '24 13:07 tkamiya22

When I changed the value of c to 61, I was able to read it with QRQR. (I'll make a PR after I check some cases.)

https://github.com/OUDON/rmqrcode-python/blob/9dbbc2c6163fde897431a57cad9e475bf1e56e48/src/rmqrcode/format/rmqr_versions.py#L994-L1000

tkamiya22 avatar Jul 09 '24 13:07 tkamiya22

I have also run into this issue. I cannot generate QR codes longer than 31 characters and shorter than 38 with the following settings: ErroeCorrectionLevel: M, FitStrategy: minimize width. Doing so generates a KeyError: 21.

The code below shows that KeyErrors shows up with character counts of 32 thru 37.

Please implement a fix soon.


for x in range(1, 40):
    try:
        qr_data = "a"*x        
        qr = rMQR.fit(
                qr_data,
                ecc=rmqrcode.ErrorCorrectionLevel.M,
                fit_strategy=rmqrcode.FitStrategy.MINIMIZE_WIDTH
        )
    except KeyError:
        print(f"Failed for character count [ {x} ]  [ {qr_data} ]")
    else:
        print(f"Passed for character count [ {x} ]  [ {qr_data} ]")

Passed for character count [ 1 ] [ a ] Passed for character count [ 2 ] [ aa ] Passed for character count [ 3 ] [ aaa ] Passed for character count [ 4 ] [ aaaa ] Passed for character count [ 5 ] [ aaaaa ] Passed for character count [ 6 ] [ aaaaaa ] Passed for character count [ 7 ] [ aaaaaaa ] Passed for character count [ 8 ] [ aaaaaaaa ] Passed for character count [ 9 ] [ aaaaaaaaa ] Passed for character count [ 10 ] [ aaaaaaaaaa ] Passed for character count [ 11 ] [ aaaaaaaaaaa ] Passed for character count [ 12 ] [ aaaaaaaaaaaa ] Passed for character count [ 13 ] [ aaaaaaaaaaaaa ] Passed for character count [ 14 ] [ aaaaaaaaaaaaaa ] Passed for character count [ 15 ] [ aaaaaaaaaaaaaaa ] Passed for character count [ 16 ] [ aaaaaaaaaaaaaaaa ] Passed for character count [ 17 ] [ aaaaaaaaaaaaaaaaa ] Passed for character count [ 18 ] [ aaaaaaaaaaaaaaaaaa ] Passed for character count [ 19 ] [ aaaaaaaaaaaaaaaaaaa ] Passed for character count [ 20 ] [ aaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 21 ] [ aaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 22 ] [ aaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 23 ] [ aaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 24 ] [ aaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 25 ] [ aaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 26 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 27 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 28 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 29 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 30 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 31 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Failed for character count [ 32 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Failed for character count [ 33 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Failed for character count [ 34 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Failed for character count [ 35 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Failed for character count [ 36 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Failed for character count [ 37 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 38 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] Passed for character count [ 39 ] [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ]

This appears to be reproducible on the "https://rmqr.oudon.xyz/" QR generator site. Entering a string of 35 'a' characters with EC=M, and MINIMIZE_WIDTH and will not return a value, it will just hang the site.

I traced the KeyError to this line in rmqrcode.py. The value of _ecc_codewords_num is 21.:

    def _compute_ecc_codewords(self):
        """Computes the ecc codewords with the data codewords."""
        g = GeneratorPolynomials[self._ecc_codewords_num]  #  <-----HERE
        self._ecc_codewords = compute_reed_solomon(self._data_codewords, g, self._ecc_codewords_num)

GeneratorPolynomials has no entry for "21":

GeneratorPolynomials = {
    7 : [0, 87, 229, 146, 149, 238, 102, 21],
    8 : [0, 175, 238, 208, 249, 215, 252, 196, 28],
    9 : [0, 95, 246, 137, 231, 235, 149, 11, 123, 36],
    10: [0, 251, 67, 46, 61, 118, 70, 64, 94, 32, 45],
    12: [0, 102, 43, 98, 121, 187, 113, 198, 143, 131, 87, 157, 66],
    14: [0, 199, 249, 155, 48, 190, 124, 218, 137, 216, 87, 207, 59, 22, 91],
    16: [0, 120, 104, 107, 109, 102, 161, 76, 3, 91, 191, 147, 169, 182, 194, 225, 120],
    18: [0, 215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, 148, 252, 179, 5, 98, 96, 153],
    20: [0, 17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221, 225, 83, 239, 156, 164, 212, 212, 188, 190],
    22: [0, 210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200, 74, 8, 172, 98, 80, 219, 134, 160, 105, 165, 231],
    24: [0, 229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169, 152, 192, 226, 228, 218, 111, 0, 117, 232, 87, 96, 227, 21],
    26: [0, 173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111, 28, 165, 53, 161, 21, 245, 142, 13, 102, 48, 227, 153, 145, 218, 70],
    28: [0, 168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195, 147, 205, 27, 232, 201, 21, 43, 245, 87, 42, 195, 212, 119, 242, 37, 9, 123],
    30: [0, 41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110, 86, 239, 96, 222, 125, 42, 173, 226, 193, 224, 130, 156, 37, 251, 216, 238, 40, 192, 180],
}

rothloup avatar Jan 24 '25 19:01 rothloup

The cause does not appear to be that GeneratorPolynomials lacks an entry for '21'; rather, it seems to be due to a mistake in the constants.
The code, updated to include the commits from the pull request, was able to successfully generate, and read the expected output by QRQR.

from rmqrcode import rMQR, ErrorCorrectionLevel, FitStrategy, QRImage
from PIL import Image

images = []
for n in range(32, 37+1):
    try:
        qr_data = ''.join((str((i+1)%10) for i in range(n)))
        qr = rMQR.fit(
            qr_data,
            ecc=ErrorCorrectionLevel.M,
            fit_strategy=FitStrategy.MINIMIZE_WIDTH,
        )
        images.append(QRImage(qr)._img)
    except KeyError:
        print(f"Failed for character count [ {n} ]  [ {qr_data} ]")
    else:
        print(f"Passed for character count [ {n} ]  [ {qr_data} ]")

widths = [img.width for img in images]
heights = [img.height for img in images]
joined = Image.new("RGB", (max(widths), sum(heights)), (255, 255, 255))
for i, img in enumerate(images):
    joined.paste(img, (0, sum(heights[:i])))
joined.save('joined.png')

Image

tkamiya22 avatar Apr 23 '25 14:04 tkamiya22