├── 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