$search
00001 import math 00002 from PIL import Image, ImageDraw 00003 00004 #QRCode for Python 00005 # 00006 #Ported from the Javascript library by Sam Curren 00007 # 00008 #QRCode for Javascript 00009 #http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/qrcode.js 00010 # 00011 #Copyright (c) 2009 Kazuhiko Arase 00012 # 00013 #URL: http://www.d-project.com/ 00014 # 00015 #Licensed under the MIT license: 00016 # http://www.opensource.org/licenses/mit-license.php 00017 # 00018 # The word "QR Code" is registered trademark of 00019 # DENSO WAVE INCORPORATED 00020 # http://www.denso-wave.com/qrcode/faqpatent-e.html 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 #// not JIS ... 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 #//(col + row) % 3; 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 #pixels per box 00123 offset = 4 #boxes as border 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 #// vertical 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 #// horizontal 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 #// fixed module 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 #// calc num max data. 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 #// end code 00287 if (buffer.getLengthInBits() + 4 <= totalDataCount * 8): 00288 buffer.put(0, 4) 00289 00290 #// padding 00291 while (buffer.getLengthInBits() % 8 != 0): 00292 buffer.putBit(False) 00293 00294 #// padding 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 #// 1 - 9 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 #// 10 - 26 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 #// 27 - 40 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 #// LEVEL1 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 #// LEVEL2 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 #// LEVEL3 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 #// LEVEL4 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 # recursive call 00667 return QRPolynomial(num, 0).mod(e); 00668 00669 class QRRSBlock: 00670 00671 RS_BLOCK_TABLE = [ 00672 00673 #// L 00674 #// M 00675 #// Q 00676 #// H 00677 00678 #// 1 00679 [1, 26, 19], 00680 [1, 26, 16], 00681 [1, 26, 13], 00682 [1, 26, 9], 00683 00684 #// 2 00685 [1, 44, 34], 00686 [1, 44, 28], 00687 [1, 44, 22], 00688 [1, 44, 16], 00689 00690 #// 3 00691 [1, 70, 55], 00692 [1, 70, 44], 00693 [2, 35, 17], 00694 [2, 35, 13], 00695 00696 #// 4 00697 [1, 100, 80], 00698 [2, 50, 32], 00699 [2, 50, 24], 00700 [4, 25, 9], 00701 00702 #// 5 00703 [1, 134, 108], 00704 [2, 67, 43], 00705 [2, 33, 15, 2, 34, 16], 00706 [2, 33, 11, 2, 34, 12], 00707 00708 #// 6 00709 [2, 86, 68], 00710 [4, 43, 27], 00711 [4, 43, 19], 00712 [4, 43, 15], 00713 00714 #// 7 00715 [2, 98, 78], 00716 [4, 49, 31], 00717 [2, 32, 14, 4, 33, 15], 00718 [4, 39, 13, 1, 40, 14], 00719 00720 #// 8 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 #// 9 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 #// 10 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 # 11 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 # 12 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 # 13 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 # 14 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 # 15 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 # 16 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 # 17 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 # 18 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 # 19 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 # 20 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 # 21 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 # 22 00805 [2, 139, 111, 7, 140, 112], 00806 [17, 74, 46], 00807 [7, 54, 24, 16, 55, 25], 00808 [34, 37, 13], 00809 00810 # 23 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 # 24 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 # 25 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 # 26 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 # 27 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 # 28 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 # 29 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 # 30 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 # 31 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 # 32 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 # 33 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 # 34 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 # 35 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 # 36 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 # 37 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 # 38 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 # 39 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 # 40 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