├── .gitignore ├── MIT-LICENSE.txt ├── Makefile ├── README.md ├── bower.json ├── examples ├── basic.html └── demo.html ├── index.html ├── jquery.qrcode.min.js └── src ├── jquery.qrcode.js └── qrcode.js /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Jerome Etienne, http://jetienne.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME=jquery-qrcode 2 | 3 | all: 4 | 5 | server: 6 | python -m SimpleHTTPServer 7 | 8 | build: minify 9 | 10 | minify: 11 | echo > /tmp/jquery.qrcode.tmp.js 12 | head -2 src/jquery.qrcode.js >> /tmp/jquery.qrcode.tmp.js 13 | cat src/qrcode.js >> /tmp/jquery.qrcode.tmp.js 14 | tail -n +3 src/jquery.qrcode.js >> /tmp/jquery.qrcode.tmp.js 15 | curl --data-urlencode "js_code@/tmp/jquery.qrcode.tmp.js" \ 16 | -d "output_format=text&output_info=compiled_code&compilation_level=SIMPLE_OPTIMIZATIONS" \ 17 | http://closure-compiler.appspot.com/compile \ 18 | > jquery.qrcode.min.js 19 | 20 | homepage_build: 21 | pandoc -A ~/.pandoc.header.html -s README.md -o index.html 22 | sed -i "s/github.com\/you/github.com\/jeromeetienne\/$(PROJECT_NAME)/g" index.html 23 | 24 | ################################################################################# 25 | # deploy # 26 | ################################################################################# 27 | 28 | deploy: build 29 | # assume there is something to commit 30 | # use "git diff --exit-code HEAD" to know if there is something to commit 31 | # so two lines: one if no commit, one if something to commit 32 | git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jquery.qrcode.js 2 | 3 | jquery.qrcode.js 4 | is *jquery plugin for a pure browser qrcode generation*. 5 | It allow you to easily add qrcode to your webpages. 6 | It is standalone, less than 4k after minify+gzip, no image download. 7 | It doesnt rely on external services which go on and off, or add latency while loading. 8 | It is based on a library 9 | which build qrcode in various language. jquery.qrcode.js wraps 10 | it to make it easy to include in your own code. 11 | 12 | Show, don't tell, here is a example 13 | 14 | ## How to Use It 15 | 16 | Let me walk you thru it. First include it in your webpage with the usual script tag 17 | 18 | 19 | 20 | Then create a DOM element which gonna contains the generated qrcode image. Lets say 21 | a div 22 | 23 |
24 | 25 | Then you add the *qrcode* in this container by 26 | 27 | jquery('#qrcode').qrcode("this plugin is great"); 28 | 29 | This is it. see it live. 30 | 31 | You can set the height and width of the generated qrcode: 32 | 33 | jquery('#qrcode').qrcode({width: 64,height: 64,text: "size doesn't matter"}); 34 | 35 | 36 | ## Conclusion 37 | jquery.qrcode.js is available on github 38 | here 39 | under MIT license. 40 | If you hit bugs, fill issues on github. 41 | Feel free to fork, modify and have fun with it :) 42 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-qrcode", 3 | "version": "1.0.0", 4 | "homepage": "http://www.d-project.com/", 5 | "authors": [ 6 | "jeromeetienne" 7 | ], 8 | "description": "It allow you to easily add qrcode to your webpages. It is standalone, less than 4k after minify+gzip, no image download", 9 | "main": "jquery.qrcode.min.js", 10 | "keywords": [ 11 | "QR", 12 | "jQuery", 13 | "standalone" 14 | ], 15 | "license": "MIT", 16 | "ignore": [ 17 | "**/.*", 18 | "node_modules", 19 | "bower_components", 20 | "test", 21 | "tests" 22 | ], 23 | "dependencies": { 24 | "jquery": "~1.9" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | basic example 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 |

Render in table

14 |
15 |

Render in canvas

16 |
17 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo page 5 | 6 | 7 | 8 |

9 | TODO make a nice looking pure client qrcode generator 10 | even allow download of the image 11 |

12 | 13 |
14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |

jquery.qrcode.js

jquery.qrcode.js is jquery plugin for a pure browser qrcode generation. It allow you to easily add qrcode to your webpages. It is standalone, less than 4k after minify+gzip, no image download. It doesnt rely on external services which go on and off, or add latency while loading. It is based on a library which build qrcode in various language. jquery.qrcode.js wraps it to make it easy to include in your own code.

Show, dont tell, here is a example

How to Use It

Let me walk you thru it. First include it in your webpage with the usual script tag

<script type="text/javascript" src="jquery.qrcode.min.js"></script>
 27 | 

Then create a DOM element which gonna contains the generated qrcode image. Lets say a div

<div id="qrcode"></div>
 34 | 

Then you add the qrcode in this container by

jquery('#qrcode').qrcode("this plugin is great");
 43 | 

This is it. see it live.

Conclusion

jquery.qrcode.js is available on github here under MIT license. If you hit bugs, fill issues on github. Feel free to fork, modify and have fun with it :)

