You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
7.2 KiB

4 years ago
  1. from qrcode import constants
  2. EXP_TABLE = list(range(256))
  3. LOG_TABLE = list(range(256))
  4. for i in range(8):
  5. EXP_TABLE[i] = 1 << i
  6. for i in range(8, 256):
  7. EXP_TABLE[i] = (
  8. EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^
  9. EXP_TABLE[i - 8])
  10. for i in range(255):
  11. LOG_TABLE[EXP_TABLE[i]] = i
  12. RS_BLOCK_OFFSET = {
  13. constants.ERROR_CORRECT_L: 0,
  14. constants.ERROR_CORRECT_M: 1,
  15. constants.ERROR_CORRECT_Q: 2,
  16. constants.ERROR_CORRECT_H: 3,
  17. }
  18. RS_BLOCK_TABLE = [
  19. # L
  20. # M
  21. # Q
  22. # H
  23. # 1
  24. [1, 26, 19],
  25. [1, 26, 16],
  26. [1, 26, 13],
  27. [1, 26, 9],
  28. # 2
  29. [1, 44, 34],
  30. [1, 44, 28],
  31. [1, 44, 22],
  32. [1, 44, 16],
  33. # 3
  34. [1, 70, 55],
  35. [1, 70, 44],
  36. [2, 35, 17],
  37. [2, 35, 13],
  38. # 4
  39. [1, 100, 80],
  40. [2, 50, 32],
  41. [2, 50, 24],
  42. [4, 25, 9],
  43. # 5
  44. [1, 134, 108],
  45. [2, 67, 43],
  46. [2, 33, 15, 2, 34, 16],
  47. [2, 33, 11, 2, 34, 12],
  48. # 6
  49. [2, 86, 68],
  50. [4, 43, 27],
  51. [4, 43, 19],
  52. [4, 43, 15],
  53. # 7
  54. [2, 98, 78],
  55. [4, 49, 31],
  56. [2, 32, 14, 4, 33, 15],
  57. [4, 39, 13, 1, 40, 14],
  58. # 8
  59. [2, 121, 97],
  60. [2, 60, 38, 2, 61, 39],
  61. [4, 40, 18, 2, 41, 19],
  62. [4, 40, 14, 2, 41, 15],
  63. # 9
  64. [2, 146, 116],
  65. [3, 58, 36, 2, 59, 37],
  66. [4, 36, 16, 4, 37, 17],
  67. [4, 36, 12, 4, 37, 13],
  68. # 10
  69. [2, 86, 68, 2, 87, 69],
  70. [4, 69, 43, 1, 70, 44],
  71. [6, 43, 19, 2, 44, 20],
  72. [6, 43, 15, 2, 44, 16],
  73. # 11
  74. [4, 101, 81],
  75. [1, 80, 50, 4, 81, 51],
  76. [4, 50, 22, 4, 51, 23],
  77. [3, 36, 12, 8, 37, 13],
  78. # 12
  79. [2, 116, 92, 2, 117, 93],
  80. [6, 58, 36, 2, 59, 37],
  81. [4, 46, 20, 6, 47, 21],
  82. [7, 42, 14, 4, 43, 15],
  83. # 13
  84. [4, 133, 107],
  85. [8, 59, 37, 1, 60, 38],
  86. [8, 44, 20, 4, 45, 21],
  87. [12, 33, 11, 4, 34, 12],
  88. # 14
  89. [3, 145, 115, 1, 146, 116],
  90. [4, 64, 40, 5, 65, 41],
  91. [11, 36, 16, 5, 37, 17],
  92. [11, 36, 12, 5, 37, 13],
  93. # 15
  94. [5, 109, 87, 1, 110, 88],
  95. [5, 65, 41, 5, 66, 42],
  96. [5, 54, 24, 7, 55, 25],
  97. [11, 36, 12, 7, 37, 13],
  98. # 16
  99. [5, 122, 98, 1, 123, 99],
  100. [7, 73, 45, 3, 74, 46],
  101. [15, 43, 19, 2, 44, 20],
  102. [3, 45, 15, 13, 46, 16],
  103. # 17
  104. [1, 135, 107, 5, 136, 108],
  105. [10, 74, 46, 1, 75, 47],
  106. [1, 50, 22, 15, 51, 23],
  107. [2, 42, 14, 17, 43, 15],
  108. # 18
  109. [5, 150, 120, 1, 151, 121],
  110. [9, 69, 43, 4, 70, 44],
  111. [17, 50, 22, 1, 51, 23],
  112. [2, 42, 14, 19, 43, 15],
  113. # 19
  114. [3, 141, 113, 4, 142, 114],
  115. [3, 70, 44, 11, 71, 45],
  116. [17, 47, 21, 4, 48, 22],
  117. [9, 39, 13, 16, 40, 14],
  118. # 20
  119. [3, 135, 107, 5, 136, 108],
  120. [3, 67, 41, 13, 68, 42],
  121. [15, 54, 24, 5, 55, 25],
  122. [15, 43, 15, 10, 44, 16],
  123. # 21
  124. [4, 144, 116, 4, 145, 117],
  125. [17, 68, 42],
  126. [17, 50, 22, 6, 51, 23],
  127. [19, 46, 16, 6, 47, 17],
  128. # 22
  129. [2, 139, 111, 7, 140, 112],
  130. [17, 74, 46],
  131. [7, 54, 24, 16, 55, 25],
  132. [34, 37, 13],
  133. # 23
  134. [4, 151, 121, 5, 152, 122],
  135. [4, 75, 47, 14, 76, 48],
  136. [11, 54, 24, 14, 55, 25],
  137. [16, 45, 15, 14, 46, 16],
  138. # 24
  139. [6, 147, 117, 4, 148, 118],
  140. [6, 73, 45, 14, 74, 46],
  141. [11, 54, 24, 16, 55, 25],
  142. [30, 46, 16, 2, 47, 17],
  143. # 25
  144. [8, 132, 106, 4, 133, 107],
  145. [8, 75, 47, 13, 76, 48],
  146. [7, 54, 24, 22, 55, 25],
  147. [22, 45, 15, 13, 46, 16],
  148. # 26
  149. [10, 142, 114, 2, 143, 115],
  150. [19, 74, 46, 4, 75, 47],
  151. [28, 50, 22, 6, 51, 23],
  152. [33, 46, 16, 4, 47, 17],
  153. # 27
  154. [8, 152, 122, 4, 153, 123],
  155. [22, 73, 45, 3, 74, 46],
  156. [8, 53, 23, 26, 54, 24],
  157. [12, 45, 15, 28, 46, 16],
  158. # 28
  159. [3, 147, 117, 10, 148, 118],
  160. [3, 73, 45, 23, 74, 46],
  161. [4, 54, 24, 31, 55, 25],
  162. [11, 45, 15, 31, 46, 16],
  163. # 29
  164. [7, 146, 116, 7, 147, 117],
  165. [21, 73, 45, 7, 74, 46],
  166. [1, 53, 23, 37, 54, 24],
  167. [19, 45, 15, 26, 46, 16],
  168. # 30
  169. [5, 145, 115, 10, 146, 116],
  170. [19, 75, 47, 10, 76, 48],
  171. [15, 54, 24, 25, 55, 25],
  172. [23, 45, 15, 25, 46, 16],
  173. # 31
  174. [13, 145, 115, 3, 146, 116],
  175. [2, 74, 46, 29, 75, 47],
  176. [42, 54, 24, 1, 55, 25],
  177. [23, 45, 15, 28, 46, 16],
  178. # 32
  179. [17, 145, 115],
  180. [10, 74, 46, 23, 75, 47],
  181. [10, 54, 24, 35, 55, 25],
  182. [19, 45, 15, 35, 46, 16],
  183. # 33
  184. [17, 145, 115, 1, 146, 116],
  185. [14, 74, 46, 21, 75, 47],
  186. [29, 54, 24, 19, 55, 25],
  187. [11, 45, 15, 46, 46, 16],
  188. # 34
  189. [13, 145, 115, 6, 146, 116],
  190. [14, 74, 46, 23, 75, 47],
  191. [44, 54, 24, 7, 55, 25],
  192. [59, 46, 16, 1, 47, 17],
  193. # 35
  194. [12, 151, 121, 7, 152, 122],
  195. [12, 75, 47, 26, 76, 48],
  196. [39, 54, 24, 14, 55, 25],
  197. [22, 45, 15, 41, 46, 16],
  198. # 36
  199. [6, 151, 121, 14, 152, 122],
  200. [6, 75, 47, 34, 76, 48],
  201. [46, 54, 24, 10, 55, 25],
  202. [2, 45, 15, 64, 46, 16],
  203. # 37
  204. [17, 152, 122, 4, 153, 123],
  205. [29, 74, 46, 14, 75, 47],
  206. [49, 54, 24, 10, 55, 25],
  207. [24, 45, 15, 46, 46, 16],
  208. # 38
  209. [4, 152, 122, 18, 153, 123],
  210. [13, 74, 46, 32, 75, 47],
  211. [48, 54, 24, 14, 55, 25],
  212. [42, 45, 15, 32, 46, 16],
  213. # 39
  214. [20, 147, 117, 4, 148, 118],
  215. [40, 75, 47, 7, 76, 48],
  216. [43, 54, 24, 22, 55, 25],
  217. [10, 45, 15, 67, 46, 16],
  218. # 40
  219. [19, 148, 118, 6, 149, 119],
  220. [18, 75, 47, 31, 76, 48],
  221. [34, 54, 24, 34, 55, 25],
  222. [20, 45, 15, 61, 46, 16]
  223. ]
  224. def glog(n):
  225. if n < 1: # pragma: no cover
  226. raise ValueError("glog(%s)" % n)
  227. return LOG_TABLE[n]
  228. def gexp(n):
  229. return EXP_TABLE[n % 255]
  230. class Polynomial:
  231. def __init__(self, num, shift):
  232. if not num: # pragma: no cover
  233. raise Exception("%s/%s" % (len(num), shift))
  234. for offset in range(len(num)):
  235. if num[offset] != 0:
  236. break
  237. else:
  238. offset += 1
  239. self.num = num[offset:] + [0] * shift
  240. def __getitem__(self, index):
  241. return self.num[index]
  242. def __iter__(self):
  243. return iter(self.num)
  244. def __len__(self):
  245. return len(self.num)
  246. def __mul__(self, other):
  247. num = [0] * (len(self) + len(other) - 1)
  248. for i, item in enumerate(self):
  249. for j, other_item in enumerate(other):
  250. num[i + j] ^= gexp(glog(item) + glog(other_item))
  251. return Polynomial(num, 0)
  252. def __mod__(self, other):
  253. difference = len(self) - len(other)
  254. if difference < 0:
  255. return self
  256. ratio = glog(self[0]) - glog(other[0])
  257. num = [
  258. item ^ gexp(glog(other_item) + ratio)
  259. for item, other_item in zip(self, other)]
  260. if difference:
  261. num.extend(self[-difference:])
  262. # recursive call
  263. return Polynomial(num, 0) % other
  264. class RSBlock:
  265. def __init__(self, total_count, data_count):
  266. self.total_count = total_count
  267. self.data_count = data_count
  268. def rs_blocks(version, error_correction):
  269. if error_correction not in RS_BLOCK_OFFSET: # pragma: no cover
  270. raise Exception(
  271. "bad rs block @ version: %s / error_correction: %s" %
  272. (version, error_correction))
  273. offset = RS_BLOCK_OFFSET[error_correction]
  274. rs_block = RS_BLOCK_TABLE[(version - 1) * 4 + offset]
  275. blocks = []
  276. for i in range(0, len(rs_block), 3):
  277. count, total_count, data_count = rs_block[i:i + 3]
  278. for j in range(count):
  279. blocks.append(RSBlock(total_count, data_count))
  280. return blocks