├── MIT Licence.rtf ├── README ├── bin └── as3-qrcode-encoder.swc ├── demo-app ├── libs │ └── as3-qrcode-encoder.swc └── src │ ├── Main.mxml │ └── org │ └── jbpin │ └── qrcodegen │ └── component │ ├── EmailGenerator.mxml │ ├── LinkGenerator.mxml │ ├── QRGenerator.as │ ├── SMSGenerator.mxml │ ├── TextGenerator.mxml │ └── VCardGenerator.mxml └── src └── org └── qrcode ├── QRCode.as ├── QRImage.as ├── QRMask.as ├── QRSplit.as ├── QRbitstream.as ├── encode └── QRRawCode.as ├── enum ├── QRCodeEncodeType.as ├── QRCodeErrorLevel.as └── QRCodeOutputType.as ├── input ├── QRInput.as └── QRInputItem.as ├── rs ├── QRRsBlock.as └── QRRsItem.as ├── specs ├── QRSpecCapacity.as └── QRSpecs.as └── utils ├── FrameFiller.as ├── QRCodeTool.as └── QRUtil.as /MIT Licence.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 2 | {\fonttbl\f0\froman\fcharset0 Times-Roman;\f1\fnil\fcharset0 LucidaGrande;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww9000\viewh8400\viewkind0 5 | \deftab720 6 | \pard\pardeftab720\sa240\ql\qnatural 7 | 8 | \f0\fs24 \cf0 Copyright (c) 2010 Jean-Baptiste PIN\ 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | \f1 \uc0\u8232 11 | \f0 of this software and associated documentation files (the "Software"), to deal 12 | \f1 \uc0\u8232 13 | \f0 in the Software without restriction, including without limitation the rights 14 | \f1 \uc0\u8232 15 | \f0 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | \f1 \uc0\u8232 17 | \f0 copies of the Software, and to permit persons to whom the Software is 18 | \f1 \uc0\u8232 19 | \f0 furnished to do so, subject to the following conditions:\ 20 | The above copyright notice and this permission notice shall be included in 21 | \f1 \uc0\u8232 22 | \f0 all copies or substantial portions of the Software.\ 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | \f1 \uc0\u8232 25 | \f0 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | \f1 \uc0\u8232 27 | \f0 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | \f1 \uc0\u8232 29 | \f0 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | \f1 \uc0\u8232 31 | \f0 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | \f1 \uc0\u8232 33 | \f0 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 34 | \f1 \uc0\u8232 35 | \f0 THE SOFTWARE.\ 36 | } -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | AS3 QR Code encoder is an adaptation of qrencode open source C library to as3 language. This library allow you to generate a qr code from your application (Flex, Flash, AIR) on offline mode. 2 | 3 | How to use it ? 4 | 5 | var qr:QRCode = new QRCode(); 6 | qr.encode("String to encode"); 7 | var bitMap:Bitmap = new Bitmap(qr.bitmapData); 8 | 9 | That is just the first version of the library, I will try to optimize it and fixing some problem soon as possible.. 10 | The choice to just provide a bitmap data object has been made to allow you to display the qrcode or to encoding it and save it to a png or jpeg file. 11 | 12 | A flash demo: 13 | 14 | import flash.display.Sprite; import org.qrcode.QRCode; import flash.display.Bitmap; var sp:Sprite = new Sprite(); var qr:QRCode = new QRCode(); qr.encode("TEST"); var img:Bitmap = new Bitmap(qr.bitmapData); sp.addChild(img); addChild(sp); 15 | 16 | The project is under MIT License. -------------------------------------------------------------------------------- /bin/as3-qrcode-encoder.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbpin/as3-qrcode-encoder/9610219b38d9c09ae05ffba9109458ca239f5c51/bin/as3-qrcode-encoder.swc -------------------------------------------------------------------------------- /demo-app/libs/as3-qrcode-encoder.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbpin/as3-qrcode-encoder/9610219b38d9c09ae05ffba9109458ca239f5c51/demo-app/libs/as3-qrcode-encoder.swc -------------------------------------------------------------------------------- /demo-app/src/Main.mxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /demo-app/src/org/jbpin/qrcodegen/component/EmailGenerator.mxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo-app/src/org/jbpin/qrcodegen/component/LinkGenerator.mxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo-app/src/org/jbpin/qrcodegen/component/QRGenerator.as: -------------------------------------------------------------------------------- 1 | package org.jbpin.qrcodegen.component 2 | { 3 | import flash.events.Event; 4 | 5 | import mx.containers.Canvas; 6 | 7 | [Event(name="generate")] 8 | public class QRGenerator extends Canvas 9 | { 10 | 11 | public static const GENERATE_EVENT:String = "generate"; 12 | 13 | public var stToEncode:String; 14 | 15 | public function QRGenerator() 16 | { 17 | super(); 18 | } 19 | 20 | public function generate():void{ 21 | dispatchEvent(new Event(GENERATE_EVENT)); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /demo-app/src/org/jbpin/qrcodegen/component/SMSGenerator.mxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /demo-app/src/org/jbpin/qrcodegen/component/TextGenerator.mxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /demo-app/src/org/jbpin/qrcodegen/component/VCardGenerator.mxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/org/qrcode/QRCode.as: -------------------------------------------------------------------------------- 1 | package org.qrcode 2 | { 3 | import flash.display.BitmapData; 4 | import flash.geom.Point; 5 | 6 | 7 | import org.qrcode.encode.QRRawCode; 8 | import org.qrcode.enum.QRCodeEncodeType; 9 | import org.qrcode.enum.QRCodeErrorLevel; 10 | import org.qrcode.input.QRInput; 11 | import org.qrcode.specs.QRSpecs; 12 | import org.qrcode.utils.FrameFiller; 13 | import org.qrcode.utils.QRCodeTool; 14 | 15 | public class QRCode 16 | { 17 | private var data:Array = []; 18 | 19 | private var level:int; 20 | private var type:int; 21 | private var version:int = 1; 22 | private var width:int; 23 | 24 | private var text:String; 25 | 26 | [Bindable] 27 | public var bitmapData:BitmapData; 28 | 29 | public function QRCode(errorLevel:int=QRCodeErrorLevel.QRCODE_ERROR_LEVEL_LOW,encodeType:int = QRCodeEncodeType.QRCODE_ENCODE_BYTES) { 30 | this.level = errorLevel; 31 | this.type = encodeType; 32 | 33 | } 34 | 35 | public function encode(content:String):void{ 36 | this.version = 1; 37 | this.text = content; 38 | encodeString(true); 39 | encodeBitmap(); 40 | } 41 | 42 | 43 | private function encodeBitmap():void{ 44 | this.bitmapData = QRImage.image(this.data); 45 | } 46 | 47 | private function encodeString(casesensitive:Boolean = true):void{ 48 | if(type != QRCodeEncodeType.QRCODE_ENCODE_BYTES && type != QRCodeEncodeType.QRCODE_ENCODE_KANJI) { 49 | throw new Error('bad hint'); 50 | } 51 | 52 | var input:QRInput = new QRInput(version, level); 53 | if(input == null) 54 | return; 55 | 56 | input = QRSplit.splitStringToQRinput(text, input, type, casesensitive); 57 | 58 | var ar:Array = this.encodeInput(input); 59 | this.data = QRCodeTool.binarize(ar); 60 | } 61 | 62 | private function encodeMask(input:QRInput,mask:int):QRCode 63 | { 64 | if(input.version < 0 || input.version > QRSpecs.QRSPEC_VERSION_MAX) { 65 | throw new Error('wrong version'); 66 | } 67 | if(input.errorCorrectionLevel > QRCodeErrorLevel.QRCODE_ERROR_LEVEL_HIGH) { 68 | throw new Error('wrong level'); 69 | } 70 | 71 | var raw:QRRawCode = new QRRawCode(input); 72 | 73 | version = raw.version; 74 | width = QRSpecs.getWidth(version); 75 | var frame:Array = QRSpecs.newFrame(version); 76 | 77 | //this.data = frame; 78 | //return this; 79 | 80 | 81 | var filler:FrameFiller = new FrameFiller(width, frame); 82 | if(filler == null) { 83 | return null; 84 | } 85 | 86 | 87 | // inteleaved data and ecc codes 88 | for(var i:int=0; i> 1; 95 | } 96 | } 97 | 98 | 99 | // remainder bits 100 | j = QRSpecs.getRemainder(version); 101 | for(i=0; i> 1; 44 | } 45 | 46 | for(i=0; i<7; i++) { 47 | if(format & 1) { 48 | blacks += 2; 49 | v = 0x85; 50 | } else { 51 | v = 0x84; 52 | } 53 | 54 | mask[width - 7 + i][8] = v; 55 | if(i == 0) { 56 | mask[8][7] = v; 57 | } else { 58 | mask[8][6 - i] = v; 59 | } 60 | 61 | format = format >> 1; 62 | } 63 | 64 | return blacks; 65 | } 66 | 67 | public function mask0(x:Number, y:Number):int { return int( ( (x + y) & 1) == 0 ); } 68 | public function mask1(x:Number, y:Number):int { return int((y&1) == 0); } 69 | public function mask2(x:Number, y:Number):int { return int((x % 3) == 0); } 70 | public function mask3(x:Number, y:Number):int { return int((x+y)%3 == 0); } 71 | public function mask4(x:Number, y:Number):int { return int( ( (int(y*0.5) + int(x/3)) &1) == 0 )} 72 | public function mask5(x:Number, y:Number):int { return int( ( ( (x*y) % 2 ) + ((x*y) % 3 ) ) == 0 )} 73 | public function mask6(x:Number, y:Number):int { return int( ( ( ( (x*y) &1 ) + ((x*y) % 3 ) ) &1 ) == 0 ); } 74 | public function mask7(x:Number, y:Number):int { return int( ( ( ( (x+y) &1 ) + ((x*y) % 3 ) ) &1 ) == 0 ) } 75 | 76 | private function generateMaskNo(maskNo:int, width:int):Array 77 | { 78 | var bitMask:Array = QRUtil.array_fill(0, width, QRUtil.array_fill(0, width, 0x00)); 79 | 80 | for(var y:int=0; y= 5) { 157 | demerit += N1 + (runLength[i] - 5); 158 | } 159 | if((i & 1)) { 160 | if(i >= 3 && i < (length-2) && runLength[i] % 3 == 0) { 161 | var fact:int = runLength[i] / 3; 162 | if((runLength[i-2] == fact) && 163 | (runLength[i-1] == fact) && 164 | (runLength[i+1] == fact) && 165 | (runLength[i+2] == fact)) { 166 | if((runLength[i-3] < 0) || (runLength[i-3] >= (4 * fact))) { 167 | demerit += N3; 168 | } else if(((i+3) >= length) || (runLength[i+3] >= (4 * fact))) { 169 | demerit += N3; 170 | } 171 | } 172 | } 173 | } 174 | } 175 | return demerit; 176 | } 177 | 178 | public function evaluateSymbol(width:int,frame:Array):int 179 | { 180 | var head:int = 0; 181 | var demerit:int = 0; 182 | runLength = QRUtil.array_fill(0, QRSpecs.QRSPEC_VERSION_MAX + 1, 0x00); 183 | 184 | for(var y:int=0; y0) 192 | frameYM = frame[y-1]; 193 | 194 | for(var x:int=0; x 0) && (y > 0)) { 196 | var b22:Number = frameY[x] & frameY[x-1] & frameYM[x] & frameYM[x-1]; 197 | var w22:Number = frameY[x] | frameY[x-1] | frameYM[x] | frameYM[x-1]; 198 | 199 | if((b22 | (w22 ^ 1))&1) { 200 | demerit += N2; 201 | } 202 | } 203 | if((x == 0) && (frameY[x] & 1)) { 204 | runLength[0] = -1; 205 | head = 1; 206 | runLength[head] = 1; 207 | } else if(x > 0) { 208 | if((frameY[x] ^ frameY[x-1]) & 1) { 209 | head++; 210 | runLength[head] = 1; 211 | } else { 212 | runLength[head]++; 213 | } 214 | } 215 | } 216 | 217 | demerit += this.calcN1N3(head+1,runLength); 218 | } 219 | 220 | for(x=0; x 0) { 230 | if((frame[y][x] ^ frame[y-1][x]) & 1) { 231 | head++; 232 | runLength[head] = 1; 233 | } else { 234 | runLength[head]++; 235 | } 236 | } 237 | } 238 | 239 | demerit += this.calcN1N3(head+1,runLength); 240 | } 241 | 242 | return demerit; 243 | } 244 | 245 | public function mask(width:int, level:int):Array 246 | { 247 | var minDemerit:int = int.MAX_VALUE; 248 | var bestMaskNum:int = 0; 249 | var bestMask:Array = []; 250 | 251 | var checked_masks:Array = [0,2,3,4,5,6,7]; 252 | 253 | 254 | bestMask = QRUtil.copyArray(frames); 255 | 256 | for each(var i:int in checked_masks) { 257 | var demerit:int = 0; 258 | var blacks:int = 0; 259 | var ar:Array = this.makeMaskNo(i, width); 260 | var mask:Array = ar[0]; 261 | blacks = ar[1]; 262 | blacks += this.writeFormatInformation(mask, width, i, level); 263 | blacks = 100 * blacks / (width * width); 264 | demerit = int(Math.abs(blacks - 50) / 5) * N4; 265 | demerit += this.evaluateSymbol(width, mask); 266 | 267 | if(demerit < minDemerit) { 268 | minDemerit = demerit; 269 | bestMask = mask; 270 | bestMaskNum = i; 271 | } 272 | } 273 | return bestMask; 274 | } 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/org/qrcode/QRSplit.as: -------------------------------------------------------------------------------- 1 | package org.qrcode 2 | { 3 | import flash.geom.Point; 4 | 5 | import org.qrcode.enum.QRCodeEncodeType; 6 | import org.qrcode.input.QRInput; 7 | import org.qrcode.specs.QRSpecs; 8 | 9 | public class QRSplit 10 | { 11 | public var dataStr:Array = []; 12 | public var input:QRInput; 13 | public var modeHint:int; 14 | 15 | public function QRSplit(dataStr:String, input:QRInput, modeHint:int){ 16 | this.dataStr = dataStr.split(""); 17 | this.input = input; 18 | this.modeHint = modeHint; 19 | } 20 | 21 | public static function isdigitat(str:Array, pos:int):Boolean 22 | { 23 | if (pos >= str.length) 24 | return false; 25 | 26 | return ((str[pos].toString().charCodeAt() >= '0'.charCodeAt())&&(str[pos].toString().charCodeAt() <= '9'.charCodeAt())); 27 | } 28 | 29 | public static function isalnumat(str:Array, pos:int):Boolean 30 | { 31 | if (pos >= str.length) 32 | return false; 33 | 34 | return (QRInput.lookAnTable(str[pos].toString().charCodeAt()) >= 0); 35 | } 36 | 37 | public function identifyMode(pos:int):int 38 | { 39 | if (pos >= this.dataStr.length) 40 | return -1; 41 | 42 | var c:String = this.dataStr[pos]; 43 | 44 | if(isdigitat(this.dataStr, pos)) { 45 | return QRCodeEncodeType.QRCODE_ENCODE_NUMERIC; 46 | } else if(isalnumat(this.dataStr, pos)) { 47 | return QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC; 48 | } else if(this.modeHint == QRCodeEncodeType.QRCODE_ENCODE_KANJI) { 49 | 50 | if (pos+1 < this.dataStr.length) 51 | { 52 | var d:String = this.dataStr[pos+1]; 53 | var word:int = (c.charCodeAt() << 8) | d.charCodeAt(); 54 | if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) { 55 | return QRCodeEncodeType.QRCODE_ENCODE_KANJI; 56 | } 57 | } 58 | } 59 | 60 | return QRCodeEncodeType.QRCODE_ENCODE_BYTES; 61 | } 62 | 63 | public function eatNum():int 64 | { 65 | var ln:int = QRSpecs.lengthIndicator(QRCodeEncodeType.QRCODE_ENCODE_NUMERIC, this.input.version); 66 | 67 | var p:int = 0; 68 | while(isdigitat(this.dataStr, p)) { 69 | p++; 70 | } 71 | 72 | var run:int = p; 73 | var mode:int = this.identifyMode(p); 74 | 75 | if(mode == QRCodeEncodeType.QRCODE_ENCODE_BYTES) { 76 | var dif:int = QRInput.estimateBitsModeNum(run) + 4 + ln 77 | + QRInput.estimateBitsMode8(1) // + 4 + l8 78 | - QRInput.estimateBitsMode8(run + 1); // - 4 - l8 79 | if(dif > 0) { 80 | return this.eat8(); 81 | } 82 | } 83 | if(mode == QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC) { 84 | dif = QRInput.estimateBitsModeNum(run) + 4 + ln 85 | + QRInput.estimateBitsModeAn(1) // + 4 + la 86 | - QRInput.estimateBitsModeAn(run + 1);// - 4 - la 87 | if(dif > 0) { 88 | return this.eatAn(); 89 | } 90 | } 91 | 92 | var ret:int = this.input.append(QRCodeEncodeType.QRCODE_ENCODE_NUMERIC, run, this.dataStr); 93 | if(ret < 0) 94 | return -1; 95 | 96 | return run; 97 | } 98 | 99 | public function eatAn():int 100 | { 101 | var la:int = QRSpecs.lengthIndicator(QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC, this.input.version); 102 | var ln:int = QRSpecs.lengthIndicator(QRCodeEncodeType.QRCODE_ENCODE_NUMERIC, this.input.version); 103 | 104 | var p:int = 0; 105 | 106 | while(isalnumat(this.dataStr, p)) { 107 | if(isdigitat(this.dataStr, p)) { 108 | var q:int = p; 109 | while(isdigitat(this.dataStr, q)) { 110 | q++; 111 | } 112 | 113 | var dif:int = QRInput.estimateBitsModeAn(p) // + 4 + la 114 | + QRInput.estimateBitsModeNum(q - p) + 4 + ln 115 | - QRInput.estimateBitsModeAn(q); // - 4 - la 116 | 117 | if(dif < 0) { 118 | break; 119 | } else { 120 | p = q; 121 | } 122 | } else { 123 | p++; 124 | } 125 | } 126 | 127 | var run:int = p; 128 | 129 | if(!isalnumat(this.dataStr, p)) { 130 | dif = QRInput.estimateBitsModeAn(run) + 4 + la 131 | + QRInput.estimateBitsMode8(1) // + 4 + l8 132 | - QRInput.estimateBitsMode8(run + 1); // - 4 - l8 133 | if(dif > 0) { 134 | return this.eat8(); 135 | } 136 | } 137 | 138 | var ret:int = this.input.append(QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC, run, this.dataStr); 139 | if(ret < 0) 140 | return -1; 141 | 142 | return run; 143 | } 144 | 145 | public function eatKanji():int 146 | { 147 | var p:int = 0; 148 | 149 | while(this.identifyMode(p) == QRCodeEncodeType.QRCODE_ENCODE_KANJI) { 150 | p += 2; 151 | } 152 | 153 | var run:int = p; 154 | var ret:int = this.input.append(QRCodeEncodeType.QRCODE_ENCODE_KANJI, p, this.dataStr); 155 | if(ret < 0) 156 | return -1; 157 | 158 | return run; 159 | } 160 | 161 | public function eat8():int 162 | { 163 | var la:int = QRSpecs.lengthIndicator(QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC, this.input.version); 164 | var ln:int = QRSpecs.lengthIndicator(QRCodeEncodeType.QRCODE_ENCODE_NUMERIC, this.input.version); 165 | 166 | var p:int = 1; 167 | var dataStrLen:int = this.dataStr.length; 168 | 169 | while(p < dataStrLen) { 170 | 171 | var mode:int = this.identifyMode(p); 172 | if(mode == QRCodeEncodeType.QRCODE_ENCODE_KANJI) { 173 | break; 174 | } 175 | if(mode == QRCodeEncodeType.QRCODE_ENCODE_NUMERIC) { 176 | var q:int = p; 177 | while(isdigitat(this.dataStr, q)) { 178 | q++; 179 | } 180 | var dif:int = QRInput.estimateBitsMode8(p) // + 4 + l8 181 | + QRInput.estimateBitsModeNum(q - p) + 4 + ln 182 | - QRInput.estimateBitsMode8(q); // - 4 - l8 183 | if(dif < 0) { 184 | break; 185 | } else { 186 | p = q; 187 | } 188 | } else if(mode == QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC) { 189 | q = p; 190 | while(isalnumat(this.dataStr, q)) { 191 | q++; 192 | } 193 | dif = QRInput.estimateBitsMode8(p) // + 4 + l8 194 | + QRInput.estimateBitsModeAn(q - p) + 4 + la 195 | - QRInput.estimateBitsMode8(q); // - 4 - l8 196 | if(dif < 0) { 197 | break; 198 | } else { 199 | p = q; 200 | } 201 | } else { 202 | p++; 203 | } 204 | } 205 | 206 | var run:int = p; 207 | var ret:int = this.input.append(QRCodeEncodeType.QRCODE_ENCODE_BYTES, run, this.dataStr); 208 | 209 | if(ret < 0) 210 | return -1; 211 | 212 | return run; 213 | } 214 | 215 | public function splitString():int 216 | { 217 | while (this.dataStr.length > 0) 218 | { 219 | var mode:int = this.identifyMode(0); 220 | var length:int; 221 | switch (mode) { 222 | case QRCodeEncodeType.QRCODE_ENCODE_NUMERIC: length = this.eatNum(); break; 223 | case QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC: length = this.eatAn(); break; 224 | case QRCodeEncodeType.QRCODE_ENCODE_KANJI: 225 | if (modeHint == QRCodeEncodeType.QRCODE_ENCODE_KANJI) 226 | length = this.eatKanji(); 227 | else length = this.eat8(); 228 | break; 229 | default: length = this.eat8(); break; 230 | 231 | } 232 | 233 | if(length == 0) return 0; 234 | if(length < 0) return -1; 235 | 236 | this.dataStr = this.dataStr.slice(length); 237 | } 238 | return length; 239 | } 240 | 241 | public function toUpper():Array 242 | { 243 | var stringLen:int = this.dataStr.length; 244 | var p:int = 0; 245 | 246 | while (p= 'a'.charCodeAt() && this.dataStr[p].charCodeAt() <= 'z'.charCodeAt()) { 252 | this.dataStr[p] = String.fromCharCode(this.dataStr[p].charCodeAt() - 32); 253 | } 254 | p++; 255 | } 256 | } 257 | 258 | return this.dataStr; 259 | } 260 | 261 | public static function splitStringToQRinput(string:String, input:QRInput, modeHint:int, casesensitive:Boolean = true):QRInput 262 | { 263 | if(string == null || string == '\0' || string == '') { 264 | throw new Error('empty string!!!'); 265 | } 266 | 267 | var split:QRSplit = new QRSplit(string, input, modeHint); 268 | 269 | if(!casesensitive) 270 | split.toUpper(); 271 | 272 | split.splitString(); 273 | return split.input; 274 | } 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/org/qrcode/QRbitstream.as: -------------------------------------------------------------------------------- 1 | package org.qrcode 2 | { 3 | import org.qrcode.utils.QRUtil; 4 | 5 | public class QRbitstream 6 | { 7 | 8 | public var data:Array = []; 9 | 10 | public function QRbitstream() 11 | { 12 | } 13 | 14 | public function get size():int 15 | { 16 | return this.data.length; 17 | } 18 | 19 | public function allocate(setLength:int):void 20 | { 21 | this.data = QRUtil.array_fill(0, setLength, 0x00); 22 | } 23 | 24 | public static function newFromNum(bits:Number, num:Number):QRbitstream 25 | { 26 | var bstream:QRbitstream = new QRbitstream(); 27 | bstream.allocate(bits); 28 | 29 | var mask:int = 1 << (bits - 1); 30 | for(var i:int=0; i> 1; 37 | } 38 | 39 | return bstream; 40 | } 41 | 42 | public static function newFromBytes(size:int, data:Array):QRbitstream 43 | { 44 | var bstream:QRbitstream = new QRbitstream(); 45 | bstream.allocate(size * 8); 46 | var p:int =0; 47 | 48 | for(var i:int=0; i> 1; 58 | } 59 | } 60 | 61 | return bstream; 62 | } 63 | 64 | public function append(arg:QRbitstream):void 65 | { 66 | if (arg == null) { 67 | return; 68 | } 69 | 70 | if(arg.size == 0) { 71 | return; 72 | } 73 | 74 | if(this.size == 0) { 75 | this.data = arg.data; 76 | return; 77 | } 78 | 79 | QRUtil.array_merge(this.data,arg.data); 80 | } 81 | 82 | public function appendNum(bits:Number, num:Number):void 83 | { 84 | if (bits == 0) 85 | return; 86 | 87 | var b:QRbitstream = QRbitstream.newFromNum(bits, num); 88 | 89 | if(b == null) 90 | return; 91 | 92 | this.append(b); 93 | } 94 | 95 | public function appendBytes(size:int, data:Array):void 96 | { 97 | if (size == 0) 98 | return; 99 | 100 | var b:QRbitstream = QRbitstream.newFromBytes(size, data); 101 | 102 | if(b == null) 103 | return; 104 | 105 | this.append(b); 106 | } 107 | 108 | public function toByte():Array 109 | { 110 | 111 | var size:int = this.size; 112 | 113 | if(size == 0) { 114 | return []; 115 | } 116 | 117 | var databyte:Array = QRUtil.array_fill(0, (size + 7) / 8, 0x00); 118 | var bytes:int = size / 8; 119 | 120 | var p:int = 0; 121 | 122 | for(var i:int=0; i= this.rsblocks[0].dataLength) { 103 | row += this.b1; 104 | } 105 | ret = this.rsblocks[row].data[col]; 106 | } else if(this.count < this.dataLength + this.eccLength) { 107 | row = (this.count - this.dataLength) % this.blocks; 108 | col = (this.count - this.dataLength) / this.blocks; 109 | ret = this.rsblocks[row].ecc[col]; 110 | } else { 111 | return 0; 112 | } 113 | this.count++; 114 | 115 | return ret; 116 | } 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/org/qrcode/enum/QRCodeEncodeType.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.enum 2 | { 3 | public class QRCodeEncodeType 4 | { 5 | public static const QRCODE_ENCODE_NUL:int=-1; 6 | public static const QRCODE_ENCODE_NUMERIC:int=0; 7 | public static const QRCODE_ENCODE_ALPHA_NUMERIC:int=1; 8 | public static const QRCODE_ENCODE_BYTES:int=2; 9 | public static const QRCODE_ENCODE_KANJI:int=3; 10 | public static const QRCODE_ENCODE_STRUCTURE:int=4; 11 | } 12 | } -------------------------------------------------------------------------------- /src/org/qrcode/enum/QRCodeErrorLevel.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.enum 2 | { 3 | public class QRCodeErrorLevel 4 | { 5 | public static const QRCODE_ERROR_LEVEL_LOW:int=0; 6 | public static const QRCODE_ERROR_LEVEL_MEDIUM:int=1; 7 | public static const QRCODE_ERROR_LEVEL_Q:int=2; 8 | public static const QRCODE_ERROR_LEVEL_HIGH:int=3; 9 | } 10 | } -------------------------------------------------------------------------------- /src/org/qrcode/enum/QRCodeOutputType.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.enum 2 | { 3 | public class QRCodeOutputType 4 | { 5 | public static const QRCODE_OUTPUT_TEXT:String="outputText"; 6 | public static const QRCODE_OUTPUT_BITMAP:String="outputBitmap"; 7 | public static const QRCODE_OUTPUT_PNG:String="outputPNG"; 8 | } 9 | } -------------------------------------------------------------------------------- /src/org/qrcode/input/QRInput.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.input 2 | { 3 | 4 | import org.qrcode.QRbitstream; 5 | import org.qrcode.enum.QRCodeEncodeType; 6 | import org.qrcode.enum.QRCodeErrorLevel; 7 | import org.qrcode.specs.QRSpecs; 8 | 9 | public class QRInput 10 | { 11 | public var items:Array; 12 | 13 | private var _version:int; 14 | private var _level:int; 15 | 16 | public function QRInput(qrversion:int = 0, qrlevel:int = QRCodeErrorLevel.QRCODE_ERROR_LEVEL_LOW) 17 | { 18 | if (qrversion < 0 || qrversion > QRSpecs.QRSPEC_VERSION_MAX || qrlevel > QRCodeErrorLevel.QRCODE_ERROR_LEVEL_HIGH) { 19 | throw new Error('Invalid version no'); 20 | } 21 | this.items = []; 22 | this._version = qrversion; 23 | this._level = qrlevel; 24 | } 25 | 26 | public function get version():int 27 | { 28 | return this._version; 29 | } 30 | 31 | public function set version(value:int):void 32 | { 33 | if(value < 0 || value > QRSpecs.QRSPEC_VERSION_MAX) { 34 | throw new Error('Invalid version no'); 35 | return; 36 | } 37 | this._version = value; 38 | } 39 | 40 | public function get errorCorrectionLevel():int{ 41 | return this._level; 42 | } 43 | 44 | public function set errorCorrectionLevel(value:int):void 45 | { 46 | if(value > QRCodeErrorLevel.QRCODE_ERROR_LEVEL_HIGH) { 47 | throw new Error('Invalid ECLEVEL'); 48 | } 49 | 50 | this._level = value; 51 | 52 | } 53 | 54 | public function appendEntry(entry:QRInputItem):void 55 | { 56 | this.items.addItem(entry); 57 | } 58 | 59 | public function append(mode:int, size:int, data:Array):int 60 | { 61 | try { 62 | var entry:QRInputItem = new QRInputItem(mode, size, data); 63 | this.items.push(entry); 64 | return 0; 65 | } catch (e:Error) { 66 | return -1; 67 | } 68 | return 0; 69 | } 70 | 71 | public function insertStructuredAppendHeader(size:int, index:int, parity:int):int 72 | { 73 | if( size > QRInputItem.MAX_STRUCTURED_SYMBOLS ) { 74 | throw new Error('insertStructuredAppendHeader wrong size'); 75 | } 76 | 77 | if( index <= 0 || index > QRInputItem.MAX_STRUCTURED_SYMBOLS ) { 78 | throw new Error('insertStructuredAppendHeader wrong index'); 79 | } 80 | 81 | var buf:Array = [size, index, parity]; 82 | 83 | try { 84 | var entry:QRInputItem = new QRInputItem(QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE, 3, buf); 85 | this.items.unshift(entry); 86 | return 0; 87 | } catch (e:Error) { 88 | return -1; 89 | } 90 | return 0; 91 | } 92 | 93 | public function calcParity():Number 94 | { 95 | var parity:Number = 0; 96 | 97 | for each(var item:QRInputItem in items) { 98 | if(item.mode != QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE) { 99 | for(var i:int=item.size-1; i>=0; i--) { 100 | parity ^= item.data[i]; 101 | } 102 | } 103 | } 104 | 105 | return parity; 106 | } 107 | 108 | public static function checkModeNum(size:int, data:Array):Boolean 109 | { 110 | for(var i:int=0; i '9'.charCodeAt())){ 112 | return false; 113 | } 114 | } 115 | 116 | return true; 117 | } 118 | 119 | public static function estimateBitsModeNum(size:int):int 120 | { 121 | var w:int = size / 3; 122 | var bits:int = w * 10; 123 | 124 | switch(size - w * 3) { 125 | case 1: 126 | bits += 4; 127 | break; 128 | case 2: 129 | bits += 7; 130 | break; 131 | default: 132 | break; 133 | } 134 | 135 | return bits; 136 | } 137 | 138 | public static const anTable:Array = [ 139 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 140 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 141 | 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, 142 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, 143 | -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 144 | 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, 145 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 146 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 147 | ]; 148 | 149 | public static function lookAnTable(c:int):int 150 | { 151 | return ((c > 127)?-1:anTable[c]); 152 | } 153 | 154 | public static function checkModeAn(size:int, data:Array):Boolean 155 | { 156 | for(var i:int=0; i 0x9ffc && val < 0xe040) 195 | || val > 0xebbf) { 196 | return false; 197 | } 198 | } 199 | 200 | return true; 201 | } 202 | 203 | /*********************************************************************** 204 | * Validation 205 | **********************************************************************/ 206 | 207 | public static function check(mode:int, size:int, data:Array):Boolean 208 | { 209 | if(size <= 0) 210 | return false; 211 | 212 | switch(mode) { 213 | case QRCodeEncodeType.QRCODE_ENCODE_NUMERIC: 214 | return checkModeNum(size, data); 215 | break; 216 | case QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC: 217 | return checkModeAn(size, data); 218 | break; 219 | case QRCodeEncodeType.QRCODE_ENCODE_KANJI: 220 | return checkModeKanji(size, data); 221 | break; 222 | case QRCodeEncodeType.QRCODE_ENCODE_BYTES: 223 | return true; 224 | break; 225 | case QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE: 226 | return true; 227 | break; 228 | default: 229 | break; 230 | } 231 | 232 | return false; 233 | } 234 | 235 | public function estimateBitStreamSize(version:int):int 236 | { 237 | var bits:int = 0; 238 | 239 | for each(var item:QRInputItem in this.items) { 240 | bits += item.estimateBitStreamSizeOfEntry(version); 241 | } 242 | 243 | return bits; 244 | } 245 | 246 | public function estimateVersion():int 247 | { 248 | var version:int = 0; 249 | var prev:int = 0; 250 | do { 251 | prev = version; 252 | var bits:int = this.estimateBitStreamSize(prev); 253 | version = QRSpecs.getMinimumVersion(((bits + 7) / 8), _level); 254 | if (version < 0) { 255 | return -1; 256 | } 257 | } while (version > prev); 258 | 259 | return version; 260 | } 261 | 262 | public static function lengthOfCode(mode:int, version:int, bits:int):int 263 | { 264 | var payload:int = bits - 4 - QRSpecs.lengthIndicator(mode, version); 265 | var chunks:int; 266 | var remain:Number; 267 | var size:int 268 | switch(mode) { 269 | case QRCodeEncodeType.QRCODE_ENCODE_NUMERIC: 270 | chunks = payload / 10; 271 | remain = payload - chunks * 10; 272 | size = chunks * 3; 273 | if(remain >= 7) { 274 | size += 2; 275 | } else if(remain >= 4) { 276 | size += 1; 277 | } 278 | break; 279 | case QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC: 280 | chunks = payload / 11; 281 | remain = payload - chunks * 11; 282 | size = chunks * 2; 283 | if(remain >= 6) 284 | size++; 285 | break; 286 | case QRCodeEncodeType.QRCODE_ENCODE_BYTES: 287 | size = payload / 8; 288 | break; 289 | case QRCodeEncodeType.QRCODE_ENCODE_KANJI: 290 | size = (payload / 13) * 2; 291 | break; 292 | case QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE: 293 | size = payload / 8; 294 | break; 295 | default: 296 | size = 0; 297 | break; 298 | } 299 | 300 | var maxsize:int = QRSpecs.maximumWords(mode, version); 301 | if(size < 0) size = 0; 302 | if(size > maxsize) size = maxsize; 303 | 304 | return size; 305 | } 306 | 307 | public function createBitStream():int 308 | { 309 | var total:int = 0; 310 | 311 | for each(var item:QRInputItem in this.items) { 312 | var bits:int = item.encodeBitStream(this.version); 313 | 314 | if(bits < 0) 315 | return -1; 316 | 317 | total += bits; 318 | } 319 | 320 | return total; 321 | } 322 | 323 | public function convertData():int 324 | { 325 | var ver:int = this.estimateVersion(); 326 | if(ver > this.version) { 327 | this.version = ver; 328 | } 329 | 330 | for(;;) { 331 | var bits:int = this.createBitStream(); 332 | 333 | if(bits < 0) 334 | return -1; 335 | 336 | ver = QRSpecs.getMinimumVersion((bits + 7) / 8, _level); 337 | if(ver < 0) { 338 | throw new Error('WRONG VERSION'); 339 | return -1; 340 | } else if(ver > this.version) { 341 | this.version = ver; 342 | } else { 343 | break; 344 | } 345 | } 346 | 347 | return 0; 348 | } 349 | 350 | public function appendPaddingBit(bstream:QRbitstream):QRbitstream 351 | { 352 | var bits:int = bstream.size; 353 | var maxwords:int = QRSpecs.getDataLength(_version, _level); 354 | var maxbits:int = maxwords * 8; 355 | 356 | if (maxbits == bits) { 357 | return bstream; 358 | } 359 | 360 | if (maxbits - bits < 5) { 361 | bstream.appendNum(maxbits - bits, 0); 362 | return bstream; 363 | } 364 | 365 | bits += 4; 366 | var words:int = (bits + 7) / 8; 367 | 368 | var padding:QRbitstream = new QRbitstream(); 369 | padding.appendNum(words * 8 - bits + 4, 0); 370 | 371 | var padlen:int = maxwords - words; 372 | 373 | if(padlen > 0) { 374 | 375 | var padbuf:Array = []; 376 | for(var i:int=0; i> 8) * 0xc0; 143 | val = (val & 0xff) + h; 144 | 145 | bs.appendNum(13, val); 146 | } 147 | 148 | this.bstream = bs; 149 | return 0; 150 | 151 | } catch (e:Error) { 152 | return -1; 153 | } 154 | return 0; 155 | } 156 | 157 | public function encodeModeStructure():int 158 | { 159 | try { 160 | var bs:QRbitstream = new QRbitstream(); 161 | 162 | bs.appendNum(4, 0x03); 163 | bs.appendNum(4, this.data[1].toString().charCodeAt() - 1); 164 | bs.appendNum(4, this.data[0].toString().charCodeAt() - 1); 165 | bs.appendNum(8, this.data[2].toString().charCodeAt()); 166 | 167 | this.bstream = bs; 168 | return 0; 169 | 170 | } catch (e:Error) { 171 | return -1; 172 | } 173 | return 0; 174 | } 175 | 176 | public function estimateBitStreamSizeOfEntry(version:int):int 177 | { 178 | var bits:int = 0; 179 | 180 | if(version == 0) 181 | version = 1; 182 | 183 | switch(this.mode) { 184 | case QRCodeEncodeType.QRCODE_ENCODE_NUMERIC: 185 | bits = QRInput.estimateBitsModeNum(this.size); 186 | break; 187 | case QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC: 188 | bits = QRInput.estimateBitsModeAn(this.size); 189 | break; 190 | case QRCodeEncodeType.QRCODE_ENCODE_BYTES: 191 | bits = QRInput.estimateBitsMode8(this.size); 192 | break; 193 | case QRCodeEncodeType.QRCODE_ENCODE_KANJI: 194 | bits = QRInput.estimateBitsModeKanji(this.size); 195 | break; 196 | case QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE: 197 | return STRUCTURE_HEADER_BITS; 198 | default: 199 | return 0; 200 | } 201 | 202 | var l:int = QRSpecs.lengthIndicator(this.mode, version); 203 | var m:int = 1 << l; 204 | var num:int = (this.size + m - 1) / m; 205 | 206 | bits += num * (4 + l); 207 | 208 | return bits; 209 | } 210 | 211 | public function encodeBitStream(version:int):int 212 | { 213 | try { 214 | 215 | this.bstream = null; 216 | var words:int = QRSpecs.maximumWords(this.mode, version); 217 | 218 | if(this.size > words) { 219 | 220 | var st1:QRInputItem = new QRInputItem(this.mode, words, this.data); 221 | var st2:QRInputItem = new QRInputItem(this.mode, this.size - words, this.data.slice(words)); 222 | 223 | st1.encodeBitStream(version); 224 | st2.encodeBitStream(version); 225 | 226 | this.bstream = new QRbitstream(); 227 | this.bstream.append(st1.bstream); 228 | this.bstream.append(st2.bstream); 229 | 230 | 231 | } else { 232 | 233 | var ret:int = 0; 234 | 235 | switch(this.mode) { 236 | case QRCodeEncodeType.QRCODE_ENCODE_NUMERIC: 237 | ret = this.encodeModeNum(version); 238 | break; 239 | case QRCodeEncodeType.QRCODE_ENCODE_ALPHA_NUMERIC: 240 | ret = this.encodeModeAn(version); 241 | break; 242 | case QRCodeEncodeType.QRCODE_ENCODE_BYTES: 243 | ret = this.encodeMode8(version); 244 | break; 245 | case QRCodeEncodeType.QRCODE_ENCODE_KANJI: 246 | ret = this.encodeModeKanji(version); 247 | case QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE: 248 | ret = this.encodeModeStructure(); 249 | default: 250 | return 0; 251 | } 252 | 253 | if(ret < 0) 254 | return -1; 255 | } 256 | 257 | return this.bstream.size; 258 | 259 | } catch (e:Error) { 260 | return -1; 261 | } 262 | return 0; 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /src/org/qrcode/rs/QRRsBlock.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.rs 2 | { 3 | 4 | public class QRRsBlock 5 | { 6 | public var dataLength:int; 7 | public var data:Array = []; 8 | public var eccLength:int; 9 | public var ecc:Array = []; 10 | 11 | public function QRRsBlock(dl:int, data:Array, el:int, ecc:Array, rs:QRRsItem) 12 | { 13 | rs.encode_rs_char(data); 14 | 15 | this.dataLength = dl; 16 | this.data = data; 17 | this.eccLength = el; 18 | this.ecc = ecc; 19 | } 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /src/org/qrcode/rs/QRRsItem.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.rs 2 | { 3 | import org.qrcode.utils.QRUtil; 4 | 5 | public class QRRsItem 6 | { 7 | 8 | private static var A0:uint; 9 | private static var NN:uint; 10 | 11 | public var mm:uint; // Bits per symbol 12 | public var nn:uint; // Symbols per block (= (1<= this.nn) { 30 | x -= this.nn; 31 | x = (x >> this.mm) + (x & this.nn); 32 | } 33 | 34 | return x; 35 | } 36 | 37 | public static function init_rs_char(symsize:int, gfpoly:int, fcr:int, prim:int, nroots:int, pad:int):QRRsItem 38 | { 39 | // Common code for intializing a Reed-Solomon control block (char or int symbols) 40 | // Copyright 2004 Phil Karn, KA9Q 41 | // May be used under the terms of the GNU Lesser General Public License (LGPL) 42 | 43 | var rs:QRRsItem = null; 44 | 45 | // Check parameter ranges 46 | if(symsize < 0 || symsize > 8) return rs; 47 | if(fcr < 0 || fcr >= (1<= (1<= (1< ((1< 0; j--) { 109 | if (rs.genpoly[j] != 0) { 110 | rs.genpoly[j] = rs.genpoly[j-1] ^ rs.alpha_to[rs.modnn(rs.index_of[rs.genpoly[j]] + root)]; 111 | } else { 112 | rs.genpoly[j] = rs.genpoly[j-1]; 113 | } 114 | } 115 | // rs.genpoly[0] can never be zero 116 | rs.genpoly[0] = rs.alpha_to[rs.modnn(rs.index_of[rs.genpoly[0]] + root)]; 117 | } 118 | 119 | // convert rs.genpoly[] to index form for quicker encoding 120 | for (i = 0; i <= nroots; i++) 121 | rs.genpoly[i] = rs.index_of[rs.genpoly[i]]; 122 | 123 | return rs; 124 | } 125 | 126 | public function encode_rs_char(data:Array):Array 127 | { 128 | var rc:QRRsItem = this; 129 | var a0:Number = rc.nn; 130 | 131 | var parity:Array = QRUtil.array_fill(0, rc.nroots, 0x00); 132 | 133 | for(var i:int=0; i< (rc.nn-rc.nroots-rc.pad); i++) { 134 | 135 | var feedback:int = rc.index_of[data[i] ^ parity[0]]; 136 | if(feedback != a0) { 137 | // feedback term is non-zero 138 | 139 | // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must 140 | // always be for the polynomials constructed by init_rs() 141 | feedback = this.modnn(rc.nn - rc.genpoly[rc.nroots] + feedback); 142 | 143 | for(var j:int=1;j= size) 62 | return i; 63 | } 64 | 65 | return -1; 66 | } 67 | 68 | ///-------------------------------/// 69 | /// Length indicator /// 70 | ///-------------------------------/// 71 | 72 | public static const lengthTableBits:Array = [ 73 | [10, 12, 14], 74 | [ 9, 11, 13], 75 | [ 8, 16, 16], 76 | [ 8, 10, 12] 77 | ]; 78 | 79 | /** 80 | * return lenght indicator 81 | * @param mode int QREncodeType value 82 | * @param version int the version of qrcode 83 | * @return int the length indicator 84 | */ 85 | public static function lengthIndicator(mode:int, version:int):int 86 | { 87 | if (mode == QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE) 88 | return 0; 89 | var l:int; 90 | if (version <= 9) { 91 | l = 0; 92 | } else if (version <= 26) { 93 | l = 1; 94 | } else { 95 | l = 2; 96 | } 97 | 98 | return lengthTableBits[mode][l]; 99 | } 100 | 101 | /** 102 | * Return the maximum data capacity for a mode and a version 103 | */ 104 | public static function maximumWords(mode:int, version:int):int 105 | { 106 | if(mode ==QRCodeEncodeType.QRCODE_ENCODE_STRUCTURE) 107 | return 3; 108 | var l:int; 109 | if(version <= 9) { 110 | l = 0; 111 | } else if(version <= 26) { 112 | l = 1; 113 | } else { 114 | l = 2; 115 | } 116 | 117 | var bits:int = lengthTableBits[mode][l]; 118 | var words:int = (1 << bits) - 1; 119 | 120 | if(mode == QRCodeEncodeType.QRCODE_ENCODE_KANJI) { 121 | words *= 2; // the number of bytes is required 122 | } 123 | 124 | return words; 125 | } 126 | 127 | 128 | 129 | public static const eccTable:Array = [ 130 | [[ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0]], 131 | [[ 1, 0], [ 1, 0], [ 1, 0], [ 1, 0]], // 1 132 | [[ 1, 0], [ 1, 0], [ 1, 0], [ 1, 0]], 133 | [[ 1, 0], [ 1, 0], [ 2, 0], [ 2, 0]], 134 | [[ 1, 0], [ 2, 0], [ 2, 0], [ 4, 0]], 135 | [[ 1, 0], [ 2, 0], [ 2, 2], [ 2, 2]], // 5 136 | [[ 2, 0], [ 4, 0], [ 4, 0], [ 4, 0]], 137 | [[ 2, 0], [ 4, 0], [ 2, 4], [ 4, 1]], 138 | [[ 2, 0], [ 2, 2], [ 4, 2], [ 4, 2]], 139 | [[ 2, 0], [ 3, 2], [ 4, 4], [ 4, 4]], 140 | [[ 2, 2], [ 4, 1], [ 6, 2], [ 6, 2]], //10 141 | [[ 4, 0], [ 1, 4], [ 4, 4], [ 3, 8]], 142 | [[ 2, 2], [ 6, 2], [ 4, 6], [ 7, 4]], 143 | [[ 4, 0], [ 8, 1], [ 8, 4], [12, 4]], 144 | [[ 3, 1], [ 4, 5], [11, 5], [11, 5]], 145 | [[ 5, 1], [ 5, 5], [ 5, 7], [11, 7]], //15 146 | [[ 5, 1], [ 7, 3], [15, 2], [ 3, 13]], 147 | [[ 1, 5], [10, 1], [ 1, 15], [ 2, 17]], 148 | [[ 5, 1], [ 9, 4], [17, 1], [ 2, 19]], 149 | [[ 3, 4], [ 3, 11], [17, 4], [ 9, 16]], 150 | [[ 3, 5], [ 3, 13], [15, 5], [15, 10]], //20 151 | [[ 4, 4], [17, 0], [17, 6], [19, 6]], 152 | [[ 2, 7], [17, 0], [ 7, 16], [34, 0]], 153 | [[ 4, 5], [ 4, 14], [11, 14], [16, 14]], 154 | [[ 6, 4], [ 6, 14], [11, 16], [30, 2]], 155 | [[ 8, 4], [ 8, 13], [ 7, 22], [22, 13]], //25 156 | [[10, 2], [19, 4], [28, 6], [33, 4]], 157 | [[ 8, 4], [22, 3], [ 8, 26], [12, 28]], 158 | [[ 3, 10], [ 3, 23], [ 4, 31], [11, 31]], 159 | [[ 7, 7], [21, 7], [ 1, 37], [19, 26]], 160 | [[ 5, 10], [19, 10], [15, 25], [23, 25]], //30 161 | [[13, 3], [ 2, 29], [42, 1], [23, 28]], 162 | [[17, 0], [10, 23], [10, 35], [19, 35]], 163 | [[17, 1], [14, 21], [29, 19], [11, 46]], 164 | [[13, 6], [14, 23], [44, 7], [59, 1]], 165 | [[12, 7], [12, 26], [39, 14], [22, 41]], //35 166 | [[ 6, 14], [ 6, 34], [46, 10], [ 2, 64]], 167 | [[17, 4], [29, 14], [49, 10], [24, 46]], 168 | [[ 4, 18], [13, 32], [48, 14], [42, 32]], 169 | [[20, 4], [40, 7], [43, 22], [10, 67]], 170 | [[19, 6], [18, 31], [34, 34], [20, 61]]//40 171 | ]; 172 | 173 | 174 | /** 175 | * Get Error correction code for a version and a level 176 | * @return the array spec 177 | */ 178 | public static function getEccSpec(version:int, level:int, spec:Array=null):Array 179 | { 180 | if (spec == null || spec.length < 5) { 181 | spec = [0,0,0,0,0]; 182 | } 183 | 184 | var b1:int = eccTable[version][level][0]; 185 | var b2:int = eccTable[version][level][1]; 186 | var data:int = getDataLength(version, level); 187 | var ecc:int = getECCLength(version, level); 188 | 189 | if(b2 == 0) { 190 | spec[0] = b1; 191 | spec[1] = (data / b1) as int; 192 | spec[2] = (ecc / b1) as int; 193 | spec[3] = 0; 194 | spec[4] = 0; 195 | } else { 196 | spec[0] = b1; 197 | spec[1] = int(data / (b1 + b2)); 198 | spec[2] = int(ecc / (b1 + b2)); 199 | spec[3] = b2; 200 | spec[4] = spec[1] + 1; 201 | } 202 | return spec; 203 | } 204 | 205 | 206 | public static const alignmentPattern:Array = [ 207 | [ 0, 0], 208 | [ 0, 0], [18, 0], [22, 0], [26, 0], [30, 0], // 1- 5 209 | [34, 0], [22, 38], [24, 42], [26, 46], [28, 50], // 6-10 210 | [30, 54], [32, 58], [34, 62], [26, 46], [26, 48], //11-15 211 | [26, 50], [30, 54], [30, 56], [30, 58], [34, 62], //16-20 212 | [28, 50], [26, 50], [30, 54], [28, 54], [32, 58], //21-25 213 | [30, 58], [34, 62], [26, 50], [30, 54], [26, 52], //26-30 214 | [30, 56], [34, 60], [30, 58], [34, 62], [30, 54], //31-35 215 | [24, 50], [28, 54], [32, 58], [26, 54], [30, 58], //35-40 216 | ]; 217 | 218 | 219 | /** -------------------------------------------------------------------- 220 | * Put an alignment marker. 221 | * @param frame Array array of ByteArray 222 | * @param width 223 | * @param ox,oy center coordinate of the pattern 224 | * @return Array the frame with alignement marker 225 | */ 226 | public static function putAlignmentMarker(frame:Array, ox:int, oy:int):Array 227 | { 228 | 229 | var finder:Vector. = new Vector.(); 230 | finder.push( 231 | 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 232 | 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, 233 | 0xa1, 0xa0, 0xa1, 0xa0, 0xa1, 234 | 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, 235 | 0xa1, 0xa1, 0xa1, 0xa1, 0xa1 236 | ); 237 | 238 | var finderpos:int = 0; 239 | 240 | for(var x:int=0; x<5; x++) { 241 | for(var y:int=0; y<5; y++) { 242 | (frame[ox+x-2] as Array)[oy+y-2] = finder[finderpos+y]; 243 | } 244 | finderpos += 5; 245 | } 246 | 247 | return frame; 248 | 249 | } 250 | 251 | /** 252 | * put Alignement pattern in the frame 253 | */ 254 | public static function putAlignmentPattern(version:int, frame:Array, width:int):Array 255 | { 256 | if(version < 2) 257 | return frame; 258 | 259 | var d:int = alignmentPattern[version][1] - alignmentPattern[version][0]; 260 | var w:int; 261 | if(d < 0) { 262 | w = 2; 263 | } else { 264 | w = int((width - alignmentPattern[version][0]) / d + 2); 265 | } 266 | 267 | var x:int; 268 | var y:int; 269 | if(w * w - 3 == 1) { 270 | x = alignmentPattern[version][0]; 271 | y = alignmentPattern[version][0]; 272 | frame = putAlignmentMarker(frame, x, y); 273 | return frame; 274 | } 275 | 276 | var cx:int = alignmentPattern[version][0]; 277 | for(x=1; x< w - 1; x++) { 278 | frame = putAlignmentMarker(frame, 6, cx); 279 | frame = putAlignmentMarker(frame, cx, 6); 280 | cx += d; 281 | } 282 | 283 | var cy:int = alignmentPattern[version][0]; 284 | for(y=0; y QRSPEC_VERSION_MAX) 308 | return 0; 309 | 310 | return versionPattern[version -7]; 311 | } 312 | 313 | 314 | public static const formatInfo:Array = [ 315 | [0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976], 316 | [0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0], 317 | [0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed], 318 | [0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b] 319 | ]; 320 | 321 | public static function getFormatInfo(mask:int, level:int):uint 322 | { 323 | if(mask < 0 || mask > 7) 324 | return 0; 325 | 326 | if(level < 0 || level > 3) 327 | return 0; 328 | 329 | return formatInfo[level][mask]; 330 | } 331 | 332 | 333 | /** -------------------------------------------------------------------- 334 | * Put a finder pattern. 335 | * @param frame 336 | * @param width 337 | * @param ox,oy upper-left coordinate of the pattern 338 | */ 339 | public static function putFinderPattern(frame:Array, ox:int, oy:int):Array 340 | { 341 | var finder:Array = [ 342 | 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 343 | 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 344 | 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 345 | 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 346 | 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 347 | 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 348 | 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 349 | ]; 350 | 351 | var finderpos:int = 0; 352 | 353 | for(var x:int=0; x<7; x++) { 354 | for(var y:int=0; y<7; y++) { 355 | (frame[ox+x] as Array)[oy+y] = finder[finderpos+y]; 356 | } 357 | finderpos += 7; 358 | } 359 | 360 | return frame; 361 | } 362 | 363 | 364 | public static function createFrame(version:int):Array 365 | { 366 | var width:int = getCapacity(version).width; 367 | var frameLine:Array = QRUtil.array_fill(0, width,0x00); 368 | var frame:Array =  QRUtil.array_fill(0, width, frameLine); 369 | 370 | 371 | // Finder pattern 372 | frame = putFinderPattern(frame ,0, 0); 373 | frame = putFinderPattern(frame, width - 7, 0); 374 | frame = putFinderPattern(frame, 0, width - 7); 375 | 376 | // Separator 377 | var yOffset:int = width - 7; 378 | 379 | for(var y:int=0; y<7; y++,yOffset++) { 380 | frame[y][7] = 0xc0; 381 | frame[y][width - 8] = 0xc0; 382 | frame[yOffset][7] = 0xc0; 383 | } 384 | 385 | var setPattern:Array = QRUtil.array_fill(0,8,0xc0); 386 | 387 | var p:int = 0; 388 | var q:int = width - 7; 389 | for(y=0; y<7; y++,q++,p++) { 390 | frame[p][7] = 0xc0; 391 | frame[p][width - 8] = 0xc0; 392 | frame[q][7] = 0xc0; 393 | } 394 | 395 | frame = QRUtil.memset(frame, 7, 0, 0xc0, 8); 396 | frame = QRUtil.memset(frame, 7, width-8, 0xc0, width - 8); 397 | frame = QRUtil.memset(frame, width-8 , 0, 0xc0, 8); 398 | 399 | // Format info 400 | yOffset = width - 8; 401 | 402 | frame = QRUtil.memset(frame, 8 ,0, 0x84, 9); 403 | frame = QRUtil.memset(frame, 8 ,width-8, 0x84, 8); 404 | 405 | for(y=0; y<8; y++,yOffset++) { 406 | frame[y][8] = 0x84; 407 | frame[yOffset][8] = 0x84; 408 | } 409 | 410 | // Timing pattern 411 | 412 | for(var i:int=1; i= 7) { 422 | var vinf:int = getVersionPattern(version);; 423 | 424 | var v:int = vinf; 425 | 426 | for(var x:int=0; x<6; x++) { 427 | for(y=0; y<3; y++) { 428 | frame[(width - 11)+y][x] = 0x88 | (v & 1); 429 | v = v >> 1; 430 | } 431 | } 432 | 433 | v = vinf; 434 | for(y=0; y<6; y++) { 435 | for(x=0; x<3; x++) { 436 | frame[y][x+(width - 11)] = 0x88 | (v & 1); 437 | v = v >> 1; 438 | } 439 | } 440 | } 441 | // and a little bit... 442 | frame[width - 8][8] = 0x81; 443 | 444 | return frame; 445 | } 446 | 447 | 448 | public static function serial(frame:Array):ByteArray{ 449 | var ba:ByteArray = new ByteArray(); 450 | ba.writeObject(frame); 451 | ba.compress(); 452 | return ba; 453 | } 454 | 455 | public static function unserial(code:ByteArray):Array 456 | { 457 | code.uncompress() 458 | return code.readObject() as Array; 459 | } 460 | 461 | public static function newFrame(version:int):Array{ 462 | if(version < 1 || version > QRSPEC_VERSION_MAX) 463 | return null 464 | if(frames[version] == null){ 465 | frames[version] = createFrame(version); 466 | } 467 | if(frames[version] == null){ 468 | return []; 469 | } 470 | return frames[version]; 471 | } 472 | 473 | public static function rsBlockNum(spec:Array):int { return spec[0] + spec[3]; } 474 | public static function rsBlockNum1(spec:Array):int { return spec[0]; } 475 | public static function rsDataCodes1(spec:Array):int { return spec[1]; } 476 | public static function rsEccCodes1(spec:Array):int { return spec[2]; } 477 | public static function rsBlockNum2(spec:Array):int { return spec[3]; } 478 | public static function rsDataCodes2(spec:Array):int { return spec[4]; } 479 | public static function rsEccCodes2(spec:Array):int { return spec[2]; } 480 | public static function rsDataLength(spec:Array):int { return (spec[0] * spec[1]) + (spec[3] * spec[4]); } 481 | public static function rsEccLength(spec:Array):int { return (spec[0] + spec[3]) * spec[2]; } 482 | 483 | } 484 | } 485 | -------------------------------------------------------------------------------- /src/org/qrcode/utils/FrameFiller.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.utils 2 | { 3 | import flash.geom.Point; 4 | 5 | public class FrameFiller 6 | { 7 | public var width:int; 8 | public var frame:Array; 9 | public var x:int; 10 | public var y:int; 11 | public var dir:int; 12 | public var bit:int; 13 | 14 | public function FrameFiller(width:int,frame:Array) 15 | { 16 | this.width = width; 17 | this.frame = frame; 18 | this.x = width - 1; 19 | this.y = width - 1; 20 | this.dir = -1; 21 | this.bit = -1; 22 | } 23 | 24 | public function setFrameAt(at:Point, val:Object):void 25 | { 26 | this.frame[at.y][at.x] = val; 27 | } 28 | 29 | public function getFrameAt(at:Point):Object 30 | { 31 | return this.frame[at.y][at.x]; 32 | } 33 | 34 | public function next():Point 35 | { 36 | do { 37 | 38 | if(this.bit == -1) { 39 | this.bit = 0; 40 | return new Point(this.x,this.y); 41 | } 42 | 43 | var xt:int = this.x; 44 | var yt:int = this.y; 45 | var w:int = this.width; 46 | 47 | if(this.bit == 0) { 48 | xt--; 49 | this.bit++; 50 | } else { 51 | xt++; 52 | yt += this.dir; 53 | this.bit--; 54 | } 55 | 56 | if(this.dir < 0) { 57 | if(yt < 0) { 58 | yt = 0; 59 | xt -= 2; 60 | this.dir = 1; 61 | if(xt == 6) { 62 | xt--; 63 | yt = 9; 64 | } 65 | } 66 | } else { 67 | if(yt == w) { 68 | yt = w - 1; 69 | xt -= 2; 70 | this.dir = -1; 71 | if(xt == 6) { 72 | xt--; 73 | yt -= 8; 74 | } 75 | } 76 | } 77 | if(xt < 0 || yt < 0) 78 | return null; 79 | 80 | this.x = xt; 81 | this.y = yt; 82 | 83 | } while(this.frame[y][x] & 0x80); 84 | 85 | return new Point(this.x,this.y); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /src/org/qrcode/utils/QRCodeTool.as: -------------------------------------------------------------------------------- 1 | package org.qrcode.utils 2 | { 3 | import flash.display.FrameLabel; 4 | 5 | public class QRCodeTool 6 | { 7 | 8 | public static function binarize(frame:Array):Array 9 | { 10 | var len:int = frame.length; 11 | for(var frindex:String in frame) { 12 | var frameLine:Array = frame[frindex]; 13 | for(var i:int=0; i