56 | 145 | 146 | 147 | Follow jerome_etienne on Twitter 148 | 149 | 150 | Fork me on GitHub 151 | 152 |
153 | 154 | Tweet 155 |
156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /jquery.qrcode.min.js: -------------------------------------------------------------------------------- 1 | (function(r){r.fn.qrcode=function(h){var s;function u(a){this.mode=s;this.data=a}function o(a,c){this.typeNumber=a;this.errorCorrectLevel=c;this.modules=null;this.moduleCount=0;this.dataCache=null;this.dataList=[]}function q(a,c){if(void 0==a.length)throw Error(a.length+"/"+c);for(var d=0;da||this.moduleCount<=a||0>c||this.moduleCount<=c)throw Error(a+","+c);return this.modules[a][c]},getModuleCount:function(){return this.moduleCount},make:function(){if(1>this.typeNumber){for(var a=1,a=1;40>a;a++){for(var c=p.getRSBlocks(a,this.errorCorrectLevel),d=new t,b=0,e=0;e=d;d++)if(!(-1>=a+d||this.moduleCount<=a+d))for(var b=-1;7>=b;b++)-1>=c+b||this.moduleCount<=c+b||(this.modules[a+d][c+b]= 5 | 0<=d&&6>=d&&(0==b||6==b)||0<=b&&6>=b&&(0==d||6==d)||2<=d&&4>=d&&2<=b&&4>=b?!0:!1)},getBestMaskPattern:function(){for(var a=0,c=0,d=0;8>d;d++){this.makeImpl(!0,d);var b=j.getLostPoint(this);if(0==d||a>b)a=b,c=d}return c},createMovieClip:function(a,c,d){a=a.createEmptyMovieClip(c,d);this.make();for(c=0;c=f;f++)for(var i=-2;2>=i;i++)this.modules[b+f][e+i]=-2==f||2==f||-2==i||2==i||0==f&&0==i?!0:!1}},setupTypeNumber:function(a){for(var c= 7 | j.getBCHTypeNumber(this.typeNumber),d=0;18>d;d++){var b=!a&&1==(c>>d&1);this.modules[Math.floor(d/3)][d%3+this.moduleCount-8-3]=b}for(d=0;18>d;d++)b=!a&&1==(c>>d&1),this.modules[d%3+this.moduleCount-8-3][Math.floor(d/3)]=b},setupTypeInfo:function(a,c){for(var d=j.getBCHTypeInfo(this.errorCorrectLevel<<3|c),b=0;15>b;b++){var e=!a&&1==(d>>b&1);6>b?this.modules[b][8]=e:8>b?this.modules[b+1][8]=e:this.modules[this.moduleCount-15+b][8]=e}for(b=0;15>b;b++)e=!a&&1==(d>>b&1),8>b?this.modules[8][this.moduleCount- 8 | b-1]=e:9>b?this.modules[8][15-b-1+1]=e:this.modules[8][15-b-1]=e;this.modules[this.moduleCount-8][8]=!a},mapData:function(a,c){for(var d=-1,b=this.moduleCount-1,e=7,f=0,i=this.moduleCount-1;0g;g++)if(null==this.modules[b][i-g]){var n=!1;f>>e&1));j.getMask(c,b,i-g)&&(n=!n);this.modules[b][i-g]=n;e--; -1==e&&(f++,e=7)}b+=d;if(0>b||this.moduleCount<=b){b-=d;d=-d;break}}}};o.PAD0=236;o.PAD1=17;o.createData=function(a,c,d){for(var c=p.getRSBlocks(a, 9 | c),b=new t,e=0;e8*a)throw Error("code length overflow. ("+b.getLengthInBits()+">"+8*a+")");for(b.getLengthInBits()+4<=8*a&&b.put(0,4);0!=b.getLengthInBits()%8;)b.putBit(!1);for(;!(b.getLengthInBits()>=8*a);){b.put(o.PAD0,8);if(b.getLengthInBits()>=8*a)break;b.put(o.PAD1,8)}return o.createBytes(b,c)};o.createBytes=function(a,c){for(var d= 10 | 0,b=0,e=0,f=Array(c.length),i=Array(c.length),g=0;g>>=1;return c},getPatternPosition:function(a){return j.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,c,d){switch(a){case 0:return 0==(c+d)%2;case 1:return 0==c%2;case 2:return 0==d%3;case 3:return 0==(c+d)%3;case 4:return 0==(Math.floor(c/2)+Math.floor(d/3))%2;case 5:return 0==c*d%2+c*d%3;case 6:return 0==(c*d%2+c*d%3)%2;case 7:return 0==(c*d%3+(c+d)%2)%2;default:throw Error("bad maskPattern:"+ 14 | a);}},getErrorCorrectPolynomial:function(a){for(var c=new q([1],0),d=0;dc)switch(a){case 1:return 10;case 2:return 9;case s:return 8;case 8:return 8;default:throw Error("mode:"+a);}else if(27>c)switch(a){case 1:return 12;case 2:return 11;case s:return 16;case 8:return 10;default:throw Error("mode:"+a);}else if(41>c)switch(a){case 1:return 14;case 2:return 13;case s:return 16;case 8:return 12;default:throw Error("mode:"+ 15 | a);}else throw Error("type:"+c);},getLostPoint:function(a){for(var c=a.getModuleCount(),d=0,b=0;b=g;g++)if(!(0>b+g||c<=b+g))for(var h=-1;1>=h;h++)0>e+h||c<=e+h||0==g&&0==h||i==a.isDark(b+g,e+h)&&f++;5a)throw Error("glog("+a+")");return l.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;256<=a;)a-=255;return l.EXP_TABLE[a]},EXP_TABLE:Array(256), 17 | LOG_TABLE:Array(256)},m=0;8>m;m++)l.EXP_TABLE[m]=1<m;m++)l.EXP_TABLE[m]=l.EXP_TABLE[m-4]^l.EXP_TABLE[m-5]^l.EXP_TABLE[m-6]^l.EXP_TABLE[m-8];for(m=0;255>m;m++)l.LOG_TABLE[l.EXP_TABLE[m]]=m;q.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var c=Array(this.getLength()+a.getLength()-1),d=0;d 18 | this.getLength()-a.getLength())return this;for(var c=l.glog(this.get(0))-l.glog(a.get(0)),d=Array(this.getLength()),b=0;b>>7-a%8&1)},put:function(a,c){for(var d=0;d>>c-d-1&1))},getLengthInBits:function(){return this.length},putBit:function(a){var c=Math.floor(this.length/8);this.buffer.length<=c&&this.buffer.push(0);a&&(this.buffer[c]|=128>>>this.length%8);this.length++}};"string"===typeof h&&(h={text:h});h=r.extend({},{render:"canvas",width:256,height:256,typeNumber:-1, 26 | correctLevel:2,background:"#ffffff",foreground:"#000000"},h);return this.each(function(){var a;if("canvas"==h.render){a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();var c=document.createElement("canvas");c.width=h.width;c.height=h.height;for(var d=c.getContext("2d"),b=h.width/a.getModuleCount(),e=h.height/a.getModuleCount(),f=0;f").css("width",h.width+"px").css("height",h.height+"px").css("border","0px").css("border-collapse","collapse").css("background-color",h.background);d=h.width/a.getModuleCount();b=h.height/a.getModuleCount();for(e=0;e").css("height",b+"px").appendTo(c);for(i=0;i").css("width", 28 | d+"px").css("background-color",a.isDark(e,i)?h.foreground:h.background).appendTo(f)}}a=c;jQuery(a).appendTo(this)})}})(jQuery); 29 | -------------------------------------------------------------------------------- /src/jquery.qrcode.js: -------------------------------------------------------------------------------- 1 | (function( $ ){ 2 | $.fn.qrcode = function(options) { 3 | // if options is string, 4 | if( typeof options === 'string' ){ 5 | options = { text: options }; 6 | } 7 | 8 | // set default values 9 | // typeNumber < 1 for automatic calculation 10 | options = $.extend( {}, { 11 | render : "canvas", 12 | width : 256, 13 | height : 256, 14 | typeNumber : -1, 15 | correctLevel : QRErrorCorrectLevel.H, 16 | background : "#ffffff", 17 | foreground : "#000000" 18 | }, options); 19 | 20 | var createCanvas = function(){ 21 | // create the qrcode itself 22 | var qrcode = new QRCode(options.typeNumber, options.correctLevel); 23 | qrcode.addData(options.text); 24 | qrcode.make(); 25 | 26 | // create canvas element 27 | var canvas = document.createElement('canvas'); 28 | canvas.width = options.width; 29 | canvas.height = options.height; 30 | var ctx = canvas.getContext('2d'); 31 | 32 | // compute tileW/tileH based on options.width/options.height 33 | var tileW = options.width / qrcode.getModuleCount(); 34 | var tileH = options.height / qrcode.getModuleCount(); 35 | 36 | // draw in the canvas 37 | for( var row = 0; row < qrcode.getModuleCount(); row++ ){ 38 | for( var col = 0; col < qrcode.getModuleCount(); col++ ){ 39 | ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : options.background; 40 | var w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW)); 41 | var h = (Math.ceil((row+1)*tileH) - Math.floor(row*tileH)); 42 | ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH), w, h); 43 | } 44 | } 45 | // return just built canvas 46 | return canvas; 47 | } 48 | 49 | // from Jon-Carlos Rivera (https://github.com/imbcmdth) 50 | var createTable = function(){ 51 | // create the qrcode itself 52 | var qrcode = new QRCode(options.typeNumber, options.correctLevel); 53 | qrcode.addData(options.text); 54 | qrcode.make(); 55 | 56 | // create table element 57 | var $table = $('
') 58 | .css("width", options.width+"px") 59 | .css("height", options.height+"px") 60 | .css("border", "0px") 61 | .css("border-collapse", "collapse") 62 | .css('background-color', options.background); 63 | 64 | // compute tileS percentage 65 | var tileW = options.width / qrcode.getModuleCount(); 66 | var tileH = options.height / qrcode.getModuleCount(); 67 | 68 | // draw in the table 69 | for(var row = 0; row < qrcode.getModuleCount(); row++ ){ 70 | var $row = $('').css('height', tileH+"px").appendTo($table); 71 | 72 | for(var col = 0; col < qrcode.getModuleCount(); col++ ){ 73 | $('') 74 | .css('width', tileW+"px") 75 | .css('background-color', qrcode.isDark(row, col) ? options.foreground : options.background) 76 | .appendTo($row); 77 | } 78 | } 79 | // return just built canvas 80 | return $table; 81 | } 82 | 83 | 84 | return this.each(function(){ 85 | var element = options.render == "canvas" ? createCanvas() : createTable(); 86 | $(element).appendTo(this); 87 | }); 88 | }; 89 | })( jQuery ); 90 | -------------------------------------------------------------------------------- /src/qrcode.js: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------- 2 | // QRCode for JavaScript 3 | // 4 | // Copyright (c) 2009 Kazuhiko Arase 5 | // 6 | // URL: http://www.d-project.com/ 7 | // 8 | // Licensed under the MIT license: 9 | // http://www.opensource.org/licenses/mit-license.php 10 | // 11 | // The word "QR Code" is registered trademark of 12 | // DENSO WAVE INCORPORATED 13 | // http://www.denso-wave.com/qrcode/faqpatent-e.html 14 | // 15 | //--------------------------------------------------------------------- 16 | 17 | //--------------------------------------------------------------------- 18 | // QR8bitByte 19 | //--------------------------------------------------------------------- 20 | 21 | function QR8bitByte(data) { 22 | this.mode = QRMode.MODE_8BIT_BYTE; 23 | this.data = data; 24 | } 25 | 26 | QR8bitByte.prototype = { 27 | 28 | getLength : function(buffer) { 29 | return this.data.length; 30 | }, 31 | 32 | write : function(buffer) { 33 | for (var i = 0; i < this.data.length; i++) { 34 | // not JIS ... 35 | buffer.put(this.data.charCodeAt(i), 8); 36 | } 37 | } 38 | }; 39 | 40 | //--------------------------------------------------------------------- 41 | // QRCode 42 | //--------------------------------------------------------------------- 43 | 44 | function QRCode(typeNumber, errorCorrectLevel) { 45 | this.typeNumber = typeNumber; 46 | this.errorCorrectLevel = errorCorrectLevel; 47 | this.modules = null; 48 | this.moduleCount = 0; 49 | this.dataCache = null; 50 | this.dataList = new Array(); 51 | } 52 | 53 | QRCode.prototype = { 54 | 55 | addData : function(data) { 56 | var newData = new QR8bitByte(data); 57 | this.dataList.push(newData); 58 | this.dataCache = null; 59 | }, 60 | 61 | isDark : function(row, col) { 62 | if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { 63 | throw new Error(row + "," + col); 64 | } 65 | return this.modules[row][col]; 66 | }, 67 | 68 | getModuleCount : function() { 69 | return this.moduleCount; 70 | }, 71 | 72 | make : function() { 73 | // Calculate automatically typeNumber if provided is < 1 74 | if (this.typeNumber < 1 ){ 75 | var typeNumber = 1; 76 | for (typeNumber = 1; typeNumber < 40; typeNumber++) { 77 | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); 78 | 79 | var buffer = new QRBitBuffer(); 80 | var totalDataCount = 0; 81 | for (var i = 0; i < rsBlocks.length; i++) { 82 | totalDataCount += rsBlocks[i].dataCount; 83 | } 84 | 85 | for (var i = 0; i < this.dataList.length; i++) { 86 | var data = this.dataList[i]; 87 | buffer.put(data.mode, 4); 88 | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) ); 89 | data.write(buffer); 90 | } 91 | if (buffer.getLengthInBits() <= totalDataCount * 8) 92 | break; 93 | } 94 | this.typeNumber = typeNumber; 95 | } 96 | this.makeImpl(false, this.getBestMaskPattern() ); 97 | }, 98 | 99 | makeImpl : function(test, maskPattern) { 100 | 101 | this.moduleCount = this.typeNumber * 4 + 17; 102 | this.modules = new Array(this.moduleCount); 103 | 104 | for (var row = 0; row < this.moduleCount; row++) { 105 | 106 | this.modules[row] = new Array(this.moduleCount); 107 | 108 | for (var col = 0; col < this.moduleCount; col++) { 109 | this.modules[row][col] = null;//(col + row) % 3; 110 | } 111 | } 112 | 113 | this.setupPositionProbePattern(0, 0); 114 | this.setupPositionProbePattern(this.moduleCount - 7, 0); 115 | this.setupPositionProbePattern(0, this.moduleCount - 7); 116 | this.setupPositionAdjustPattern(); 117 | this.setupTimingPattern(); 118 | this.setupTypeInfo(test, maskPattern); 119 | 120 | if (this.typeNumber >= 7) { 121 | this.setupTypeNumber(test); 122 | } 123 | 124 | if (this.dataCache == null) { 125 | this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); 126 | } 127 | 128 | this.mapData(this.dataCache, maskPattern); 129 | }, 130 | 131 | setupPositionProbePattern : function(row, col) { 132 | 133 | for (var r = -1; r <= 7; r++) { 134 | 135 | if (row + r <= -1 || this.moduleCount <= row + r) continue; 136 | 137 | for (var c = -1; c <= 7; c++) { 138 | 139 | if (col + c <= -1 || this.moduleCount <= col + c) continue; 140 | 141 | if ( (0 <= r && r <= 6 && (c == 0 || c == 6) ) 142 | || (0 <= c && c <= 6 && (r == 0 || r == 6) ) 143 | || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) { 144 | this.modules[row + r][col + c] = true; 145 | } else { 146 | this.modules[row + r][col + c] = false; 147 | } 148 | } 149 | } 150 | }, 151 | 152 | getBestMaskPattern : function() { 153 | 154 | var minLostPoint = 0; 155 | var pattern = 0; 156 | 157 | for (var i = 0; i < 8; i++) { 158 | 159 | this.makeImpl(true, i); 160 | 161 | var lostPoint = QRUtil.getLostPoint(this); 162 | 163 | if (i == 0 || minLostPoint > lostPoint) { 164 | minLostPoint = lostPoint; 165 | pattern = i; 166 | } 167 | } 168 | 169 | return pattern; 170 | }, 171 | 172 | createMovieClip : function(target_mc, instance_name, depth) { 173 | 174 | var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); 175 | var cs = 1; 176 | 177 | this.make(); 178 | 179 | for (var row = 0; row < this.modules.length; row++) { 180 | 181 | var y = row * cs; 182 | 183 | for (var col = 0; col < this.modules[row].length; col++) { 184 | 185 | var x = col * cs; 186 | var dark = this.modules[row][col]; 187 | 188 | if (dark) { 189 | qr_mc.beginFill(0, 100); 190 | qr_mc.moveTo(x, y); 191 | qr_mc.lineTo(x + cs, y); 192 | qr_mc.lineTo(x + cs, y + cs); 193 | qr_mc.lineTo(x, y + cs); 194 | qr_mc.endFill(); 195 | } 196 | } 197 | } 198 | 199 | return qr_mc; 200 | }, 201 | 202 | setupTimingPattern : function() { 203 | 204 | for (var r = 8; r < this.moduleCount - 8; r++) { 205 | if (this.modules[r][6] != null) { 206 | continue; 207 | } 208 | this.modules[r][6] = (r % 2 == 0); 209 | } 210 | 211 | for (var c = 8; c < this.moduleCount - 8; c++) { 212 | if (this.modules[6][c] != null) { 213 | continue; 214 | } 215 | this.modules[6][c] = (c % 2 == 0); 216 | } 217 | }, 218 | 219 | setupPositionAdjustPattern : function() { 220 | 221 | var pos = QRUtil.getPatternPosition(this.typeNumber); 222 | 223 | for (var i = 0; i < pos.length; i++) { 224 | 225 | for (var j = 0; j < pos.length; j++) { 226 | 227 | var row = pos[i]; 228 | var col = pos[j]; 229 | 230 | if (this.modules[row][col] != null) { 231 | continue; 232 | } 233 | 234 | for (var r = -2; r <= 2; r++) { 235 | 236 | for (var c = -2; c <= 2; c++) { 237 | 238 | if (r == -2 || r == 2 || c == -2 || c == 2 239 | || (r == 0 && c == 0) ) { 240 | this.modules[row + r][col + c] = true; 241 | } else { 242 | this.modules[row + r][col + c] = false; 243 | } 244 | } 245 | } 246 | } 247 | } 248 | }, 249 | 250 | setupTypeNumber : function(test) { 251 | 252 | var bits = QRUtil.getBCHTypeNumber(this.typeNumber); 253 | 254 | for (var i = 0; i < 18; i++) { 255 | var mod = (!test && ( (bits >> i) & 1) == 1); 256 | this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; 257 | } 258 | 259 | for (var i = 0; i < 18; i++) { 260 | var mod = (!test && ( (bits >> i) & 1) == 1); 261 | this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; 262 | } 263 | }, 264 | 265 | setupTypeInfo : function(test, maskPattern) { 266 | 267 | var data = (this.errorCorrectLevel << 3) | maskPattern; 268 | var bits = QRUtil.getBCHTypeInfo(data); 269 | 270 | // vertical 271 | for (var i = 0; i < 15; i++) { 272 | 273 | var mod = (!test && ( (bits >> i) & 1) == 1); 274 | 275 | if (i < 6) { 276 | this.modules[i][8] = mod; 277 | } else if (i < 8) { 278 | this.modules[i + 1][8] = mod; 279 | } else { 280 | this.modules[this.moduleCount - 15 + i][8] = mod; 281 | } 282 | } 283 | 284 | // horizontal 285 | for (var i = 0; i < 15; i++) { 286 | 287 | var mod = (!test && ( (bits >> i) & 1) == 1); 288 | 289 | if (i < 8) { 290 | this.modules[8][this.moduleCount - i - 1] = mod; 291 | } else if (i < 9) { 292 | this.modules[8][15 - i - 1 + 1] = mod; 293 | } else { 294 | this.modules[8][15 - i - 1] = mod; 295 | } 296 | } 297 | 298 | // fixed module 299 | this.modules[this.moduleCount - 8][8] = (!test); 300 | 301 | }, 302 | 303 | mapData : function(data, maskPattern) { 304 | 305 | var inc = -1; 306 | var row = this.moduleCount - 1; 307 | var bitIndex = 7; 308 | var byteIndex = 0; 309 | 310 | for (var col = this.moduleCount - 1; col > 0; col -= 2) { 311 | 312 | if (col == 6) col--; 313 | 314 | while (true) { 315 | 316 | for (var c = 0; c < 2; c++) { 317 | 318 | if (this.modules[row][col - c] == null) { 319 | 320 | var dark = false; 321 | 322 | if (byteIndex < data.length) { 323 | dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1); 324 | } 325 | 326 | var mask = QRUtil.getMask(maskPattern, row, col - c); 327 | 328 | if (mask) { 329 | dark = !dark; 330 | } 331 | 332 | this.modules[row][col - c] = dark; 333 | bitIndex--; 334 | 335 | if (bitIndex == -1) { 336 | byteIndex++; 337 | bitIndex = 7; 338 | } 339 | } 340 | } 341 | 342 | row += inc; 343 | 344 | if (row < 0 || this.moduleCount <= row) { 345 | row -= inc; 346 | inc = -inc; 347 | break; 348 | } 349 | } 350 | } 351 | 352 | } 353 | 354 | }; 355 | 356 | QRCode.PAD0 = 0xEC; 357 | QRCode.PAD1 = 0x11; 358 | 359 | QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) { 360 | 361 | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); 362 | 363 | var buffer = new QRBitBuffer(); 364 | 365 | for (var i = 0; i < dataList.length; i++) { 366 | var data = dataList[i]; 367 | buffer.put(data.mode, 4); 368 | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) ); 369 | data.write(buffer); 370 | } 371 | 372 | // calc num max data. 373 | var totalDataCount = 0; 374 | for (var i = 0; i < rsBlocks.length; i++) { 375 | totalDataCount += rsBlocks[i].dataCount; 376 | } 377 | 378 | if (buffer.getLengthInBits() > totalDataCount * 8) { 379 | throw new Error("code length overflow. (" 380 | + buffer.getLengthInBits() 381 | + ">" 382 | + totalDataCount * 8 383 | + ")"); 384 | } 385 | 386 | // end code 387 | if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { 388 | buffer.put(0, 4); 389 | } 390 | 391 | // padding 392 | while (buffer.getLengthInBits() % 8 != 0) { 393 | buffer.putBit(false); 394 | } 395 | 396 | // padding 397 | while (true) { 398 | 399 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 400 | break; 401 | } 402 | buffer.put(QRCode.PAD0, 8); 403 | 404 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 405 | break; 406 | } 407 | buffer.put(QRCode.PAD1, 8); 408 | } 409 | 410 | return QRCode.createBytes(buffer, rsBlocks); 411 | } 412 | 413 | QRCode.createBytes = function(buffer, rsBlocks) { 414 | 415 | var offset = 0; 416 | 417 | var maxDcCount = 0; 418 | var maxEcCount = 0; 419 | 420 | var dcdata = new Array(rsBlocks.length); 421 | var ecdata = new Array(rsBlocks.length); 422 | 423 | for (var r = 0; r < rsBlocks.length; r++) { 424 | 425 | var dcCount = rsBlocks[r].dataCount; 426 | var ecCount = rsBlocks[r].totalCount - dcCount; 427 | 428 | maxDcCount = Math.max(maxDcCount, dcCount); 429 | maxEcCount = Math.max(maxEcCount, ecCount); 430 | 431 | dcdata[r] = new Array(dcCount); 432 | 433 | for (var i = 0; i < dcdata[r].length; i++) { 434 | dcdata[r][i] = 0xff & buffer.buffer[i + offset]; 435 | } 436 | offset += dcCount; 437 | 438 | var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); 439 | var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); 440 | 441 | var modPoly = rawPoly.mod(rsPoly); 442 | ecdata[r] = new Array(rsPoly.getLength() - 1); 443 | for (var i = 0; i < ecdata[r].length; i++) { 444 | var modIndex = i + modPoly.getLength() - ecdata[r].length; 445 | ecdata[r][i] = (modIndex >= 0)? modPoly.get(modIndex) : 0; 446 | } 447 | 448 | } 449 | 450 | var totalCodeCount = 0; 451 | for (var i = 0; i < rsBlocks.length; i++) { 452 | totalCodeCount += rsBlocks[i].totalCount; 453 | } 454 | 455 | var data = new Array(totalCodeCount); 456 | var index = 0; 457 | 458 | for (var i = 0; i < maxDcCount; i++) { 459 | for (var r = 0; r < rsBlocks.length; r++) { 460 | if (i < dcdata[r].length) { 461 | data[index++] = dcdata[r][i]; 462 | } 463 | } 464 | } 465 | 466 | for (var i = 0; i < maxEcCount; i++) { 467 | for (var r = 0; r < rsBlocks.length; r++) { 468 | if (i < ecdata[r].length) { 469 | data[index++] = ecdata[r][i]; 470 | } 471 | } 472 | } 473 | 474 | return data; 475 | 476 | } 477 | 478 | //--------------------------------------------------------------------- 479 | // QRMode 480 | //--------------------------------------------------------------------- 481 | 482 | var QRMode = { 483 | MODE_NUMBER : 1 << 0, 484 | MODE_ALPHA_NUM : 1 << 1, 485 | MODE_8BIT_BYTE : 1 << 2, 486 | MODE_KANJI : 1 << 3 487 | }; 488 | 489 | //--------------------------------------------------------------------- 490 | // QRErrorCorrectLevel 491 | //--------------------------------------------------------------------- 492 | 493 | var QRErrorCorrectLevel = { 494 | L : 1, 495 | M : 0, 496 | Q : 3, 497 | H : 2 498 | }; 499 | 500 | //--------------------------------------------------------------------- 501 | // QRMaskPattern 502 | //--------------------------------------------------------------------- 503 | 504 | var QRMaskPattern = { 505 | PATTERN000 : 0, 506 | PATTERN001 : 1, 507 | PATTERN010 : 2, 508 | PATTERN011 : 3, 509 | PATTERN100 : 4, 510 | PATTERN101 : 5, 511 | PATTERN110 : 6, 512 | PATTERN111 : 7 513 | }; 514 | 515 | //--------------------------------------------------------------------- 516 | // QRUtil 517 | //--------------------------------------------------------------------- 518 | 519 | var QRUtil = { 520 | 521 | PATTERN_POSITION_TABLE : [ 522 | [], 523 | [6, 18], 524 | [6, 22], 525 | [6, 26], 526 | [6, 30], 527 | [6, 34], 528 | [6, 22, 38], 529 | [6, 24, 42], 530 | [6, 26, 46], 531 | [6, 28, 50], 532 | [6, 30, 54], 533 | [6, 32, 58], 534 | [6, 34, 62], 535 | [6, 26, 46, 66], 536 | [6, 26, 48, 70], 537 | [6, 26, 50, 74], 538 | [6, 30, 54, 78], 539 | [6, 30, 56, 82], 540 | [6, 30, 58, 86], 541 | [6, 34, 62, 90], 542 | [6, 28, 50, 72, 94], 543 | [6, 26, 50, 74, 98], 544 | [6, 30, 54, 78, 102], 545 | [6, 28, 54, 80, 106], 546 | [6, 32, 58, 84, 110], 547 | [6, 30, 58, 86, 114], 548 | [6, 34, 62, 90, 118], 549 | [6, 26, 50, 74, 98, 122], 550 | [6, 30, 54, 78, 102, 126], 551 | [6, 26, 52, 78, 104, 130], 552 | [6, 30, 56, 82, 108, 134], 553 | [6, 34, 60, 86, 112, 138], 554 | [6, 30, 58, 86, 114, 142], 555 | [6, 34, 62, 90, 118, 146], 556 | [6, 30, 54, 78, 102, 126, 150], 557 | [6, 24, 50, 76, 102, 128, 154], 558 | [6, 28, 54, 80, 106, 132, 158], 559 | [6, 32, 58, 84, 110, 136, 162], 560 | [6, 26, 54, 82, 110, 138, 166], 561 | [6, 30, 58, 86, 114, 142, 170] 562 | ], 563 | 564 | G15 : (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), 565 | G18 : (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), 566 | G15_MASK : (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), 567 | 568 | getBCHTypeInfo : function(data) { 569 | var d = data << 10; 570 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { 571 | d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) ); 572 | } 573 | return ( (data << 10) | d) ^ QRUtil.G15_MASK; 574 | }, 575 | 576 | getBCHTypeNumber : function(data) { 577 | var d = data << 12; 578 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { 579 | d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) ); 580 | } 581 | return (data << 12) | d; 582 | }, 583 | 584 | getBCHDigit : function(data) { 585 | 586 | var digit = 0; 587 | 588 | while (data != 0) { 589 | digit++; 590 | data >>>= 1; 591 | } 592 | 593 | return digit; 594 | }, 595 | 596 | getPatternPosition : function(typeNumber) { 597 | return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; 598 | }, 599 | 600 | getMask : function(maskPattern, i, j) { 601 | 602 | switch (maskPattern) { 603 | 604 | case QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0; 605 | case QRMaskPattern.PATTERN001 : return i % 2 == 0; 606 | case QRMaskPattern.PATTERN010 : return j % 3 == 0; 607 | case QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0; 608 | case QRMaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; 609 | case QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0; 610 | case QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; 611 | case QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; 612 | 613 | default : 614 | throw new Error("bad maskPattern:" + maskPattern); 615 | } 616 | }, 617 | 618 | getErrorCorrectPolynomial : function(errorCorrectLength) { 619 | 620 | var a = new QRPolynomial([1], 0); 621 | 622 | for (var i = 0; i < errorCorrectLength; i++) { 623 | a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0) ); 624 | } 625 | 626 | return a; 627 | }, 628 | 629 | getLengthInBits : function(mode, type) { 630 | 631 | if (1 <= type && type < 10) { 632 | 633 | // 1 - 9 634 | 635 | switch(mode) { 636 | case QRMode.MODE_NUMBER : return 10; 637 | case QRMode.MODE_ALPHA_NUM : return 9; 638 | case QRMode.MODE_8BIT_BYTE : return 8; 639 | case QRMode.MODE_KANJI : return 8; 640 | default : 641 | throw new Error("mode:" + mode); 642 | } 643 | 644 | } else if (type < 27) { 645 | 646 | // 10 - 26 647 | 648 | switch(mode) { 649 | case QRMode.MODE_NUMBER : return 12; 650 | case QRMode.MODE_ALPHA_NUM : return 11; 651 | case QRMode.MODE_8BIT_BYTE : return 16; 652 | case QRMode.MODE_KANJI : return 10; 653 | default : 654 | throw new Error("mode:" + mode); 655 | } 656 | 657 | } else if (type < 41) { 658 | 659 | // 27 - 40 660 | 661 | switch(mode) { 662 | case QRMode.MODE_NUMBER : return 14; 663 | case QRMode.MODE_ALPHA_NUM : return 13; 664 | case QRMode.MODE_8BIT_BYTE : return 16; 665 | case QRMode.MODE_KANJI : return 12; 666 | default : 667 | throw new Error("mode:" + mode); 668 | } 669 | 670 | } else { 671 | throw new Error("type:" + type); 672 | } 673 | }, 674 | 675 | getLostPoint : function(qrCode) { 676 | 677 | var moduleCount = qrCode.getModuleCount(); 678 | 679 | var lostPoint = 0; 680 | 681 | // LEVEL1 682 | 683 | for (var row = 0; row < moduleCount; row++) { 684 | 685 | for (var col = 0; col < moduleCount; col++) { 686 | 687 | var sameCount = 0; 688 | var dark = qrCode.isDark(row, col); 689 | 690 | for (var r = -1; r <= 1; r++) { 691 | 692 | if (row + r < 0 || moduleCount <= row + r) { 693 | continue; 694 | } 695 | 696 | for (var c = -1; c <= 1; c++) { 697 | 698 | if (col + c < 0 || moduleCount <= col + c) { 699 | continue; 700 | } 701 | 702 | if (r == 0 && c == 0) { 703 | continue; 704 | } 705 | 706 | if (dark == qrCode.isDark(row + r, col + c) ) { 707 | sameCount++; 708 | } 709 | } 710 | } 711 | 712 | if (sameCount > 5) { 713 | lostPoint += (3 + sameCount - 5); 714 | } 715 | } 716 | } 717 | 718 | // LEVEL2 719 | 720 | for (var row = 0; row < moduleCount - 1; row++) { 721 | for (var col = 0; col < moduleCount - 1; col++) { 722 | var count = 0; 723 | if (qrCode.isDark(row, col ) ) count++; 724 | if (qrCode.isDark(row + 1, col ) ) count++; 725 | if (qrCode.isDark(row, col + 1) ) count++; 726 | if (qrCode.isDark(row + 1, col + 1) ) count++; 727 | if (count == 0 || count == 4) { 728 | lostPoint += 3; 729 | } 730 | } 731 | } 732 | 733 | // LEVEL3 734 | 735 | for (var row = 0; row < moduleCount; row++) { 736 | for (var col = 0; col < moduleCount - 6; col++) { 737 | if (qrCode.isDark(row, col) 738 | && !qrCode.isDark(row, col + 1) 739 | && qrCode.isDark(row, col + 2) 740 | && qrCode.isDark(row, col + 3) 741 | && qrCode.isDark(row, col + 4) 742 | && !qrCode.isDark(row, col + 5) 743 | && qrCode.isDark(row, col + 6) ) { 744 | lostPoint += 40; 745 | } 746 | } 747 | } 748 | 749 | for (var col = 0; col < moduleCount; col++) { 750 | for (var row = 0; row < moduleCount - 6; row++) { 751 | if (qrCode.isDark(row, col) 752 | && !qrCode.isDark(row + 1, col) 753 | && qrCode.isDark(row + 2, col) 754 | && qrCode.isDark(row + 3, col) 755 | && qrCode.isDark(row + 4, col) 756 | && !qrCode.isDark(row + 5, col) 757 | && qrCode.isDark(row + 6, col) ) { 758 | lostPoint += 40; 759 | } 760 | } 761 | } 762 | 763 | // LEVEL4 764 | 765 | var darkCount = 0; 766 | 767 | for (var col = 0; col < moduleCount; col++) { 768 | for (var row = 0; row < moduleCount; row++) { 769 | if (qrCode.isDark(row, col) ) { 770 | darkCount++; 771 | } 772 | } 773 | } 774 | 775 | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; 776 | lostPoint += ratio * 10; 777 | 778 | return lostPoint; 779 | } 780 | 781 | }; 782 | 783 | 784 | //--------------------------------------------------------------------- 785 | // QRMath 786 | //--------------------------------------------------------------------- 787 | 788 | var QRMath = { 789 | 790 | glog : function(n) { 791 | 792 | if (n < 1) { 793 | throw new Error("glog(" + n + ")"); 794 | } 795 | 796 | return QRMath.LOG_TABLE[n]; 797 | }, 798 | 799 | gexp : function(n) { 800 | 801 | while (n < 0) { 802 | n += 255; 803 | } 804 | 805 | while (n >= 256) { 806 | n -= 255; 807 | } 808 | 809 | return QRMath.EXP_TABLE[n]; 810 | }, 811 | 812 | EXP_TABLE : new Array(256), 813 | 814 | LOG_TABLE : new Array(256) 815 | 816 | }; 817 | 818 | for (var i = 0; i < 8; i++) { 819 | QRMath.EXP_TABLE[i] = 1 << i; 820 | } 821 | for (var i = 8; i < 256; i++) { 822 | QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] 823 | ^ QRMath.EXP_TABLE[i - 5] 824 | ^ QRMath.EXP_TABLE[i - 6] 825 | ^ QRMath.EXP_TABLE[i - 8]; 826 | } 827 | for (var i = 0; i < 255; i++) { 828 | QRMath.LOG_TABLE[QRMath.EXP_TABLE[i] ] = i; 829 | } 830 | 831 | //--------------------------------------------------------------------- 832 | // QRPolynomial 833 | //--------------------------------------------------------------------- 834 | 835 | function QRPolynomial(num, shift) { 836 | 837 | if (num.length == undefined) { 838 | throw new Error(num.length + "/" + shift); 839 | } 840 | 841 | var offset = 0; 842 | 843 | while (offset < num.length && num[offset] == 0) { 844 | offset++; 845 | } 846 | 847 | this.num = new Array(num.length - offset + shift); 848 | for (var i = 0; i < num.length - offset; i++) { 849 | this.num[i] = num[i + offset]; 850 | } 851 | } 852 | 853 | QRPolynomial.prototype = { 854 | 855 | get : function(index) { 856 | return this.num[index]; 857 | }, 858 | 859 | getLength : function() { 860 | return this.num.length; 861 | }, 862 | 863 | multiply : function(e) { 864 | 865 | var num = new Array(this.getLength() + e.getLength() - 1); 866 | 867 | for (var i = 0; i < this.getLength(); i++) { 868 | for (var j = 0; j < e.getLength(); j++) { 869 | num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i) ) + QRMath.glog(e.get(j) ) ); 870 | } 871 | } 872 | 873 | return new QRPolynomial(num, 0); 874 | }, 875 | 876 | mod : function(e) { 877 | 878 | if (this.getLength() - e.getLength() < 0) { 879 | return this; 880 | } 881 | 882 | var ratio = QRMath.glog(this.get(0) ) - QRMath.glog(e.get(0) ); 883 | 884 | var num = new Array(this.getLength() ); 885 | 886 | for (var i = 0; i < this.getLength(); i++) { 887 | num[i] = this.get(i); 888 | } 889 | 890 | for (var i = 0; i < e.getLength(); i++) { 891 | num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio); 892 | } 893 | 894 | // recursive call 895 | return new QRPolynomial(num, 0).mod(e); 896 | } 897 | }; 898 | 899 | //--------------------------------------------------------------------- 900 | // QRRSBlock 901 | //--------------------------------------------------------------------- 902 | 903 | function QRRSBlock(totalCount, dataCount) { 904 | this.totalCount = totalCount; 905 | this.dataCount = dataCount; 906 | } 907 | 908 | QRRSBlock.RS_BLOCK_TABLE = [ 909 | 910 | // L 911 | // M 912 | // Q 913 | // H 914 | 915 | // 1 916 | [1, 26, 19], 917 | [1, 26, 16], 918 | [1, 26, 13], 919 | [1, 26, 9], 920 | 921 | // 2 922 | [1, 44, 34], 923 | [1, 44, 28], 924 | [1, 44, 22], 925 | [1, 44, 16], 926 | 927 | // 3 928 | [1, 70, 55], 929 | [1, 70, 44], 930 | [2, 35, 17], 931 | [2, 35, 13], 932 | 933 | // 4 934 | [1, 100, 80], 935 | [2, 50, 32], 936 | [2, 50, 24], 937 | [4, 25, 9], 938 | 939 | // 5 940 | [1, 134, 108], 941 | [2, 67, 43], 942 | [2, 33, 15, 2, 34, 16], 943 | [2, 33, 11, 2, 34, 12], 944 | 945 | // 6 946 | [2, 86, 68], 947 | [4, 43, 27], 948 | [4, 43, 19], 949 | [4, 43, 15], 950 | 951 | // 7 952 | [2, 98, 78], 953 | [4, 49, 31], 954 | [2, 32, 14, 4, 33, 15], 955 | [4, 39, 13, 1, 40, 14], 956 | 957 | // 8 958 | [2, 121, 97], 959 | [2, 60, 38, 2, 61, 39], 960 | [4, 40, 18, 2, 41, 19], 961 | [4, 40, 14, 2, 41, 15], 962 | 963 | // 9 964 | [2, 146, 116], 965 | [3, 58, 36, 2, 59, 37], 966 | [4, 36, 16, 4, 37, 17], 967 | [4, 36, 12, 4, 37, 13], 968 | 969 | // 10 970 | [2, 86, 68, 2, 87, 69], 971 | [4, 69, 43, 1, 70, 44], 972 | [6, 43, 19, 2, 44, 20], 973 | [6, 43, 15, 2, 44, 16], 974 | 975 | // 11 976 | [4, 101, 81], 977 | [1, 80, 50, 4, 81, 51], 978 | [4, 50, 22, 4, 51, 23], 979 | [3, 36, 12, 8, 37, 13], 980 | 981 | // 12 982 | [2, 116, 92, 2, 117, 93], 983 | [6, 58, 36, 2, 59, 37], 984 | [4, 46, 20, 6, 47, 21], 985 | [7, 42, 14, 4, 43, 15], 986 | 987 | // 13 988 | [4, 133, 107], 989 | [8, 59, 37, 1, 60, 38], 990 | [8, 44, 20, 4, 45, 21], 991 | [12, 33, 11, 4, 34, 12], 992 | 993 | // 14 994 | [3, 145, 115, 1, 146, 116], 995 | [4, 64, 40, 5, 65, 41], 996 | [11, 36, 16, 5, 37, 17], 997 | [11, 36, 12, 5, 37, 13], 998 | 999 | // 15 1000 | [5, 109, 87, 1, 110, 88], 1001 | [5, 65, 41, 5, 66, 42], 1002 | [5, 54, 24, 7, 55, 25], 1003 | [11, 36, 12], 1004 | 1005 | // 16 1006 | [5, 122, 98, 1, 123, 99], 1007 | [7, 73, 45, 3, 74, 46], 1008 | [15, 43, 19, 2, 44, 20], 1009 | [3, 45, 15, 13, 46, 16], 1010 | 1011 | // 17 1012 | [1, 135, 107, 5, 136, 108], 1013 | [10, 74, 46, 1, 75, 47], 1014 | [1, 50, 22, 15, 51, 23], 1015 | [2, 42, 14, 17, 43, 15], 1016 | 1017 | // 18 1018 | [5, 150, 120, 1, 151, 121], 1019 | [9, 69, 43, 4, 70, 44], 1020 | [17, 50, 22, 1, 51, 23], 1021 | [2, 42, 14, 19, 43, 15], 1022 | 1023 | // 19 1024 | [3, 141, 113, 4, 142, 114], 1025 | [3, 70, 44, 11, 71, 45], 1026 | [17, 47, 21, 4, 48, 22], 1027 | [9, 39, 13, 16, 40, 14], 1028 | 1029 | // 20 1030 | [3, 135, 107, 5, 136, 108], 1031 | [3, 67, 41, 13, 68, 42], 1032 | [15, 54, 24, 5, 55, 25], 1033 | [15, 43, 15, 10, 44, 16], 1034 | 1035 | // 21 1036 | [4, 144, 116, 4, 145, 117], 1037 | [17, 68, 42], 1038 | [17, 50, 22, 6, 51, 23], 1039 | [19, 46, 16, 6, 47, 17], 1040 | 1041 | // 22 1042 | [2, 139, 111, 7, 140, 112], 1043 | [17, 74, 46], 1044 | [7, 54, 24, 16, 55, 25], 1045 | [34, 37, 13], 1046 | 1047 | // 23 1048 | [4, 151, 121, 5, 152, 122], 1049 | [4, 75, 47, 14, 76, 48], 1050 | [11, 54, 24, 14, 55, 25], 1051 | [16, 45, 15, 14, 46, 16], 1052 | 1053 | // 24 1054 | [6, 147, 117, 4, 148, 118], 1055 | [6, 73, 45, 14, 74, 46], 1056 | [11, 54, 24, 16, 55, 25], 1057 | [30, 46, 16, 2, 47, 17], 1058 | 1059 | // 25 1060 | [8, 132, 106, 4, 133, 107], 1061 | [8, 75, 47, 13, 76, 48], 1062 | [7, 54, 24, 22, 55, 25], 1063 | [22, 45, 15, 13, 46, 16], 1064 | 1065 | // 26 1066 | [10, 142, 114, 2, 143, 115], 1067 | [19, 74, 46, 4, 75, 47], 1068 | [28, 50, 22, 6, 51, 23], 1069 | [33, 46, 16, 4, 47, 17], 1070 | 1071 | // 27 1072 | [8, 152, 122, 4, 153, 123], 1073 | [22, 73, 45, 3, 74, 46], 1074 | [8, 53, 23, 26, 54, 24], 1075 | [12, 45, 15, 28, 46, 16], 1076 | 1077 | // 28 1078 | [3, 147, 117, 10, 148, 118], 1079 | [3, 73, 45, 23, 74, 46], 1080 | [4, 54, 24, 31, 55, 25], 1081 | [11, 45, 15, 31, 46, 16], 1082 | 1083 | // 29 1084 | [7, 146, 116, 7, 147, 117], 1085 | [21, 73, 45, 7, 74, 46], 1086 | [1, 53, 23, 37, 54, 24], 1087 | [19, 45, 15, 26, 46, 16], 1088 | 1089 | // 30 1090 | [5, 145, 115, 10, 146, 116], 1091 | [19, 75, 47, 10, 76, 48], 1092 | [15, 54, 24, 25, 55, 25], 1093 | [23, 45, 15, 25, 46, 16], 1094 | 1095 | // 31 1096 | [13, 145, 115, 3, 146, 116], 1097 | [2, 74, 46, 29, 75, 47], 1098 | [42, 54, 24, 1, 55, 25], 1099 | [23, 45, 15, 28, 46, 16], 1100 | 1101 | // 32 1102 | [17, 145, 115], 1103 | [10, 74, 46, 23, 75, 47], 1104 | [10, 54, 24, 35, 55, 25], 1105 | [19, 45, 15, 35, 46, 16], 1106 | 1107 | // 33 1108 | [17, 145, 115, 1, 146, 116], 1109 | [14, 74, 46, 21, 75, 47], 1110 | [29, 54, 24, 19, 55, 25], 1111 | [11, 45, 15, 46, 46, 16], 1112 | 1113 | // 34 1114 | [13, 145, 115, 6, 146, 116], 1115 | [14, 74, 46, 23, 75, 47], 1116 | [44, 54, 24, 7, 55, 25], 1117 | [59, 46, 16, 1, 47, 17], 1118 | 1119 | // 35 1120 | [12, 151, 121, 7, 152, 122], 1121 | [12, 75, 47, 26, 76, 48], 1122 | [39, 54, 24, 14, 55, 25], 1123 | [22, 45, 15, 41, 46, 16], 1124 | 1125 | // 36 1126 | [6, 151, 121, 14, 152, 122], 1127 | [6, 75, 47, 34, 76, 48], 1128 | [46, 54, 24, 10, 55, 25], 1129 | [2, 45, 15, 64, 46, 16], 1130 | 1131 | // 37 1132 | [17, 152, 122, 4, 153, 123], 1133 | [29, 74, 46, 14, 75, 47], 1134 | [49, 54, 24, 10, 55, 25], 1135 | [24, 45, 15, 46, 46, 16], 1136 | 1137 | // 38 1138 | [4, 152, 122, 18, 153, 123], 1139 | [13, 74, 46, 32, 75, 47], 1140 | [48, 54, 24, 14, 55, 25], 1141 | [42, 45, 15, 32, 46, 16], 1142 | 1143 | // 39 1144 | [20, 147, 117, 4, 148, 118], 1145 | [40, 75, 47, 7, 76, 48], 1146 | [43, 54, 24, 22, 55, 25], 1147 | [10, 45, 15, 67, 46, 16], 1148 | 1149 | // 40 1150 | [19, 148, 118, 6, 149, 119], 1151 | [18, 75, 47, 31, 76, 48], 1152 | [34, 54, 24, 34, 55, 25], 1153 | [20, 45, 15, 61, 46, 16] 1154 | ]; 1155 | 1156 | QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) { 1157 | 1158 | var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); 1159 | 1160 | if (rsBlock == undefined) { 1161 | throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); 1162 | } 1163 | 1164 | var length = rsBlock.length / 3; 1165 | 1166 | var list = new Array(); 1167 | 1168 | for (var i = 0; i < length; i++) { 1169 | 1170 | var count = rsBlock[i * 3 + 0]; 1171 | var totalCount = rsBlock[i * 3 + 1]; 1172 | var dataCount = rsBlock[i * 3 + 2]; 1173 | 1174 | for (var j = 0; j < count; j++) { 1175 | list.push(new QRRSBlock(totalCount, dataCount) ); 1176 | } 1177 | } 1178 | 1179 | return list; 1180 | } 1181 | 1182 | QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) { 1183 | 1184 | switch(errorCorrectLevel) { 1185 | case QRErrorCorrectLevel.L : 1186 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; 1187 | case QRErrorCorrectLevel.M : 1188 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; 1189 | case QRErrorCorrectLevel.Q : 1190 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; 1191 | case QRErrorCorrectLevel.H : 1192 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; 1193 | default : 1194 | return undefined; 1195 | } 1196 | } 1197 | 1198 | //--------------------------------------------------------------------- 1199 | // QRBitBuffer 1200 | //--------------------------------------------------------------------- 1201 | 1202 | function QRBitBuffer() { 1203 | this.buffer = new Array(); 1204 | this.length = 0; 1205 | } 1206 | 1207 | QRBitBuffer.prototype = { 1208 | 1209 | get : function(index) { 1210 | var bufIndex = Math.floor(index / 8); 1211 | return ( (this.buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1; 1212 | }, 1213 | 1214 | put : function(num, length) { 1215 | for (var i = 0; i < length; i++) { 1216 | this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1); 1217 | } 1218 | }, 1219 | 1220 | getLengthInBits : function() { 1221 | return this.length; 1222 | }, 1223 | 1224 | putBit : function(bit) { 1225 | 1226 | var bufIndex = Math.floor(this.length / 8); 1227 | if (this.buffer.length <= bufIndex) { 1228 | this.buffer.push(0); 1229 | } 1230 | 1231 | if (bit) { 1232 | this.buffer[bufIndex] |= (0x80 >>> (this.length % 8) ); 1233 | } 1234 | 1235 | this.length++; 1236 | } 1237 | }; 1238 | --------------------------------------------------------------------------------