00001 import math
00002 from PIL import Image, ImageDraw
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 class QR8bitByte:
00024
00025 def __init__(self, data):
00026 self.mode = QRMode.MODE_8BIT_BYTE
00027 self.data = data
00028
00029 def getLength(self):
00030 return len(self.data)
00031
00032 def write(self, buffer):
00033 for i in range(len(self.data)):
00034
00035 buffer.put(ord(self.data[i]), 8)
00036 def __repr__(self):
00037 return self.data
00038
00039 class QRCode:
00040 def __init__(self, typeNumber, errorCorrectLevel):
00041 self.typeNumber = typeNumber
00042 self.errorCorrectLevel = errorCorrectLevel
00043 self.modules = None
00044 self.moduleCount = 0
00045 self.dataCache = None
00046 self.dataList = []
00047 def addData(self, data):
00048 newData = QR8bitByte(data)
00049 self.dataList.append(newData)
00050 self.dataCache = None
00051 def isDark(self, row, col):
00052 if (row < 0 or self.moduleCount <= row or col < 0 or self.moduleCount <= col):
00053 raise Exception("%s,%s - %s" % (row, col, self.moduleCount))
00054 return self.modules[row][col]
00055 def getModuleCount(self):
00056 return self.moduleCount
00057 def make(self):
00058 self.makeImpl(False, self.getBestMaskPattern() )
00059 def makeImpl(self, test, maskPattern):
00060
00061 self.moduleCount = self.typeNumber * 4 + 17
00062 self.modules = [None for x in range(self.moduleCount)]
00063
00064 for row in range(self.moduleCount):
00065
00066 self.modules[row] = [None for x in range(self.moduleCount)]
00067
00068 for col in range(self.moduleCount):
00069 self.modules[row][col] = None
00070
00071 self.setupPositionProbePattern(0, 0)
00072 self.setupPositionProbePattern(self.moduleCount - 7, 0)
00073 self.setupPositionProbePattern(0, self.moduleCount - 7)
00074 self.setupPositionAdjustPattern()
00075 self.setupTimingPattern()
00076 self.setupTypeInfo(test, maskPattern)
00077
00078 if (self.typeNumber >= 7):
00079 self.setupTypeNumber(test)
00080
00081 if (self.dataCache == None):
00082 self.dataCache = QRCode.createData(self.typeNumber, self.errorCorrectLevel, self.dataList)
00083 self.mapData(self.dataCache, maskPattern)
00084
00085 def setupPositionProbePattern(self, row, col):
00086
00087 for r in range(-1, 8):
00088
00089 if (row + r <= -1 or self.moduleCount <= row + r): continue
00090
00091 for c in range(-1, 8):
00092
00093 if (col + c <= -1 or self.moduleCount <= col + c): continue
00094
00095 if ( (0 <= r and r <= 6 and (c == 0 or c == 6) )
00096 or (0 <= c and c <= 6 and (r == 0 or r == 6) )
00097 or (2 <= r and r <= 4 and 2 <= c and c <= 4) ):
00098 self.modules[row + r][col + c] = True;
00099 else:
00100 self.modules[row + r][col + c] = False;
00101
00102 def getBestMaskPattern(self):
00103
00104 minLostPoint = 0
00105 pattern = 0
00106
00107 for i in range(8):
00108
00109 self.makeImpl(True, i);
00110
00111 lostPoint = QRUtil.getLostPoint(self);
00112
00113 if (i == 0 or minLostPoint > lostPoint):
00114 minLostPoint = lostPoint
00115 pattern = i
00116
00117 return pattern
00118
00119 def createMovieClip(self):
00120 raise Exception("Method not relevant to Python port")
00121 def makeImage(self):
00122 boxsize = 10
00123 offset = 4
00124 pixelsize = (self.getModuleCount() + offset + offset) * boxsize
00125
00126 im = Image.new("RGB", (pixelsize, pixelsize), "white")
00127 d = ImageDraw.Draw(im)
00128
00129 for r in range(self.getModuleCount()):
00130 for c in range(self.getModuleCount()):
00131 if (self.isDark(r, c) ):
00132 x = (c + offset) * boxsize
00133 y = (r + offset) * boxsize
00134 b = [(x,y),(x+boxsize,y+boxsize)]
00135 d.rectangle(b,fill="black")
00136 del d
00137 return im
00138
00139 def setupTimingPattern(self):
00140
00141 for r in range(8, self.moduleCount - 8):
00142 if (self.modules[r][6] != None):
00143 continue
00144 self.modules[r][6] = (r % 2 == 0)
00145
00146 for c in range(8, self.moduleCount - 8):
00147 if (self.modules[6][c] != None):
00148 continue
00149 self.modules[6][c] = (c % 2 == 0)
00150
00151 def setupPositionAdjustPattern(self):
00152
00153 pos = QRUtil.getPatternPosition(self.typeNumber)
00154
00155 for i in range(len(pos)):
00156
00157 for j in range(len(pos)):
00158
00159 row = pos[i]
00160 col = pos[j]
00161
00162 if (self.modules[row][col] != None):
00163 continue
00164
00165 for r in range(-2, 3):
00166
00167 for c in range(-2, 3):
00168
00169 if (r == -2 or r == 2 or c == -2 or c == 2 or (r == 0 and c == 0) ):
00170 self.modules[row + r][col + c] = True
00171 else:
00172 self.modules[row + r][col + c] = False
00173
00174 def setupTypeNumber(self, test):
00175
00176 bits = QRUtil.getBCHTypeNumber(self.typeNumber)
00177
00178 for i in range(18):
00179 mod = (not test and ( (bits >> i) & 1) == 1)
00180 self.modules[i // 3][i % 3 + self.moduleCount - 8 - 3] = mod;
00181
00182 for i in range(18):
00183 mod = (not test and ( (bits >> i) & 1) == 1)
00184 self.modules[i % 3 + self.moduleCount - 8 - 3][i // 3] = mod;
00185
00186 def setupTypeInfo(self, test, maskPattern):
00187
00188 data = (self.errorCorrectLevel << 3) | maskPattern
00189 bits = QRUtil.getBCHTypeInfo(data)
00190
00191
00192 for i in range(15):
00193
00194 mod = (not test and ( (bits >> i) & 1) == 1)
00195
00196 if (i < 6):
00197 self.modules[i][8] = mod
00198 elif (i < 8):
00199 self.modules[i + 1][8] = mod
00200 else:
00201 self.modules[self.moduleCount - 15 + i][8] = mod
00202
00203
00204 for i in range(15):
00205
00206 mod = (not test and ( (bits >> i) & 1) == 1);
00207
00208 if (i < 8):
00209 self.modules[8][self.moduleCount - i - 1] = mod
00210 elif (i < 9):
00211 self.modules[8][15 - i - 1 + 1] = mod
00212 else:
00213 self.modules[8][15 - i - 1] = mod
00214
00215
00216 self.modules[self.moduleCount - 8][8] = (not test)
00217
00218 def mapData(self, data, maskPattern):
00219
00220 inc = -1
00221 row = self.moduleCount - 1
00222 bitIndex = 7
00223 byteIndex = 0
00224
00225 for col in range(self.moduleCount - 1, 0, -2):
00226
00227 if (col == 6): col-=1
00228
00229 while (True):
00230
00231 for c in range(2):
00232
00233 if (self.modules[row][col - c] == None):
00234
00235 dark = False
00236
00237 if (byteIndex < len(data)):
00238 dark = ( ( (data[byteIndex] >> bitIndex) & 1) == 1)
00239
00240 mask = QRUtil.getMask(maskPattern, row, col - c)
00241
00242 if (mask):
00243 dark = not dark
00244
00245 self.modules[row][col - c] = dark
00246 bitIndex-=1
00247
00248 if (bitIndex == -1):
00249 byteIndex+=1
00250 bitIndex = 7
00251
00252 row += inc
00253
00254 if (row < 0 or self.moduleCount <= row):
00255 row -= inc
00256 inc = -inc
00257 break
00258 PAD0 = 0xEC
00259 PAD1 = 0x11
00260
00261 @staticmethod
00262 def createData(typeNumber, errorCorrectLevel, dataList):
00263
00264 rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel)
00265
00266 buffer = QRBitBuffer();
00267
00268 for i in range(len(dataList)):
00269 data = dataList[i]
00270 buffer.put(data.mode, 4)
00271 buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) )
00272 data.write(buffer)
00273
00274
00275 totalDataCount = 0;
00276 for i in range(len(rsBlocks)):
00277 totalDataCount += rsBlocks[i].dataCount
00278
00279 if (buffer.getLengthInBits() > totalDataCount * 8):
00280 raise Exception("code length overflow. ("
00281 + buffer.getLengthInBits()
00282 + ">"
00283 + totalDataCount * 8
00284 + ")")
00285
00286
00287 if (buffer.getLengthInBits() + 4 <= totalDataCount * 8):
00288 buffer.put(0, 4)
00289
00290
00291 while (buffer.getLengthInBits() % 8 != 0):
00292 buffer.putBit(False)
00293
00294
00295 while (True):
00296
00297 if (buffer.getLengthInBits() >= totalDataCount * 8):
00298 break
00299 buffer.put(QRCode.PAD0, 8)
00300
00301 if (buffer.getLengthInBits() >= totalDataCount * 8):
00302 break
00303 buffer.put(QRCode.PAD1, 8)
00304
00305 return QRCode.createBytes(buffer, rsBlocks)
00306
00307 @staticmethod
00308 def createBytes(buffer, rsBlocks):
00309
00310 offset = 0
00311
00312 maxDcCount = 0
00313 maxEcCount = 0
00314
00315 dcdata = [0 for x in range(len(rsBlocks))]
00316 ecdata = [0 for x in range(len(rsBlocks))]
00317
00318 for r in range(len(rsBlocks)):
00319
00320 dcCount = rsBlocks[r].dataCount
00321 ecCount = rsBlocks[r].totalCount - dcCount
00322
00323 maxDcCount = max(maxDcCount, dcCount)
00324 maxEcCount = max(maxEcCount, ecCount)
00325
00326 dcdata[r] = [0 for x in range(dcCount)]
00327
00328 for i in range(len(dcdata[r])):
00329 dcdata[r][i] = 0xff & buffer.buffer[i + offset]
00330 offset += dcCount
00331
00332 rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount)
00333 rawPoly = QRPolynomial(dcdata[r], rsPoly.getLength() - 1)
00334
00335 modPoly = rawPoly.mod(rsPoly)
00336 ecdata[r] = [0 for x in range(rsPoly.getLength()-1)]
00337 for i in range(len(ecdata[r])):
00338 modIndex = i + modPoly.getLength() - len(ecdata[r])
00339 if (modIndex >= 0):
00340 ecdata[r][i] = modPoly.get(modIndex)
00341 else:
00342 ecdata[r][i] = 0
00343
00344 totalCodeCount = 0
00345 for i in range(len(rsBlocks)):
00346 totalCodeCount += rsBlocks[i].totalCount
00347
00348 data = [None for x in range(totalCodeCount)]
00349 index = 0
00350
00351 for i in range(maxDcCount):
00352 for r in range(len(rsBlocks)):
00353 if (i < len(dcdata[r])):
00354 data[index] = dcdata[r][i]
00355 index+=1
00356
00357 for i in range(maxEcCount):
00358 for r in range(len(rsBlocks)):
00359 if (i < len(ecdata[r])):
00360 data[index] = ecdata[r][i]
00361 index+=1
00362
00363 return data
00364
00365
00366 class QRMode:
00367 MODE_NUMBER = 1 << 0
00368 MODE_ALPHA_NUM = 1 << 1
00369 MODE_8BIT_BYTE = 1 << 2
00370 MODE_KANJI = 1 << 3
00371
00372 class QRErrorCorrectLevel:
00373 L = 1
00374 M = 0
00375 Q = 3
00376 H = 2
00377
00378 class QRMaskPattern:
00379 PATTERN000 = 0
00380 PATTERN001 = 1
00381 PATTERN010 = 2
00382 PATTERN011 = 3
00383 PATTERN100 = 4
00384 PATTERN101 = 5
00385 PATTERN110 = 6
00386 PATTERN111 = 7
00387
00388 class QRUtil(object):
00389 PATTERN_POSITION_TABLE = [
00390 [],
00391 [6, 18],
00392 [6, 22],
00393 [6, 26],
00394 [6, 30],
00395 [6, 34],
00396 [6, 22, 38],
00397 [6, 24, 42],
00398 [6, 26, 46],
00399 [6, 28, 50],
00400 [6, 30, 54],
00401 [6, 32, 58],
00402 [6, 34, 62],
00403 [6, 26, 46, 66],
00404 [6, 26, 48, 70],
00405 [6, 26, 50, 74],
00406 [6, 30, 54, 78],
00407 [6, 30, 56, 82],
00408 [6, 30, 58, 86],
00409 [6, 34, 62, 90],
00410 [6, 28, 50, 72, 94],
00411 [6, 26, 50, 74, 98],
00412 [6, 30, 54, 78, 102],
00413 [6, 28, 54, 80, 106],
00414 [6, 32, 58, 84, 110],
00415 [6, 30, 58, 86, 114],
00416 [6, 34, 62, 90, 118],
00417 [6, 26, 50, 74, 98, 122],
00418 [6, 30, 54, 78, 102, 126],
00419 [6, 26, 52, 78, 104, 130],
00420 [6, 30, 56, 82, 108, 134],
00421 [6, 34, 60, 86, 112, 138],
00422 [6, 30, 58, 86, 114, 142],
00423 [6, 34, 62, 90, 118, 146],
00424 [6, 30, 54, 78, 102, 126, 150],
00425 [6, 24, 50, 76, 102, 128, 154],
00426 [6, 28, 54, 80, 106, 132, 158],
00427 [6, 32, 58, 84, 110, 136, 162],
00428 [6, 26, 54, 82, 110, 138, 166],
00429 [6, 30, 58, 86, 114, 142, 170]
00430 ]
00431
00432 G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0)
00433 G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0)
00434 G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1)
00435
00436 @staticmethod
00437 def getBCHTypeInfo(data):
00438 d = data << 10;
00439 while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0):
00440 d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) )
00441
00442 return ( (data << 10) | d) ^ QRUtil.G15_MASK
00443 @staticmethod
00444 def getBCHTypeNumber(data):
00445 d = data << 12;
00446 while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0):
00447 d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) )
00448 return (data << 12) | d
00449 @staticmethod
00450 def getBCHDigit(data):
00451 digit = 0;
00452 while (data != 0):
00453 digit += 1
00454 data >>= 1
00455 return digit
00456 @staticmethod
00457 def getPatternPosition(typeNumber):
00458 return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]
00459 @staticmethod
00460 def getMask(maskPattern, i, j):
00461 if maskPattern == QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0
00462 if maskPattern == QRMaskPattern.PATTERN001 : return i % 2 == 0
00463 if maskPattern == QRMaskPattern.PATTERN010 : return j % 3 == 0
00464 if maskPattern == QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0
00465 if maskPattern == QRMaskPattern.PATTERN100 : return (math.floor(i / 2) + math.floor(j / 3) ) % 2 == 0
00466 if maskPattern == QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0
00467 if maskPattern == QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0
00468 if maskPattern == QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0
00469 raise Exception("bad maskPattern:" + maskPattern);
00470 @staticmethod
00471 def getErrorCorrectPolynomial(errorCorrectLength):
00472 a = QRPolynomial([1], 0);
00473 for i in range(errorCorrectLength):
00474 a = a.multiply(QRPolynomial([1, QRMath.gexp(i)], 0) )
00475 return a
00476 @staticmethod
00477 def getLengthInBits(mode, type):
00478
00479 if 1 <= type and type < 10:
00480
00481
00482
00483 if mode == QRMode.MODE_NUMBER : return 10
00484 if mode == QRMode.MODE_ALPHA_NUM : return 9
00485 if mode == QRMode.MODE_8BIT_BYTE : return 8
00486 if mode == QRMode.MODE_KANJI : return 8
00487 raise Exception("mode:" + mode)
00488
00489 elif (type < 27):
00490
00491
00492
00493 if mode == QRMode.MODE_NUMBER : return 12
00494 if mode == QRMode.MODE_ALPHA_NUM : return 11
00495 if mode == QRMode.MODE_8BIT_BYTE : return 16
00496 if mode == QRMode.MODE_KANJI : return 10
00497 raise Exception("mode:" + mode)
00498
00499 elif (type < 41):
00500
00501
00502
00503 if mode == QRMode.MODE_NUMBER : return 14
00504 if mode == QRMode.MODE_ALPHA_NUM : return 13
00505 if mode == QRMode.MODE_8BIT_BYTE : return 16
00506 if mode == QRMode.MODE_KANJI : return 12
00507 raise Exception("mode:" + mode)
00508
00509 else:
00510 raise Exception("type:" + type)
00511 @staticmethod
00512 def getLostPoint(qrCode):
00513
00514 moduleCount = qrCode.getModuleCount();
00515
00516 lostPoint = 0;
00517
00518
00519
00520 for row in range(moduleCount):
00521
00522 for col in range(moduleCount):
00523
00524 sameCount = 0;
00525 dark = qrCode.isDark(row, col);
00526
00527 for r in range(-1, 2):
00528
00529 if (row + r < 0 or moduleCount <= row + r):
00530 continue
00531
00532 for c in range(-1, 2):
00533
00534 if (col + c < 0 or moduleCount <= col + c):
00535 continue
00536 if (r == 0 and c == 0):
00537 continue
00538
00539 if (dark == qrCode.isDark(row + r, col + c) ):
00540 sameCount+=1
00541 if (sameCount > 5):
00542 lostPoint += (3 + sameCount - 5)
00543
00544
00545
00546 for row in range(moduleCount - 1):
00547 for col in range(moduleCount - 1):
00548 count = 0;
00549 if (qrCode.isDark(row, col ) ): count+=1
00550 if (qrCode.isDark(row + 1, col ) ): count+=1
00551 if (qrCode.isDark(row, col + 1) ): count+=1
00552 if (qrCode.isDark(row + 1, col + 1) ): count+=1
00553 if (count == 0 or count == 4):
00554 lostPoint += 3
00555
00556
00557
00558 for row in range(moduleCount):
00559 for col in range(moduleCount - 6):
00560 if (qrCode.isDark(row, col)
00561 and not qrCode.isDark(row, col + 1)
00562 and qrCode.isDark(row, col + 2)
00563 and qrCode.isDark(row, col + 3)
00564 and qrCode.isDark(row, col + 4)
00565 and not qrCode.isDark(row, col + 5)
00566 and qrCode.isDark(row, col + 6) ):
00567 lostPoint += 40
00568
00569 for col in range(moduleCount):
00570 for row in range(moduleCount - 6):
00571 if (qrCode.isDark(row, col)
00572 and not qrCode.isDark(row + 1, col)
00573 and qrCode.isDark(row + 2, col)
00574 and qrCode.isDark(row + 3, col)
00575 and qrCode.isDark(row + 4, col)
00576 and not qrCode.isDark(row + 5, col)
00577 and qrCode.isDark(row + 6, col) ):
00578 lostPoint += 40
00579
00580
00581
00582 darkCount = 0;
00583
00584 for col in range(moduleCount):
00585 for row in range(moduleCount):
00586 if (qrCode.isDark(row, col) ):
00587 darkCount+=1
00588
00589 ratio = abs(100 * darkCount / moduleCount / moduleCount - 50) / 5
00590 lostPoint += ratio * 10
00591
00592 return lostPoint
00593
00594 class QRMath:
00595
00596 @staticmethod
00597 def glog(n):
00598 if (n < 1):
00599 raise Exception("glog(" + n + ")")
00600 return LOG_TABLE[n];
00601 @staticmethod
00602 def gexp(n):
00603 while n < 0:
00604 n += 255
00605 while n >= 256:
00606 n -= 255
00607 return EXP_TABLE[n];
00608
00609 EXP_TABLE = [x for x in range(256)]
00610
00611 LOG_TABLE = [x for x in range(256)]
00612
00613 for i in range(8):
00614 EXP_TABLE[i] = 1 << i;
00615
00616 for i in range(8, 256):
00617 EXP_TABLE[i] = EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8]
00618
00619 for i in range(255):
00620 LOG_TABLE[EXP_TABLE[i] ] = i
00621
00622 class QRPolynomial:
00623
00624 def __init__(self, num, shift):
00625
00626 if (len(num) == 0):
00627 raise Exception(num.length + "/" + shift)
00628
00629 offset = 0
00630
00631 while offset < len(num) and num[offset] == 0:
00632 offset += 1
00633
00634 self.num = [0 for x in range(len(num)-offset+shift)]
00635 for i in range(len(num) - offset):
00636 self.num[i] = num[i + offset]
00637
00638
00639 def get(self, index):
00640 return self.num[index]
00641 def getLength(self):
00642 return len(self.num)
00643 def multiply(self, e):
00644 num = [0 for x in range(self.getLength() + e.getLength() - 1)];
00645
00646 for i in range(self.getLength()):
00647 for j in range(e.getLength()):
00648 num[i + j] ^= QRMath.gexp(QRMath.glog(self.get(i) ) + QRMath.glog(e.get(j) ) )
00649
00650 return QRPolynomial(num, 0);
00651 def mod(self, e):
00652
00653 if (self.getLength() - e.getLength() < 0):
00654 return self;
00655
00656 ratio = QRMath.glog(self.get(0) ) - QRMath.glog(e.get(0) )
00657
00658 num = [0 for x in range(self.getLength())]
00659
00660 for i in range(self.getLength()):
00661 num[i] = self.get(i);
00662
00663 for i in range(e.getLength()):
00664 num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio)
00665
00666
00667 return QRPolynomial(num, 0).mod(e);
00668
00669 class QRRSBlock:
00670
00671 RS_BLOCK_TABLE = [
00672
00673
00674
00675
00676
00677
00678
00679 [1, 26, 19],
00680 [1, 26, 16],
00681 [1, 26, 13],
00682 [1, 26, 9],
00683
00684
00685 [1, 44, 34],
00686 [1, 44, 28],
00687 [1, 44, 22],
00688 [1, 44, 16],
00689
00690
00691 [1, 70, 55],
00692 [1, 70, 44],
00693 [2, 35, 17],
00694 [2, 35, 13],
00695
00696
00697 [1, 100, 80],
00698 [2, 50, 32],
00699 [2, 50, 24],
00700 [4, 25, 9],
00701
00702
00703 [1, 134, 108],
00704 [2, 67, 43],
00705 [2, 33, 15, 2, 34, 16],
00706 [2, 33, 11, 2, 34, 12],
00707
00708
00709 [2, 86, 68],
00710 [4, 43, 27],
00711 [4, 43, 19],
00712 [4, 43, 15],
00713
00714
00715 [2, 98, 78],
00716 [4, 49, 31],
00717 [2, 32, 14, 4, 33, 15],
00718 [4, 39, 13, 1, 40, 14],
00719
00720
00721 [2, 121, 97],
00722 [2, 60, 38, 2, 61, 39],
00723 [4, 40, 18, 2, 41, 19],
00724 [4, 40, 14, 2, 41, 15],
00725
00726
00727 [2, 146, 116],
00728 [3, 58, 36, 2, 59, 37],
00729 [4, 36, 16, 4, 37, 17],
00730 [4, 36, 12, 4, 37, 13],
00731
00732
00733 [2, 86, 68, 2, 87, 69],
00734 [4, 69, 43, 1, 70, 44],
00735 [6, 43, 19, 2, 44, 20],
00736 [6, 43, 15, 2, 44, 16],
00737
00738
00739 [4, 101, 81],
00740 [1, 80, 50, 4, 81, 51],
00741 [4, 50, 22, 4, 51, 23],
00742 [3, 36, 12, 8, 37, 13],
00743
00744
00745 [2, 116, 92, 2, 117, 93],
00746 [6, 58, 36, 2, 59, 37],
00747 [4, 46, 20, 6, 47, 21],
00748 [7, 42, 14, 4, 43, 15],
00749
00750
00751 [4, 133, 107],
00752 [8, 59, 37, 1, 60, 38],
00753 [8, 44, 20, 4, 45, 21],
00754 [12, 33, 11, 4, 34, 12],
00755
00756
00757 [3, 145, 115, 1, 146, 116],
00758 [4, 64, 40, 5, 65, 41],
00759 [11, 36, 16, 5, 37, 17],
00760 [11, 36, 12, 5, 37, 13],
00761
00762
00763 [5, 109, 87, 1, 110, 88],
00764 [5, 65, 41, 5, 66, 42],
00765 [5, 54, 24, 7, 55, 25],
00766 [11, 36, 12],
00767
00768
00769 [5, 122, 98, 1, 123, 99],
00770 [7, 73, 45, 3, 74, 46],
00771 [15, 43, 19, 2, 44, 20],
00772 [3, 45, 15, 13, 46, 16],
00773
00774
00775 [1, 135, 107, 5, 136, 108],
00776 [10, 74, 46, 1, 75, 47],
00777 [1, 50, 22, 15, 51, 23],
00778 [2, 42, 14, 17, 43, 15],
00779
00780
00781 [5, 150, 120, 1, 151, 121],
00782 [9, 69, 43, 4, 70, 44],
00783 [17, 50, 22, 1, 51, 23],
00784 [2, 42, 14, 19, 43, 15],
00785
00786
00787 [3, 141, 113, 4, 142, 114],
00788 [3, 70, 44, 11, 71, 45],
00789 [17, 47, 21, 4, 48, 22],
00790 [9, 39, 13, 16, 40, 14],
00791
00792
00793 [3, 135, 107, 5, 136, 108],
00794 [3, 67, 41, 13, 68, 42],
00795 [15, 54, 24, 5, 55, 25],
00796 [15, 43, 15, 10, 44, 16],
00797
00798
00799 [4, 144, 116, 4, 145, 117],
00800 [17, 68, 42],
00801 [17, 50, 22, 6, 51, 23],
00802 [19, 46, 16, 6, 47, 17],
00803
00804
00805 [2, 139, 111, 7, 140, 112],
00806 [17, 74, 46],
00807 [7, 54, 24, 16, 55, 25],
00808 [34, 37, 13],
00809
00810
00811 [4, 151, 121, 5, 152, 122],
00812 [4, 75, 47, 14, 76, 48],
00813 [11, 54, 24, 14, 55, 25],
00814 [16, 45, 15, 14, 46, 16],
00815
00816
00817 [6, 147, 117, 4, 148, 118],
00818 [6, 73, 45, 14, 74, 46],
00819 [11, 54, 24, 16, 55, 25],
00820 [30, 46, 16, 2, 47, 17],
00821
00822
00823 [8, 132, 106, 4, 133, 107],
00824 [8, 75, 47, 13, 76, 48],
00825 [7, 54, 24, 22, 55, 25],
00826 [22, 45, 15, 13, 46, 16],
00827
00828
00829 [10, 142, 114, 2, 143, 115],
00830 [19, 74, 46, 4, 75, 47],
00831 [28, 50, 22, 6, 51, 23],
00832 [33, 46, 16, 4, 47, 17],
00833
00834
00835 [8, 152, 122, 4, 153, 123],
00836 [22, 73, 45, 3, 74, 46],
00837 [8, 53, 23, 26, 54, 24],
00838 [12, 45, 15, 28, 46, 16],
00839
00840
00841 [3, 147, 117, 10, 148, 118],
00842 [3, 73, 45, 23, 74, 46],
00843 [4, 54, 24, 31, 55, 25],
00844 [11, 45, 15, 31, 46, 16],
00845
00846
00847 [7, 146, 116, 7, 147, 117],
00848 [21, 73, 45, 7, 74, 46],
00849 [1, 53, 23, 37, 54, 24],
00850 [19, 45, 15, 26, 46, 16],
00851
00852
00853 [5, 145, 115, 10, 146, 116],
00854 [19, 75, 47, 10, 76, 48],
00855 [15, 54, 24, 25, 55, 25],
00856 [23, 45, 15, 25, 46, 16],
00857
00858
00859 [13, 145, 115, 3, 146, 116],
00860 [2, 74, 46, 29, 75, 47],
00861 [42, 54, 24, 1, 55, 25],
00862 [23, 45, 15, 28, 46, 16],
00863
00864
00865 [17, 145, 115],
00866 [10, 74, 46, 23, 75, 47],
00867 [10, 54, 24, 35, 55, 25],
00868 [19, 45, 15, 35, 46, 16],
00869
00870
00871 [17, 145, 115, 1, 146, 116],
00872 [14, 74, 46, 21, 75, 47],
00873 [29, 54, 24, 19, 55, 25],
00874 [11, 45, 15, 46, 46, 16],
00875
00876
00877 [13, 145, 115, 6, 146, 116],
00878 [14, 74, 46, 23, 75, 47],
00879 [44, 54, 24, 7, 55, 25],
00880 [59, 46, 16, 1, 47, 17],
00881
00882
00883 [12, 151, 121, 7, 152, 122],
00884 [12, 75, 47, 26, 76, 48],
00885 [39, 54, 24, 14, 55, 25],
00886 [22, 45, 15, 41, 46, 16],
00887
00888
00889 [6, 151, 121, 14, 152, 122],
00890 [6, 75, 47, 34, 76, 48],
00891 [46, 54, 24, 10, 55, 25],
00892 [2, 45, 15, 64, 46, 16],
00893
00894
00895 [17, 152, 122, 4, 153, 123],
00896 [29, 74, 46, 14, 75, 47],
00897 [49, 54, 24, 10, 55, 25],
00898 [24, 45, 15, 46, 46, 16],
00899
00900
00901 [4, 152, 122, 18, 153, 123],
00902 [13, 74, 46, 32, 75, 47],
00903 [48, 54, 24, 14, 55, 25],
00904 [42, 45, 15, 32, 46, 16],
00905
00906
00907 [20, 147, 117, 4, 148, 118],
00908 [40, 75, 47, 7, 76, 48],
00909 [43, 54, 24, 22, 55, 25],
00910 [10, 45, 15, 67, 46, 16],
00911
00912
00913 [19, 148, 118, 6, 149, 119],
00914 [18, 75, 47, 31, 76, 48],
00915 [34, 54, 24, 34, 55, 25],
00916 [20, 45, 15, 61, 46, 16]
00917
00918 ]
00919
00920 def __init__(self, totalCount, dataCount):
00921 self.totalCount = totalCount
00922 self.dataCount = dataCount
00923
00924 @staticmethod
00925 def getRSBlocks(typeNumber, errorCorrectLevel):
00926 rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
00927 if rsBlock == None:
00928 raise Exception("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel)
00929
00930 length = len(rsBlock) / 3
00931
00932 list = []
00933
00934 for i in range(length):
00935
00936 count = rsBlock[i * 3 + 0]
00937 totalCount = rsBlock[i * 3 + 1]
00938 dataCount = rsBlock[i * 3 + 2]
00939
00940 for j in range(count):
00941 list.append(QRRSBlock(totalCount, dataCount))
00942
00943 return list;
00944
00945 @staticmethod
00946 def getRsBlockTable(typeNumber, errorCorrectLevel):
00947 if errorCorrectLevel == QRErrorCorrectLevel.L:
00948 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
00949 elif errorCorrectLevel == QRErrorCorrectLevel.M:
00950 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
00951 elif errorCorrectLevel == QRErrorCorrectLevel.Q:
00952 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
00953 elif errorCorrectLevel == QRErrorCorrectLevel.H:
00954 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
00955 else:
00956 return None;
00957
00958 class QRBitBuffer:
00959 def __init__(self):
00960 self.buffer = []
00961 self.length = 0
00962 def __repr__(self):
00963 return ".".join([str(n) for n in self.buffer])
00964 def get(self, index):
00965 bufIndex = math.floor(index / 8)
00966 val = ( (self.buffer[bufIndex] >> (7 - index % 8) ) & 1) == 1
00967 print "get ", val
00968 return ( (self.buffer[bufIndex] >> (7 - index % 8) ) & 1) == 1
00969 def put(self, num, length):
00970 for i in range(length):
00971 self.putBit( ( (num >> (length - i - 1) ) & 1) == 1)
00972 def getLengthInBits(self):
00973 return self.length
00974 def putBit(self, bit):
00975 bufIndex = self.length // 8
00976 if len(self.buffer) <= bufIndex:
00977 self.buffer.append(0)
00978 if bit:
00979 self.buffer[bufIndex] |= (0x80 >> (self.length % 8) )
00980 self.length+=1
00981
00982 def show_data(data):
00983 qr = QRCode(6, QRErrorCorrectLevel.L)
00984 qr.addData(data)
00985 qr.make()
00986 im = qr.makeImage()
00987 im.show()
00988