├── .gitignore ├── sample.js ├── package.json ├── webpack.config.js ├── README.md ├── sample.html ├── index.js ├── dist └── qrcode.js └── qrcode.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .idea 4 | -------------------------------------------------------------------------------- /sample.js: -------------------------------------------------------------------------------- 1 | var container = document.querySelector('#container'); 2 | var qr = new QRCode(container, { 3 | width: 400, 4 | height: 400 5 | }); 6 | 7 | var makeCode = function() { 8 | var text = document.querySelector('#text').value; 9 | qr.make(text); 10 | }; 11 | 12 | makeCode(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-qrcode", 3 | "version": "1.0.0", 4 | "description": "web端基于纯js实现的二维码生成模块", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://git@github.com:Spikef/js-qrcode.git" 8 | }, 9 | "main": "dist/qrcode.js", 10 | "scripts": { 11 | "build": "node_modules/.bin/webpack" 12 | }, 13 | "author": "Spikef", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "webpack": "^2.7.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: path.resolve(__dirname, 'index.js'), 6 | output: { 7 | filename: 'qrcode.js', 8 | path: path.resolve(__dirname, 'dist'), 9 | library: 'QRCode', 10 | libraryTarget: 'umd' 11 | }, 12 | plugins: [ 13 | new webpack.optimize.UglifyJsPlugin({ 14 | compress: { 15 | warnings: false, 16 | drop_debugger: true, 17 | drop_console: true 18 | } 19 | }) 20 | ] 21 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js-qrcode 2 | 3 | web端基于纯js实现的二维码生成模块 4 | 5 | ## Feature 6 | 7 | * 支持中文 8 | * 使用简单 9 | * 无外部依赖 10 | * umd加载 11 | 12 | ## Install 13 | 14 | ```bash 15 | $ npm i js-qrcode --save 16 | ``` 17 | 18 | ## Usage 19 | 20 | ### 引用 21 | 22 | 方式一: 23 | 24 | ```html 25 | 26 | ``` 27 | 28 | 方式二: 29 | 30 | ```javascript 31 | var QRCode = require('js-qrcode'); 32 | ``` 33 | 34 | ### 生成二维码 35 | 36 | ```javascript 37 | var text = document.querySelector('#text').value; 38 | var container = document.querySelector('#container'); 39 | var qr = new QRCode(container, { 40 | width : 256, 41 | height : 256, 42 | typeNumber : -1, 43 | correctLevel : 2, 44 | background : "#ffffff", 45 | foreground : "#000000" 46 | }); 47 | 48 | qr.make(text); 49 | ``` -------------------------------------------------------------------------------- /sample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QR Code Generator for JavaScript 6 | 30 | 31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var QR = require('./qrcode'); 2 | var QRErrorCorrectLevel = { 3 | L : 1, 4 | M : 0, 5 | Q : 3, 6 | H : 2 7 | }; 8 | 9 | var defaultOptions = { 10 | width : 256, 11 | height : 256, 12 | typeNumber : -1, 13 | correctLevel : QRErrorCorrectLevel.H, 14 | background : "#ffffff", 15 | foreground : "#000000" 16 | }; 17 | 18 | var QRCode = function(container, options) { 19 | this.options = extend(defaultOptions, options); 20 | this.container = container; 21 | }; 22 | 23 | QRCode.prototype.make = function(text) { 24 | var options = this.options; 25 | var container = this.container; 26 | 27 | text = utf16to8(text); 28 | 29 | var canvas = this.createCanvas(text, options); 30 | var src = canvas.toDataURL(); 31 | var img = document.createElement('img'); 32 | img.style.height = '100%'; 33 | img.style.width = '100%'; 34 | img.setAttribute('src', src); 35 | container.innerHTML = ''; 36 | container.appendChild(img); 37 | }; 38 | 39 | QRCode.prototype.createCanvas = function(text, options) { 40 | var qrcode = new QR(options.typeNumber, options.correctLevel); 41 | qrcode.addData(text); 42 | qrcode.make(); 43 | 44 | // create canvas element 45 | var canvas = document.createElement('canvas'); 46 | canvas.width = options.width; 47 | canvas.height = options.height; 48 | var ctx = canvas.getContext('2d'); 49 | 50 | // compute tileW/tileH based on options.width/options.height 51 | var tileW = options.width / qrcode.getModuleCount(); 52 | var tileH = options.height / qrcode.getModuleCount(); 53 | 54 | // draw in the canvas 55 | for( var row = 0; row < qrcode.getModuleCount(); row++ ){ 56 | for( var col = 0; col < qrcode.getModuleCount(); col++ ){ 57 | ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : options.background; 58 | var w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW)); 59 | var h = (Math.ceil((row+1)*tileW) - Math.floor(row*tileW)); 60 | ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH), w, h); 61 | } 62 | } 63 | 64 | // return just built canvas 65 | return canvas; 66 | }; 67 | 68 | function extend(source, target) { 69 | var obj = JSON.parse(JSON.stringify(source)); 70 | 71 | if (!target || typeof target !== 'object') target = {}; 72 | 73 | for (var i in target) { 74 | if (!target.hasOwnProperty(i)) continue; 75 | 76 | obj[i] = target[i]; 77 | } 78 | 79 | return obj; 80 | } 81 | 82 | function utf16to8(str) { 83 | var out, i, len, c; 84 | out = ""; 85 | len = str.length; 86 | for(i = 0; i < len; i++) { 87 | c = str.charCodeAt(i); 88 | if ((c >= 0x0001) && (c <= 0x007F)) { 89 | out += str.charAt(i); 90 | } else if (c > 0x07FF) { 91 | out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); 92 | out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); 93 | out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); 94 | } else { 95 | out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); 96 | out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); 97 | } 98 | } 99 | return out; 100 | } 101 | 102 | module.exports = QRCode; -------------------------------------------------------------------------------- /dist/qrcode.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.QRCode=e():t.QRCode=e()}(this,function(){return function(t){function e(o){if(r[o])return r[o].exports;var n=r[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,r,o){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=1)}([function(t,e){function r(t){this.mode=u.MODE_8BIT_BYTE,this.data=t}function o(t,e){this.typeNumber=t,this.errorCorrectLevel=e,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=new Array}function n(t,e){if(void 0==t.length)throw new Error(t.length+"/"+e);for(var r=0;r=7&&this.setupTypeNumber(t),null==this.dataCache&&(this.dataCache=o.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,e)},setupPositionProbePattern:function(t,e){for(var r=-1;r<=7;r++)if(!(t+r<=-1||this.moduleCount<=t+r))for(var o=-1;o<=7;o++)e+o<=-1||this.moduleCount<=e+o||(this.modules[t+r][e+o]=0<=r&&r<=6&&(0==o||6==o)||0<=o&&o<=6&&(0==r||6==r)||2<=r&&r<=4&&2<=o&&o<=4)},getBestMaskPattern:function(){for(var t=0,e=0,r=0;r<8;r++){this.makeImpl(!0,r);var o=f.getLostPoint(this);(0==r||t>o)&&(t=o,e=r)}return e},createMovieClip:function(t,e,r){var o=t.createEmptyMovieClip(e,r);this.make();for(var n=0;n>r&1);this.modules[Math.floor(r/3)][r%3+this.moduleCount-8-3]=o}for(var r=0;r<18;r++){var o=!t&&1==(e>>r&1);this.modules[r%3+this.moduleCount-8-3][Math.floor(r/3)]=o}},setupTypeInfo:function(t,e){for(var r=this.errorCorrectLevel<<3|e,o=f.getBCHTypeInfo(r),n=0;n<15;n++){var i=!t&&1==(o>>n&1);n<6?this.modules[n][8]=i:n<8?this.modules[n+1][8]=i:this.modules[this.moduleCount-15+n][8]=i}for(var n=0;n<15;n++){var i=!t&&1==(o>>n&1);n<8?this.modules[8][this.moduleCount-n-1]=i:n<9?this.modules[8][15-n-1+1]=i:this.modules[8][15-n-1]=i}this.modules[this.moduleCount-8][8]=!t},mapData:function(t,e){for(var r=-1,o=this.moduleCount-1,n=7,i=0,a=this.moduleCount-1;a>0;a-=2)for(6==a&&a--;;){for(var u=0;u<2;u++)if(null==this.modules[o][a-u]){var s=!1;i>>n&1));var h=f.getMask(e,o,a-u);h&&(s=!s),this.modules[o][a-u]=s,n--,-1==n&&(i++,n=7)}if((o+=r)<0||this.moduleCount<=o){o-=r,r=-r;break}}}},o.PAD0=236,o.PAD1=17,o.createData=function(t,e,r){for(var n=i.getRSBlocks(t,e),u=new a,s=0;s8*l)throw new Error("code length overflow. ("+u.getLengthInBits()+">"+8*l+")");for(u.getLengthInBits()+4<=8*l&&u.put(0,4);u.getLengthInBits()%8!=0;)u.putBit(!1);for(;;){if(u.getLengthInBits()>=8*l)break;if(u.put(o.PAD0,8),u.getLengthInBits()>=8*l)break;u.put(o.PAD1,8)}return o.createBytes(u,n)},o.createBytes=function(t,e){for(var r=0,o=0,i=0,a=new Array(e.length),u=new Array(e.length),s=0;s=0?m.get(v):0}}for(var p=0,g=0;g=0;)e^=f.G15<=0;)e^=f.G18<>>=1;return e},getPatternPosition:function(t){return f.PATTERN_POSITION_TABLE[t-1]},getMask:function(t,e,r){switch(t){case h.PATTERN000:return(e+r)%2==0;case h.PATTERN001:return e%2==0;case h.PATTERN010:return r%3==0;case h.PATTERN011:return(e+r)%3==0;case h.PATTERN100:return(Math.floor(e/2)+Math.floor(r/3))%2==0;case h.PATTERN101:return e*r%2+e*r%3==0;case h.PATTERN110:return(e*r%2+e*r%3)%2==0;case h.PATTERN111:return(e*r%3+(e+r)%2)%2==0;default:throw new Error("bad maskPattern:"+t)}},getErrorCorrectPolynomial:function(t){for(var e=new n([1],0),r=0;r5&&(r+=3+i-5)}for(var o=0;o=256;)t-=255;return l.EXP_TABLE[t]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},g=0;g<8;g++)l.EXP_TABLE[g]=1<>>7-t%8&1)},put:function(t,e){for(var r=0;r>>e-r-1&1))},getLengthInBits:function(){return this.length},putBit:function(t){var e=Math.floor(this.length/8);this.buffer.length<=e&&this.buffer.push(0),t&&(this.buffer[e]|=128>>>this.length%8),this.length++}},t.exports=o},function(t,e,r){function o(t,e){var r=JSON.parse(JSON.stringify(t));e&&"object"==typeof e||(e={});for(var o in e)e.hasOwnProperty(o)&&(r[o]=e[o]);return r}function n(t){var e,r,o,n;for(e="",o=t.length,r=0;r=1&&n<=127?e+=t.charAt(r):n>2047?(e+=String.fromCharCode(224|n>>12&15),e+=String.fromCharCode(128|n>>6&63),e+=String.fromCharCode(128|n>>0&63)):(e+=String.fromCharCode(192|n>>6&31),e+=String.fromCharCode(128|n>>0&63));return e}var i=r(0),a={L:1,M:0,Q:3,H:2},u={width:256,height:256,typeNumber:-1,correctLevel:a.H,background:"#ffffff",foreground:"#000000"},s=function(t,e){this.options=o(u,e),this.container=t};s.prototype.make=function(t){var e=this.options,r=this.container;t=n(t);var o=this.createCanvas(t,e),i=o.toDataURL(),a=document.createElement("img");a.style.height="100%",a.style.width="100%",a.setAttribute("src",i),r.innerHTML="",r.appendChild(a)},s.prototype.createCanvas=function(t,e){var r=new i(e.typeNumber,e.correctLevel);r.addData(t),r.make();var o=document.createElement("canvas");o.width=e.width,o.height=e.height;for(var n=o.getContext("2d"),a=e.width/r.getModuleCount(),u=e.height/r.getModuleCount(),s=0;s= 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 | 1239 | module.exports = QRCode; --------------------------------------------------------------------------------