Can not generate R17x43 code
When I try to generate codes for version R17x43, the program crashed.
to Reproduce
-
$ 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
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
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],
}
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')