pyqrnative.py
Go to the documentation of this file.
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 


pyqrnative
Author(s): Sam Curren
autogenerated on Mon Dec 2 2013 11:36:47