from qrcode import constants
|
|
|
|
EXP_TABLE = list(range(256))
|
|
|
|
LOG_TABLE = list(range(256))
|
|
|
|
for i in range(8):
|
|
EXP_TABLE[i] = 1 << i
|
|
|
|
for i in range(8, 256):
|
|
EXP_TABLE[i] = (
|
|
EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^
|
|
EXP_TABLE[i - 8])
|
|
|
|
for i in range(255):
|
|
LOG_TABLE[EXP_TABLE[i]] = i
|
|
|
|
RS_BLOCK_OFFSET = {
|
|
constants.ERROR_CORRECT_L: 0,
|
|
constants.ERROR_CORRECT_M: 1,
|
|
constants.ERROR_CORRECT_Q: 2,
|
|
constants.ERROR_CORRECT_H: 3,
|
|
}
|
|
|
|
RS_BLOCK_TABLE = [
|
|
|
|
# L
|
|
# M
|
|
# Q
|
|
# H
|
|
|
|
# 1
|
|
[1, 26, 19],
|
|
[1, 26, 16],
|
|
[1, 26, 13],
|
|
[1, 26, 9],
|
|
|
|
# 2
|
|
[1, 44, 34],
|
|
[1, 44, 28],
|
|
[1, 44, 22],
|
|
[1, 44, 16],
|
|
|
|
# 3
|
|
[1, 70, 55],
|
|
[1, 70, 44],
|
|
[2, 35, 17],
|
|
[2, 35, 13],
|
|
|
|
# 4
|
|
[1, 100, 80],
|
|
[2, 50, 32],
|
|
[2, 50, 24],
|
|
[4, 25, 9],
|
|
|
|
# 5
|
|
[1, 134, 108],
|
|
[2, 67, 43],
|
|
[2, 33, 15, 2, 34, 16],
|
|
[2, 33, 11, 2, 34, 12],
|
|
|
|
# 6
|
|
[2, 86, 68],
|
|
[4, 43, 27],
|
|
[4, 43, 19],
|
|
[4, 43, 15],
|
|
|
|
# 7
|
|
[2, 98, 78],
|
|
[4, 49, 31],
|
|
[2, 32, 14, 4, 33, 15],
|
|
[4, 39, 13, 1, 40, 14],
|
|
|
|
# 8
|
|
[2, 121, 97],
|
|
[2, 60, 38, 2, 61, 39],
|
|
[4, 40, 18, 2, 41, 19],
|
|
[4, 40, 14, 2, 41, 15],
|
|
|
|
# 9
|
|
[2, 146, 116],
|
|
[3, 58, 36, 2, 59, 37],
|
|
[4, 36, 16, 4, 37, 17],
|
|
[4, 36, 12, 4, 37, 13],
|
|
|
|
# 10
|
|
[2, 86, 68, 2, 87, 69],
|
|
[4, 69, 43, 1, 70, 44],
|
|
[6, 43, 19, 2, 44, 20],
|
|
[6, 43, 15, 2, 44, 16],
|
|
|
|
# 11
|
|
[4, 101, 81],
|
|
[1, 80, 50, 4, 81, 51],
|
|
[4, 50, 22, 4, 51, 23],
|
|
[3, 36, 12, 8, 37, 13],
|
|
|
|
# 12
|
|
[2, 116, 92, 2, 117, 93],
|
|
[6, 58, 36, 2, 59, 37],
|
|
[4, 46, 20, 6, 47, 21],
|
|
[7, 42, 14, 4, 43, 15],
|
|
|
|
# 13
|
|
[4, 133, 107],
|
|
[8, 59, 37, 1, 60, 38],
|
|
[8, 44, 20, 4, 45, 21],
|
|
[12, 33, 11, 4, 34, 12],
|
|
|
|
# 14
|
|
[3, 145, 115, 1, 146, 116],
|
|
[4, 64, 40, 5, 65, 41],
|
|
[11, 36, 16, 5, 37, 17],
|
|
[11, 36, 12, 5, 37, 13],
|
|
|
|
# 15
|
|
[5, 109, 87, 1, 110, 88],
|
|
[5, 65, 41, 5, 66, 42],
|
|
[5, 54, 24, 7, 55, 25],
|
|
[11, 36, 12, 7, 37, 13],
|
|
|
|
# 16
|
|
[5, 122, 98, 1, 123, 99],
|
|
[7, 73, 45, 3, 74, 46],
|
|
[15, 43, 19, 2, 44, 20],
|
|
[3, 45, 15, 13, 46, 16],
|
|
|
|
# 17
|
|
[1, 135, 107, 5, 136, 108],
|
|
[10, 74, 46, 1, 75, 47],
|
|
[1, 50, 22, 15, 51, 23],
|
|
[2, 42, 14, 17, 43, 15],
|
|
|
|
# 18
|
|
[5, 150, 120, 1, 151, 121],
|
|
[9, 69, 43, 4, 70, 44],
|
|
[17, 50, 22, 1, 51, 23],
|
|
[2, 42, 14, 19, 43, 15],
|
|
|
|
# 19
|
|
[3, 141, 113, 4, 142, 114],
|
|
[3, 70, 44, 11, 71, 45],
|
|
[17, 47, 21, 4, 48, 22],
|
|
[9, 39, 13, 16, 40, 14],
|
|
|
|
# 20
|
|
[3, 135, 107, 5, 136, 108],
|
|
[3, 67, 41, 13, 68, 42],
|
|
[15, 54, 24, 5, 55, 25],
|
|
[15, 43, 15, 10, 44, 16],
|
|
|
|
# 21
|
|
[4, 144, 116, 4, 145, 117],
|
|
[17, 68, 42],
|
|
[17, 50, 22, 6, 51, 23],
|
|
[19, 46, 16, 6, 47, 17],
|
|
|
|
# 22
|
|
[2, 139, 111, 7, 140, 112],
|
|
[17, 74, 46],
|
|
[7, 54, 24, 16, 55, 25],
|
|
[34, 37, 13],
|
|
|
|
# 23
|
|
[4, 151, 121, 5, 152, 122],
|
|
[4, 75, 47, 14, 76, 48],
|
|
[11, 54, 24, 14, 55, 25],
|
|
[16, 45, 15, 14, 46, 16],
|
|
|
|
# 24
|
|
[6, 147, 117, 4, 148, 118],
|
|
[6, 73, 45, 14, 74, 46],
|
|
[11, 54, 24, 16, 55, 25],
|
|
[30, 46, 16, 2, 47, 17],
|
|
|
|
# 25
|
|
[8, 132, 106, 4, 133, 107],
|
|
[8, 75, 47, 13, 76, 48],
|
|
[7, 54, 24, 22, 55, 25],
|
|
[22, 45, 15, 13, 46, 16],
|
|
|
|
# 26
|
|
[10, 142, 114, 2, 143, 115],
|
|
[19, 74, 46, 4, 75, 47],
|
|
[28, 50, 22, 6, 51, 23],
|
|
[33, 46, 16, 4, 47, 17],
|
|
|
|
# 27
|
|
[8, 152, 122, 4, 153, 123],
|
|
[22, 73, 45, 3, 74, 46],
|
|
[8, 53, 23, 26, 54, 24],
|
|
[12, 45, 15, 28, 46, 16],
|
|
|
|
# 28
|
|
[3, 147, 117, 10, 148, 118],
|
|
[3, 73, 45, 23, 74, 46],
|
|
[4, 54, 24, 31, 55, 25],
|
|
[11, 45, 15, 31, 46, 16],
|
|
|
|
# 29
|
|
[7, 146, 116, 7, 147, 117],
|
|
[21, 73, 45, 7, 74, 46],
|
|
[1, 53, 23, 37, 54, 24],
|
|
[19, 45, 15, 26, 46, 16],
|
|
|
|
# 30
|
|
[5, 145, 115, 10, 146, 116],
|
|
[19, 75, 47, 10, 76, 48],
|
|
[15, 54, 24, 25, 55, 25],
|
|
[23, 45, 15, 25, 46, 16],
|
|
|
|
# 31
|
|
[13, 145, 115, 3, 146, 116],
|
|
[2, 74, 46, 29, 75, 47],
|
|
[42, 54, 24, 1, 55, 25],
|
|
[23, 45, 15, 28, 46, 16],
|
|
|
|
# 32
|
|
[17, 145, 115],
|
|
[10, 74, 46, 23, 75, 47],
|
|
[10, 54, 24, 35, 55, 25],
|
|
[19, 45, 15, 35, 46, 16],
|
|
|
|
# 33
|
|
[17, 145, 115, 1, 146, 116],
|
|
[14, 74, 46, 21, 75, 47],
|
|
[29, 54, 24, 19, 55, 25],
|
|
[11, 45, 15, 46, 46, 16],
|
|
|
|
# 34
|
|
[13, 145, 115, 6, 146, 116],
|
|
[14, 74, 46, 23, 75, 47],
|
|
[44, 54, 24, 7, 55, 25],
|
|
[59, 46, 16, 1, 47, 17],
|
|
|
|
# 35
|
|
[12, 151, 121, 7, 152, 122],
|
|
[12, 75, 47, 26, 76, 48],
|
|
[39, 54, 24, 14, 55, 25],
|
|
[22, 45, 15, 41, 46, 16],
|
|
|
|
# 36
|
|
[6, 151, 121, 14, 152, 122],
|
|
[6, 75, 47, 34, 76, 48],
|
|
[46, 54, 24, 10, 55, 25],
|
|
[2, 45, 15, 64, 46, 16],
|
|
|
|
# 37
|
|
[17, 152, 122, 4, 153, 123],
|
|
[29, 74, 46, 14, 75, 47],
|
|
[49, 54, 24, 10, 55, 25],
|
|
[24, 45, 15, 46, 46, 16],
|
|
|
|
# 38
|
|
[4, 152, 122, 18, 153, 123],
|
|
[13, 74, 46, 32, 75, 47],
|
|
[48, 54, 24, 14, 55, 25],
|
|
[42, 45, 15, 32, 46, 16],
|
|
|
|
# 39
|
|
[20, 147, 117, 4, 148, 118],
|
|
[40, 75, 47, 7, 76, 48],
|
|
[43, 54, 24, 22, 55, 25],
|
|
[10, 45, 15, 67, 46, 16],
|
|
|
|
# 40
|
|
[19, 148, 118, 6, 149, 119],
|
|
[18, 75, 47, 31, 76, 48],
|
|
[34, 54, 24, 34, 55, 25],
|
|
[20, 45, 15, 61, 46, 16]
|
|
|
|
]
|
|
|
|
|
|
def glog(n):
|
|
if n < 1: # pragma: no cover
|
|
raise ValueError("glog(%s)" % n)
|
|
return LOG_TABLE[n]
|
|
|
|
|
|
def gexp(n):
|
|
return EXP_TABLE[n % 255]
|
|
|
|
|
|
class Polynomial:
|
|
|
|
def __init__(self, num, shift):
|
|
if not num: # pragma: no cover
|
|
raise Exception("%s/%s" % (len(num), shift))
|
|
|
|
for offset in range(len(num)):
|
|
if num[offset] != 0:
|
|
break
|
|
else:
|
|
offset += 1
|
|
|
|
self.num = num[offset:] + [0] * shift
|
|
|
|
def __getitem__(self, index):
|
|
return self.num[index]
|
|
|
|
def __iter__(self):
|
|
return iter(self.num)
|
|
|
|
def __len__(self):
|
|
return len(self.num)
|
|
|
|
def __mul__(self, other):
|
|
num = [0] * (len(self) + len(other) - 1)
|
|
|
|
for i, item in enumerate(self):
|
|
for j, other_item in enumerate(other):
|
|
num[i + j] ^= gexp(glog(item) + glog(other_item))
|
|
|
|
return Polynomial(num, 0)
|
|
|
|
def __mod__(self, other):
|
|
difference = len(self) - len(other)
|
|
if difference < 0:
|
|
return self
|
|
|
|
ratio = glog(self[0]) - glog(other[0])
|
|
|
|
num = [
|
|
item ^ gexp(glog(other_item) + ratio)
|
|
for item, other_item in zip(self, other)]
|
|
if difference:
|
|
num.extend(self[-difference:])
|
|
|
|
# recursive call
|
|
return Polynomial(num, 0) % other
|
|
|
|
|
|
class RSBlock:
|
|
|
|
def __init__(self, total_count, data_count):
|
|
self.total_count = total_count
|
|
self.data_count = data_count
|
|
|
|
|
|
def rs_blocks(version, error_correction):
|
|
if error_correction not in RS_BLOCK_OFFSET: # pragma: no cover
|
|
raise Exception(
|
|
"bad rs block @ version: %s / error_correction: %s" %
|
|
(version, error_correction))
|
|
offset = RS_BLOCK_OFFSET[error_correction]
|
|
rs_block = RS_BLOCK_TABLE[(version - 1) * 4 + offset]
|
|
|
|
blocks = []
|
|
|
|
for i in range(0, len(rs_block), 3):
|
|
count, total_count, data_count = rs_block[i:i + 3]
|
|
for j in range(count):
|
|
blocks.append(RSBlock(total_count, data_count))
|
|
|
|
return blocks
|