├── demo ├── demo.png └── weapp-demo │ ├── pages │ ├── index │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.js │ │ └── index.wxss │ └── logs │ │ ├── logs.json │ │ ├── logs.wxss │ │ ├── logs.wxml │ │ └── logs.js │ ├── app.wxss │ ├── app.json │ ├── utils │ ├── util.js │ └── weapp-qrcode.js │ ├── project.config.json │ └── app.js ├── README.md └── weapp-qrcode.js /demo/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pudon/weapp-qrcode-base64/HEAD/demo/demo.png -------------------------------------------------------------------------------- /demo/weapp-demo/pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "二维码页面" 3 | } -------------------------------------------------------------------------------- /demo/weapp-demo/pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志" 3 | } -------------------------------------------------------------------------------- /demo/weapp-demo/pages/logs/logs.wxss: -------------------------------------------------------------------------------- 1 | .log-list { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 40rpx; 5 | } 6 | .log-item { 7 | margin: 10rpx; 8 | } 9 | -------------------------------------------------------------------------------- /demo/weapp-demo/app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | padding: 50rpx 20rpx; 7 | box-sizing: border-box; 8 | } 9 | -------------------------------------------------------------------------------- /demo/weapp-demo/pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/weapp-demo/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages":[ 3 | "pages/index/index", 4 | "pages/logs/logs" 5 | ], 6 | "window":{ 7 | "backgroundTextStyle":"light", 8 | "navigationBarBackgroundColor": "#f5f5f5", 9 | "navigationBarTitleText": "WeChat", 10 | "navigationBarTextStyle":"black" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /demo/weapp-demo/pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | //logs.js 2 | const util = require('../../utils/util.js') 3 | 4 | Page({ 5 | data: { 6 | logs: [] 7 | }, 8 | onLoad: function () { 9 | this.setData({ 10 | logs: (wx.getStorageSync('logs') || []).map(log => { 11 | return util.formatTime(new Date(log)) 12 | }) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /demo/weapp-demo/utils/util.js: -------------------------------------------------------------------------------- 1 | const formatTime = date => { 2 | const year = date.getFullYear() 3 | const month = date.getMonth() + 1 4 | const day = date.getDate() 5 | const hour = date.getHours() 6 | const minute = date.getMinutes() 7 | const second = date.getSeconds() 8 | 9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 10 | } 11 | 12 | const formatNumber = n => { 13 | n = n.toString() 14 | return n[1] ? n : '0' + n 15 | } 16 | 17 | module.exports = { 18 | formatTime: formatTime 19 | } 20 | -------------------------------------------------------------------------------- /demo/weapp-demo/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo/weapp-demo/pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | //获取应用实例 3 | const app = getApp() 4 | const QR = require('../../utils/weapp-qrcode.js') 5 | 6 | Page({ 7 | data: { 8 | motto: 'Hello World', 9 | qrcodeURL: "", 10 | codeText: "github.com/Pudon", 11 | }, 12 | onLoad: function () { 13 | this.drawImg(); 14 | }, 15 | setText: function (e) { 16 | this.setData({ 17 | codeText: e.detail.value 18 | }) 19 | }, 20 | drawImg: function () { 21 | console.log(this.data.codeText); 22 | var imgData = QR.drawImg(this.data.codeText, { 23 | typeNumber: 4, 24 | errorCorrectLevel: 'M', 25 | size: 500 26 | }) 27 | this.setData({ 28 | qrcodeURL: imgData 29 | }) 30 | } 31 | }) 32 | -------------------------------------------------------------------------------- /demo/weapp-demo/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | page { 3 | height: 100%; 4 | } 5 | .container { 6 | background: #f5f5f5; 7 | } 8 | .qrcode-wrap { 9 | background: #fff; 10 | border-radius: 33rpx; 11 | } 12 | .qrcode-container { 13 | padding-top: 80rpx; 14 | padding-bottom: 50rpx; 15 | text-align: center; 16 | } 17 | .qrcode-img { 18 | width: 500rpx; 19 | height: 500rpx; 20 | } 21 | .text-container { 22 | padding: 50rpx; 23 | display: flex; 24 | align-items: center; 25 | justify-content: space-between; 26 | border-top: 2rpx solid #f0f0f0; 27 | } 28 | .text-input { 29 | border: 2rpx solid #f5f5f5; 30 | border-radius: 10rpx; 31 | margin-right: 10rpx; 32 | padding: 20rpx; 33 | } 34 | .change-btn { 35 | width: 200rpx; 36 | color: #fff; 37 | padding: 0 50rpx; 38 | } -------------------------------------------------------------------------------- /demo/weapp-demo/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true 12 | }, 13 | "compileType": "miniprogram", 14 | "libVersion": "2.2.5", 15 | "appid": "wxd523c798b0abef2b", 16 | "projectname": "%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%94%9F%E6%88%90%E4%BA%8C%E7%BB%B4%E7%A0%81", 17 | "debugOptions": { 18 | "hidedInDevtools": [] 19 | }, 20 | "isGameTourist": false, 21 | "condition": { 22 | "search": { 23 | "current": -1, 24 | "list": [] 25 | }, 26 | "conversation": { 27 | "current": -1, 28 | "list": [] 29 | }, 30 | "game": { 31 | "currentL": -1, 32 | "list": [] 33 | }, 34 | "miniprogram": { 35 | "current": -1, 36 | "list": [] 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # weapp-qrcode 2 | Generating the QR code in the form of Base64 3 | 微信小程序生成二维码的插件,基于base64编码输出二维码,不依赖canvas 理论支持全平台 4 | >PS: 主要在`node-yaqrcode`项目基础上进行改造适应微信小程序 5 | 6 | ## 说明 7 | 只需要在 wxml 文件中增加个`image`标签动态引用base64编码即可 8 | ``` 9 | 10 | ``` 11 | 12 | 使用NPM 13 | ``` 14 | npm install qrcode-base64 15 | ``` 16 | 17 | JS调用例子: 18 | ``` 19 | import QR from 'qrcode-base64' 20 | 21 | var imgData = QR.drawImg(this.data.codeText, { 22 | typeNumber: 4, 23 | errorCorrectLevel: 'M', 24 | size: 500 25 | }) 26 | // 返回输出base64编码imgData 27 | 28 | ``` 29 | 30 | JS调用例子: 31 | ``` 32 | const QR = require('../../utils/weapp-qrcode.js') 33 | var imgData = QR.drawImg(this.data.codeText, { 34 | typeNumber: 4, 35 | errorCorrectLevel: 'M', 36 | size: 500 37 | }) 38 | // 返回输出base64编码imgData 39 | 40 | ``` 41 | 42 | ## DEMO示例图 43 | 44 | ![demo-img](./demo/demo.png) 45 | 46 | ## TODO 47 | 1. 组件化,适应 `mpvue` , `wepy` 48 | 2. 更多配置项,灵活多样 49 | 3. 样式自定义化,增加更丰富的样式 50 | -------------------------------------------------------------------------------- /demo/weapp-demo/app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | // 展示本地存储能力 5 | var logs = wx.getStorageSync('logs') || [] 6 | logs.unshift(Date.now()) 7 | wx.setStorageSync('logs', logs) 8 | 9 | // 登录 10 | wx.login({ 11 | success: res => { 12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 13 | } 14 | }) 15 | // 获取用户信息 16 | wx.getSetting({ 17 | success: res => { 18 | if (res.authSetting['scope.userInfo']) { 19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 20 | wx.getUserInfo({ 21 | success: res => { 22 | // 可以将 res 发送给后台解码出 unionId 23 | this.globalData.userInfo = res.userInfo 24 | 25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 26 | // 所以此处加入 callback 以防止这种情况 27 | if (this.userInfoReadyCallback) { 28 | this.userInfoReadyCallback(res) 29 | } 30 | } 31 | }) 32 | } 33 | } 34 | }) 35 | }, 36 | globalData: { 37 | userInfo: null 38 | } 39 | }) -------------------------------------------------------------------------------- /weapp-qrcode.js: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------- 2 | // 3 | // QR Code Generator for JavaScript 4 | // 5 | // Copyright (c) 2009 Kazuhiko Arase 6 | // 7 | // URL: http://www.d-project.com/ 8 | // 9 | // Licensed under the MIT license: 10 | // http://www.opensource.org/licenses/mit-license.php 11 | // 12 | // The word 'QR Code' is registered trademark of 13 | // DENSO WAVE INCORPORATED 14 | // http://www.denso-wave.com/qrcode/faqpatent-e.html 15 | // 16 | //--------------------------------------------------------------------- 17 | 18 | //---------------微信小程序基于base64生成二维码插件修改------------------- 19 | /* 20 | * @Modified: Pudon 21 | * @demoURL: https://github.com/Pudon/weapp-qrcode 22 | * @Date: 2018-09-11 14:00:05 23 | * @Last Modified by: Pudon 24 | * @Last Modified time: 2018-09-12 16:33:19 25 | */ 26 | //--------------------------------------------------------------------- 27 | 28 | /** 29 | * qrcode 30 | * @param typeNumber 1 to 40 31 | * @param errorCorrectLevel 'L','M','Q','H' 32 | */ 33 | var qrcode = function(typeNumber, errorCorrectLevel) { 34 | 35 | var PAD0 = 0xEC; 36 | var PAD1 = 0x11; 37 | 38 | var _typeNumber = typeNumber; 39 | var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel]; 40 | var _modules = null; 41 | var _moduleCount = 0; 42 | var _dataCache = null; 43 | var _dataList = new Array(); 44 | 45 | var _this = {}; 46 | 47 | var makeImpl = function(test, maskPattern) { 48 | 49 | _moduleCount = _typeNumber * 4 + 17; 50 | _modules = function(moduleCount) { 51 | var modules = new Array(moduleCount); 52 | for (var row = 0; row < moduleCount; row += 1) { 53 | modules[row] = new Array(moduleCount); 54 | for (var col = 0; col < moduleCount; col += 1) { 55 | modules[row][col] = null; 56 | } 57 | } 58 | return modules; 59 | }(_moduleCount); 60 | 61 | setupPositionProbePattern(0, 0); 62 | setupPositionProbePattern(_moduleCount - 7, 0); 63 | setupPositionProbePattern(0, _moduleCount - 7); 64 | setupPositionAdjustPattern(); 65 | setupTimingPattern(); 66 | setupTypeInfo(test, maskPattern); 67 | 68 | if (_typeNumber >= 7) { 69 | setupTypeNumber(test); 70 | } 71 | 72 | if (_dataCache == null) { 73 | _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList); 74 | } 75 | 76 | mapData(_dataCache, maskPattern); 77 | }; 78 | 79 | var setupPositionProbePattern = function(row, col) { 80 | 81 | for (var r = -1; r <= 7; r += 1) { 82 | 83 | if (row + r <= -1 || _moduleCount <= row + r) continue; 84 | 85 | for (var c = -1; c <= 7; c += 1) { 86 | 87 | if (col + c <= -1 || _moduleCount <= col + c) continue; 88 | 89 | if ( (0 <= r && r <= 6 && (c == 0 || c == 6) ) 90 | || (0 <= c && c <= 6 && (r == 0 || r == 6) ) 91 | || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) { 92 | _modules[row + r][col + c] = true; 93 | } else { 94 | _modules[row + r][col + c] = false; 95 | } 96 | } 97 | } 98 | }; 99 | 100 | var getBestMaskPattern = function() { 101 | 102 | var minLostPoint = 0; 103 | var pattern = 0; 104 | 105 | for (var i = 0; i < 8; i += 1) { 106 | 107 | makeImpl(true, i); 108 | 109 | var lostPoint = QRUtil.getLostPoint(_this); 110 | 111 | if (i == 0 || minLostPoint > lostPoint) { 112 | minLostPoint = lostPoint; 113 | pattern = i; 114 | } 115 | } 116 | 117 | return pattern; 118 | }; 119 | 120 | var setupTimingPattern = function() { 121 | 122 | for (var r = 8; r < _moduleCount - 8; r += 1) { 123 | if (_modules[r][6] != null) { 124 | continue; 125 | } 126 | _modules[r][6] = (r % 2 == 0); 127 | } 128 | 129 | for (var c = 8; c < _moduleCount - 8; c += 1) { 130 | if (_modules[6][c] != null) { 131 | continue; 132 | } 133 | _modules[6][c] = (c % 2 == 0); 134 | } 135 | }; 136 | 137 | var setupPositionAdjustPattern = function() { 138 | 139 | var pos = QRUtil.getPatternPosition(_typeNumber); 140 | 141 | for (var i = 0; i < pos.length; i += 1) { 142 | 143 | for (var j = 0; j < pos.length; j += 1) { 144 | 145 | var row = pos[i]; 146 | var col = pos[j]; 147 | 148 | if (_modules[row][col] != null) { 149 | continue; 150 | } 151 | 152 | for (var r = -2; r <= 2; r += 1) { 153 | 154 | for (var c = -2; c <= 2; c += 1) { 155 | 156 | if (r == -2 || r == 2 || c == -2 || c == 2 157 | || (r == 0 && c == 0) ) { 158 | _modules[row + r][col + c] = true; 159 | } else { 160 | _modules[row + r][col + c] = false; 161 | } 162 | } 163 | } 164 | } 165 | } 166 | }; 167 | 168 | var setupTypeNumber = function(test) { 169 | 170 | var bits = QRUtil.getBCHTypeNumber(_typeNumber); 171 | 172 | for (var i = 0; i < 18; i += 1) { 173 | var mod = (!test && ( (bits >> i) & 1) == 1); 174 | _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod; 175 | } 176 | 177 | for (var i = 0; i < 18; i += 1) { 178 | var mod = (!test && ( (bits >> i) & 1) == 1); 179 | _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod; 180 | } 181 | }; 182 | 183 | var setupTypeInfo = function(test, maskPattern) { 184 | 185 | var data = (_errorCorrectLevel << 3) | maskPattern; 186 | var bits = QRUtil.getBCHTypeInfo(data); 187 | 188 | // vertical 189 | for (var i = 0; i < 15; i += 1) { 190 | 191 | var mod = (!test && ( (bits >> i) & 1) == 1); 192 | 193 | if (i < 6) { 194 | _modules[i][8] = mod; 195 | } else if (i < 8) { 196 | _modules[i + 1][8] = mod; 197 | } else { 198 | _modules[_moduleCount - 15 + i][8] = mod; 199 | } 200 | } 201 | 202 | // horizontal 203 | for (var i = 0; i < 15; i += 1) { 204 | 205 | var mod = (!test && ( (bits >> i) & 1) == 1); 206 | 207 | if (i < 8) { 208 | _modules[8][_moduleCount - i - 1] = mod; 209 | } else if (i < 9) { 210 | _modules[8][15 - i - 1 + 1] = mod; 211 | } else { 212 | _modules[8][15 - i - 1] = mod; 213 | } 214 | } 215 | 216 | // fixed module 217 | _modules[_moduleCount - 8][8] = (!test); 218 | }; 219 | 220 | var mapData = function(data, maskPattern) { 221 | 222 | var inc = -1; 223 | var row = _moduleCount - 1; 224 | var bitIndex = 7; 225 | var byteIndex = 0; 226 | var maskFunc = QRUtil.getMaskFunction(maskPattern); 227 | 228 | for (var col = _moduleCount - 1; col > 0; col -= 2) { 229 | 230 | if (col == 6) col -= 1; 231 | 232 | while (true) { 233 | 234 | for (var c = 0; c < 2; c += 1) { 235 | 236 | if (_modules[row][col - c] == null) { 237 | 238 | var dark = false; 239 | 240 | if (byteIndex < data.length) { 241 | dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1); 242 | } 243 | 244 | var mask = maskFunc(row, col - c); 245 | 246 | if (mask) { 247 | dark = !dark; 248 | } 249 | 250 | _modules[row][col - c] = dark; 251 | bitIndex -= 1; 252 | 253 | if (bitIndex == -1) { 254 | byteIndex += 1; 255 | bitIndex = 7; 256 | } 257 | } 258 | } 259 | 260 | row += inc; 261 | 262 | if (row < 0 || _moduleCount <= row) { 263 | row -= inc; 264 | inc = -inc; 265 | break; 266 | } 267 | } 268 | } 269 | }; 270 | 271 | var createBytes = function(buffer, rsBlocks) { 272 | 273 | var offset = 0; 274 | 275 | var maxDcCount = 0; 276 | var maxEcCount = 0; 277 | 278 | var dcdata = new Array(rsBlocks.length); 279 | var ecdata = new Array(rsBlocks.length); 280 | 281 | for (var r = 0; r < rsBlocks.length; r += 1) { 282 | 283 | var dcCount = rsBlocks[r].dataCount; 284 | var ecCount = rsBlocks[r].totalCount - dcCount; 285 | 286 | maxDcCount = Math.max(maxDcCount, dcCount); 287 | maxEcCount = Math.max(maxEcCount, ecCount); 288 | 289 | dcdata[r] = new Array(dcCount); 290 | 291 | for (var i = 0; i < dcdata[r].length; i += 1) { 292 | dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset]; 293 | } 294 | offset += dcCount; 295 | 296 | var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); 297 | var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1); 298 | 299 | var modPoly = rawPoly.mod(rsPoly); 300 | ecdata[r] = new Array(rsPoly.getLength() - 1); 301 | for (var i = 0; i < ecdata[r].length; i += 1) { 302 | var modIndex = i + modPoly.getLength() - ecdata[r].length; 303 | ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0; 304 | } 305 | } 306 | 307 | var totalCodeCount = 0; 308 | for (var i = 0; i < rsBlocks.length; i += 1) { 309 | totalCodeCount += rsBlocks[i].totalCount; 310 | } 311 | 312 | var data = new Array(totalCodeCount); 313 | var index = 0; 314 | 315 | for (var i = 0; i < maxDcCount; i += 1) { 316 | for (var r = 0; r < rsBlocks.length; r += 1) { 317 | if (i < dcdata[r].length) { 318 | data[index] = dcdata[r][i]; 319 | index += 1; 320 | } 321 | } 322 | } 323 | 324 | for (var i = 0; i < maxEcCount; i += 1) { 325 | for (var r = 0; r < rsBlocks.length; r += 1) { 326 | if (i < ecdata[r].length) { 327 | data[index] = ecdata[r][i]; 328 | index += 1; 329 | } 330 | } 331 | } 332 | 333 | return data; 334 | }; 335 | 336 | var createData = function(typeNumber, errorCorrectLevel, dataList) { 337 | 338 | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); 339 | 340 | var buffer = qrBitBuffer(); 341 | 342 | for (var i = 0; i < dataList.length; i += 1) { 343 | var data = dataList[i]; 344 | buffer.put(data.getMode(), 4); 345 | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) ); 346 | data.write(buffer); 347 | } 348 | 349 | // calc num max data. 350 | var totalDataCount = 0; 351 | for (var i = 0; i < rsBlocks.length; i += 1) { 352 | totalDataCount += rsBlocks[i].dataCount; 353 | } 354 | 355 | if (buffer.getLengthInBits() > totalDataCount * 8) { 356 | throw new Error('code length overflow. (' 357 | + buffer.getLengthInBits() 358 | + '>' 359 | + totalDataCount * 8 360 | + ')'); 361 | } 362 | 363 | // end code 364 | if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { 365 | buffer.put(0, 4); 366 | } 367 | 368 | // padding 369 | while (buffer.getLengthInBits() % 8 != 0) { 370 | buffer.putBit(false); 371 | } 372 | 373 | // padding 374 | while (true) { 375 | 376 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 377 | break; 378 | } 379 | buffer.put(PAD0, 8); 380 | 381 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 382 | break; 383 | } 384 | buffer.put(PAD1, 8); 385 | } 386 | 387 | return createBytes(buffer, rsBlocks); 388 | }; 389 | 390 | _this.addData = function(data) { 391 | var newData = qr8BitByte(data); 392 | _dataList.push(newData); 393 | _dataCache = null; 394 | }; 395 | 396 | _this.isDark = function(row, col) { 397 | if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) { 398 | throw new Error(row + ',' + col); 399 | } 400 | return _modules[row][col]; 401 | }; 402 | 403 | _this.getModuleCount = function() { 404 | return _moduleCount; 405 | }; 406 | 407 | _this.make = function() { 408 | makeImpl(false, getBestMaskPattern() ); 409 | }; 410 | 411 | _this.createTableTag = function(cellSize, margin) { 412 | 413 | cellSize = cellSize || 2; 414 | margin = (typeof margin == 'undefined')? cellSize * 4 : margin; 415 | 416 | var qrHtml = ''; 417 | 418 | qrHtml += ''; 423 | qrHtml += ''; 424 | 425 | for (var r = 0; r < _this.getModuleCount(); r += 1) { 426 | 427 | qrHtml += ''; 428 | 429 | for (var c = 0; c < _this.getModuleCount(); c += 1) { 430 | qrHtml += ''; 443 | } 444 | 445 | qrHtml += ''; 446 | qrHtml += '
'; 440 | } 441 | 442 | qrHtml += '
'; 447 | 448 | return qrHtml; 449 | }; 450 | 451 | _this.createImgTag = function(cellSize, margin, size) { 452 | 453 | cellSize = cellSize || 2; 454 | margin = (typeof margin == 'undefined')? cellSize * 4 : margin; 455 | 456 | var min = margin; 457 | var max = _this.getModuleCount() * cellSize + margin; 458 | 459 | return createImgTag(size, size, function(x, y) { 460 | if (min <= x && x < max && min <= y && y < max) { 461 | var c = Math.floor( (x - min) / cellSize); 462 | var r = Math.floor( (y - min) / cellSize); 463 | return _this.isDark(r, c)? 0 : 1; 464 | } else { 465 | return 1; 466 | } 467 | } ); 468 | }; 469 | 470 | return _this; 471 | }; 472 | 473 | //--------------------------------------------------------------------- 474 | // qrcode.stringToBytes 475 | //--------------------------------------------------------------------- 476 | 477 | qrcode.stringToBytes = function(s) { 478 | var bytes = new Array(); 479 | for (var i = 0; i < s.length; i += 1) { 480 | var c = s.charCodeAt(i); 481 | bytes.push(c & 0xff); 482 | } 483 | return bytes; 484 | }; 485 | 486 | //--------------------------------------------------------------------- 487 | // qrcode.createStringToBytes 488 | //--------------------------------------------------------------------- 489 | 490 | /** 491 | * @param unicodeData base64 string of byte array. 492 | * [16bit Unicode],[16bit Bytes], ... 493 | * @param numChars 494 | */ 495 | qrcode.createStringToBytes = function(unicodeData, numChars) { 496 | 497 | // create conversion map. 498 | 499 | var unicodeMap = function() { 500 | 501 | var bin = base64DecodeInputStream(unicodeData); 502 | var read = function() { 503 | var b = bin.read(); 504 | if (b == -1) throw new Error(); 505 | return b; 506 | }; 507 | 508 | var count = 0; 509 | var unicodeMap = {}; 510 | while (true) { 511 | var b0 = bin.read(); 512 | if (b0 == -1) break; 513 | var b1 = read(); 514 | var b2 = read(); 515 | var b3 = read(); 516 | var k = String.fromCharCode( (b0 << 8) | b1); 517 | var v = (b2 << 8) | b3; 518 | unicodeMap[k] = v; 519 | count += 1; 520 | } 521 | if (count != numChars) { 522 | throw new Error(count + ' != ' + numChars); 523 | } 524 | 525 | return unicodeMap; 526 | }(); 527 | 528 | var unknownChar = '?'.charCodeAt(0); 529 | 530 | return function(s) { 531 | var bytes = new Array(); 532 | for (var i = 0; i < s.length; i += 1) { 533 | var c = s.charCodeAt(i); 534 | if (c < 128) { 535 | bytes.push(c); 536 | } else { 537 | var b = unicodeMap[s.charAt(i)]; 538 | if (typeof b == 'number') { 539 | if ( (b & 0xff) == b) { 540 | // 1byte 541 | bytes.push(b); 542 | } else { 543 | // 2bytes 544 | bytes.push(b >>> 8); 545 | bytes.push(b & 0xff); 546 | } 547 | } else { 548 | bytes.push(unknownChar); 549 | } 550 | } 551 | } 552 | return bytes; 553 | }; 554 | }; 555 | 556 | //--------------------------------------------------------------------- 557 | // QRMode 558 | //--------------------------------------------------------------------- 559 | 560 | var QRMode = { 561 | MODE_NUMBER : 1 << 0, 562 | MODE_ALPHA_NUM : 1 << 1, 563 | MODE_8BIT_BYTE : 1 << 2, 564 | MODE_KANJI : 1 << 3 565 | }; 566 | 567 | //--------------------------------------------------------------------- 568 | // QRErrorCorrectLevel 569 | //--------------------------------------------------------------------- 570 | 571 | var QRErrorCorrectLevel = { 572 | L : 1, 573 | M : 0, 574 | Q : 3, 575 | H : 2 576 | }; 577 | 578 | //--------------------------------------------------------------------- 579 | // QRMaskPattern 580 | //--------------------------------------------------------------------- 581 | 582 | var QRMaskPattern = { 583 | PATTERN000 : 0, 584 | PATTERN001 : 1, 585 | PATTERN010 : 2, 586 | PATTERN011 : 3, 587 | PATTERN100 : 4, 588 | PATTERN101 : 5, 589 | PATTERN110 : 6, 590 | PATTERN111 : 7 591 | }; 592 | 593 | //--------------------------------------------------------------------- 594 | // QRUtil 595 | //--------------------------------------------------------------------- 596 | 597 | var QRUtil = function() { 598 | 599 | var PATTERN_POSITION_TABLE = [ 600 | [], 601 | [6, 18], 602 | [6, 22], 603 | [6, 26], 604 | [6, 30], 605 | [6, 34], 606 | [6, 22, 38], 607 | [6, 24, 42], 608 | [6, 26, 46], 609 | [6, 28, 50], 610 | [6, 30, 54], 611 | [6, 32, 58], 612 | [6, 34, 62], 613 | [6, 26, 46, 66], 614 | [6, 26, 48, 70], 615 | [6, 26, 50, 74], 616 | [6, 30, 54, 78], 617 | [6, 30, 56, 82], 618 | [6, 30, 58, 86], 619 | [6, 34, 62, 90], 620 | [6, 28, 50, 72, 94], 621 | [6, 26, 50, 74, 98], 622 | [6, 30, 54, 78, 102], 623 | [6, 28, 54, 80, 106], 624 | [6, 32, 58, 84, 110], 625 | [6, 30, 58, 86, 114], 626 | [6, 34, 62, 90, 118], 627 | [6, 26, 50, 74, 98, 122], 628 | [6, 30, 54, 78, 102, 126], 629 | [6, 26, 52, 78, 104, 130], 630 | [6, 30, 56, 82, 108, 134], 631 | [6, 34, 60, 86, 112, 138], 632 | [6, 30, 58, 86, 114, 142], 633 | [6, 34, 62, 90, 118, 146], 634 | [6, 30, 54, 78, 102, 126, 150], 635 | [6, 24, 50, 76, 102, 128, 154], 636 | [6, 28, 54, 80, 106, 132, 158], 637 | [6, 32, 58, 84, 110, 136, 162], 638 | [6, 26, 54, 82, 110, 138, 166], 639 | [6, 30, 58, 86, 114, 142, 170] 640 | ]; 641 | var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); 642 | var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0); 643 | var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1); 644 | 645 | var _this = {}; 646 | 647 | var getBCHDigit = function(data) { 648 | var digit = 0; 649 | while (data != 0) { 650 | digit += 1; 651 | data >>>= 1; 652 | } 653 | return digit; 654 | }; 655 | 656 | _this.getBCHTypeInfo = function(data) { 657 | var d = data << 10; 658 | while (getBCHDigit(d) - getBCHDigit(G15) >= 0) { 659 | d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) ); 660 | } 661 | return ( (data << 10) | d) ^ G15_MASK; 662 | }; 663 | 664 | _this.getBCHTypeNumber = function(data) { 665 | var d = data << 12; 666 | while (getBCHDigit(d) - getBCHDigit(G18) >= 0) { 667 | d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) ); 668 | } 669 | return (data << 12) | d; 670 | }; 671 | 672 | _this.getPatternPosition = function(typeNumber) { 673 | return PATTERN_POSITION_TABLE[typeNumber - 1]; 674 | }; 675 | 676 | _this.getMaskFunction = function(maskPattern) { 677 | 678 | switch (maskPattern) { 679 | 680 | case QRMaskPattern.PATTERN000 : 681 | return function(i, j) { return (i + j) % 2 == 0; }; 682 | case QRMaskPattern.PATTERN001 : 683 | return function(i, j) { return i % 2 == 0; }; 684 | case QRMaskPattern.PATTERN010 : 685 | return function(i, j) { return j % 3 == 0; }; 686 | case QRMaskPattern.PATTERN011 : 687 | return function(i, j) { return (i + j) % 3 == 0; }; 688 | case QRMaskPattern.PATTERN100 : 689 | return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; }; 690 | case QRMaskPattern.PATTERN101 : 691 | return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; }; 692 | case QRMaskPattern.PATTERN110 : 693 | return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; }; 694 | case QRMaskPattern.PATTERN111 : 695 | return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; }; 696 | 697 | default : 698 | throw new Error('bad maskPattern:' + maskPattern); 699 | } 700 | }; 701 | 702 | _this.getErrorCorrectPolynomial = function(errorCorrectLength) { 703 | var a = qrPolynomial([1], 0); 704 | for (var i = 0; i < errorCorrectLength; i += 1) { 705 | a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) ); 706 | } 707 | return a; 708 | }; 709 | 710 | _this.getLengthInBits = function(mode, type) { 711 | 712 | if (1 <= type && type < 10) { 713 | 714 | // 1 - 9 715 | 716 | switch(mode) { 717 | case QRMode.MODE_NUMBER : return 10; 718 | case QRMode.MODE_ALPHA_NUM : return 9; 719 | case QRMode.MODE_8BIT_BYTE : return 8; 720 | case QRMode.MODE_KANJI : return 8; 721 | default : 722 | throw new Error('mode:' + mode); 723 | } 724 | 725 | } else if (type < 27) { 726 | 727 | // 10 - 26 728 | 729 | switch(mode) { 730 | case QRMode.MODE_NUMBER : return 12; 731 | case QRMode.MODE_ALPHA_NUM : return 11; 732 | case QRMode.MODE_8BIT_BYTE : return 16; 733 | case QRMode.MODE_KANJI : return 10; 734 | default : 735 | throw new Error('mode:' + mode); 736 | } 737 | 738 | } else if (type < 41) { 739 | 740 | // 27 - 40 741 | 742 | switch(mode) { 743 | case QRMode.MODE_NUMBER : return 14; 744 | case QRMode.MODE_ALPHA_NUM : return 13; 745 | case QRMode.MODE_8BIT_BYTE : return 16; 746 | case QRMode.MODE_KANJI : return 12; 747 | default : 748 | throw new Error('mode:' + mode); 749 | } 750 | 751 | } else { 752 | throw new Error('type:' + type); 753 | } 754 | }; 755 | 756 | _this.getLostPoint = function(qrcode) { 757 | 758 | var moduleCount = qrcode.getModuleCount(); 759 | 760 | var lostPoint = 0; 761 | 762 | // LEVEL1 763 | 764 | for (var row = 0; row < moduleCount; row += 1) { 765 | for (var col = 0; col < moduleCount; col += 1) { 766 | 767 | var sameCount = 0; 768 | var dark = qrcode.isDark(row, col); 769 | 770 | for (var r = -1; r <= 1; r += 1) { 771 | 772 | if (row + r < 0 || moduleCount <= row + r) { 773 | continue; 774 | } 775 | 776 | for (var c = -1; c <= 1; c += 1) { 777 | 778 | if (col + c < 0 || moduleCount <= col + c) { 779 | continue; 780 | } 781 | 782 | if (r == 0 && c == 0) { 783 | continue; 784 | } 785 | 786 | if (dark == qrcode.isDark(row + r, col + c) ) { 787 | sameCount += 1; 788 | } 789 | } 790 | } 791 | 792 | if (sameCount > 5) { 793 | lostPoint += (3 + sameCount - 5); 794 | } 795 | } 796 | }; 797 | 798 | // LEVEL2 799 | 800 | for (var row = 0; row < moduleCount - 1; row += 1) { 801 | for (var col = 0; col < moduleCount - 1; col += 1) { 802 | var count = 0; 803 | if (qrcode.isDark(row, col) ) count += 1; 804 | if (qrcode.isDark(row + 1, col) ) count += 1; 805 | if (qrcode.isDark(row, col + 1) ) count += 1; 806 | if (qrcode.isDark(row + 1, col + 1) ) count += 1; 807 | if (count == 0 || count == 4) { 808 | lostPoint += 3; 809 | } 810 | } 811 | } 812 | 813 | // LEVEL3 814 | 815 | for (var row = 0; row < moduleCount; row += 1) { 816 | for (var col = 0; col < moduleCount - 6; col += 1) { 817 | if (qrcode.isDark(row, col) 818 | && !qrcode.isDark(row, col + 1) 819 | && qrcode.isDark(row, col + 2) 820 | && qrcode.isDark(row, col + 3) 821 | && qrcode.isDark(row, col + 4) 822 | && !qrcode.isDark(row, col + 5) 823 | && qrcode.isDark(row, col + 6) ) { 824 | lostPoint += 40; 825 | } 826 | } 827 | } 828 | 829 | for (var col = 0; col < moduleCount; col += 1) { 830 | for (var row = 0; row < moduleCount - 6; row += 1) { 831 | if (qrcode.isDark(row, col) 832 | && !qrcode.isDark(row + 1, col) 833 | && qrcode.isDark(row + 2, col) 834 | && qrcode.isDark(row + 3, col) 835 | && qrcode.isDark(row + 4, col) 836 | && !qrcode.isDark(row + 5, col) 837 | && qrcode.isDark(row + 6, col) ) { 838 | lostPoint += 40; 839 | } 840 | } 841 | } 842 | 843 | // LEVEL4 844 | 845 | var darkCount = 0; 846 | 847 | for (var col = 0; col < moduleCount; col += 1) { 848 | for (var row = 0; row < moduleCount; row += 1) { 849 | if (qrcode.isDark(row, col) ) { 850 | darkCount += 1; 851 | } 852 | } 853 | } 854 | 855 | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; 856 | lostPoint += ratio * 10; 857 | 858 | return lostPoint; 859 | }; 860 | 861 | return _this; 862 | }(); 863 | 864 | //--------------------------------------------------------------------- 865 | // QRMath 866 | //--------------------------------------------------------------------- 867 | 868 | var QRMath = function() { 869 | 870 | var EXP_TABLE = new Array(256); 871 | var LOG_TABLE = new Array(256); 872 | 873 | // initialize tables 874 | for (var i = 0; i < 8; i += 1) { 875 | EXP_TABLE[i] = 1 << i; 876 | } 877 | for (var i = 8; i < 256; i += 1) { 878 | EXP_TABLE[i] = EXP_TABLE[i - 4] 879 | ^ EXP_TABLE[i - 5] 880 | ^ EXP_TABLE[i - 6] 881 | ^ EXP_TABLE[i - 8]; 882 | } 883 | for (var i = 0; i < 255; i += 1) { 884 | LOG_TABLE[EXP_TABLE[i] ] = i; 885 | } 886 | 887 | var _this = {}; 888 | 889 | _this.glog = function(n) { 890 | 891 | if (n < 1) { 892 | throw new Error('glog(' + n + ')'); 893 | } 894 | 895 | return LOG_TABLE[n]; 896 | }; 897 | 898 | _this.gexp = function(n) { 899 | 900 | while (n < 0) { 901 | n += 255; 902 | } 903 | 904 | while (n >= 256) { 905 | n -= 255; 906 | } 907 | 908 | return EXP_TABLE[n]; 909 | }; 910 | 911 | return _this; 912 | }(); 913 | 914 | //--------------------------------------------------------------------- 915 | // qrPolynomial 916 | //--------------------------------------------------------------------- 917 | 918 | function qrPolynomial(num, shift) { 919 | 920 | if (typeof num.length == 'undefined') { 921 | throw new Error(num.length + '/' + shift); 922 | } 923 | 924 | var _num = function() { 925 | var offset = 0; 926 | while (offset < num.length && num[offset] == 0) { 927 | offset += 1; 928 | } 929 | var _num = new Array(num.length - offset + shift); 930 | for (var i = 0; i < num.length - offset; i += 1) { 931 | _num[i] = num[i + offset]; 932 | } 933 | return _num; 934 | }(); 935 | 936 | var _this = {}; 937 | 938 | _this.getAt = function(index) { 939 | return _num[index]; 940 | }; 941 | 942 | _this.getLength = function() { 943 | return _num.length; 944 | }; 945 | 946 | _this.multiply = function(e) { 947 | 948 | var num = new Array(_this.getLength() + e.getLength() - 1); 949 | 950 | for (var i = 0; i < _this.getLength(); i += 1) { 951 | for (var j = 0; j < e.getLength(); j += 1) { 952 | num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) ); 953 | } 954 | } 955 | 956 | return qrPolynomial(num, 0); 957 | }; 958 | 959 | _this.mod = function(e) { 960 | 961 | if (_this.getLength() - e.getLength() < 0) { 962 | return _this; 963 | } 964 | 965 | var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) ); 966 | 967 | var num = new Array(_this.getLength() ); 968 | for (var i = 0; i < _this.getLength(); i += 1) { 969 | num[i] = _this.getAt(i); 970 | } 971 | 972 | for (var i = 0; i < e.getLength(); i += 1) { 973 | num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio); 974 | } 975 | 976 | // recursive call 977 | return qrPolynomial(num, 0).mod(e); 978 | }; 979 | 980 | return _this; 981 | }; 982 | 983 | //--------------------------------------------------------------------- 984 | // QRRSBlock 985 | //--------------------------------------------------------------------- 986 | 987 | var QRRSBlock = function() { 988 | 989 | 990 | // [1: [L, M, Q, H], ..] 991 | var RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]]; 992 | 993 | var qrRSBlock = function(totalCount, dataCount) { 994 | var _this = {}; 995 | _this.totalCount = totalCount; 996 | _this.dataCount = dataCount; 997 | return _this; 998 | }; 999 | 1000 | var _this = {}; 1001 | 1002 | var getRsBlockTable = function(typeNumber, errorCorrectLevel) { 1003 | 1004 | switch(errorCorrectLevel) { 1005 | case QRErrorCorrectLevel.L : 1006 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; 1007 | case QRErrorCorrectLevel.M : 1008 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; 1009 | case QRErrorCorrectLevel.Q : 1010 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; 1011 | case QRErrorCorrectLevel.H : 1012 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; 1013 | default : 1014 | return undefined; 1015 | } 1016 | }; 1017 | 1018 | _this.getRSBlocks = function(typeNumber, errorCorrectLevel) { 1019 | 1020 | var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel); 1021 | 1022 | if (typeof rsBlock == 'undefined') { 1023 | throw new Error('bad rs block @ typeNumber:' + typeNumber + 1024 | '/errorCorrectLevel:' + errorCorrectLevel); 1025 | } 1026 | 1027 | var length = rsBlock.length / 3; 1028 | 1029 | var list = new Array(); 1030 | 1031 | for (var i = 0; i < length; i += 1) { 1032 | 1033 | var count = rsBlock[i * 3 + 0]; 1034 | var totalCount = rsBlock[i * 3 + 1]; 1035 | var dataCount = rsBlock[i * 3 + 2]; 1036 | 1037 | for (var j = 0; j < count; j += 1) { 1038 | list.push(qrRSBlock(totalCount, dataCount) ); 1039 | } 1040 | } 1041 | 1042 | return list; 1043 | }; 1044 | 1045 | return _this; 1046 | }(); 1047 | 1048 | //--------------------------------------------------------------------- 1049 | // qrBitBuffer 1050 | //--------------------------------------------------------------------- 1051 | 1052 | var qrBitBuffer = function() { 1053 | 1054 | var _buffer = new Array(); 1055 | var _length = 0; 1056 | 1057 | var _this = {}; 1058 | 1059 | _this.getBuffer = function() { 1060 | return _buffer; 1061 | }; 1062 | 1063 | _this.getAt = function(index) { 1064 | var bufIndex = Math.floor(index / 8); 1065 | return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1; 1066 | }; 1067 | 1068 | _this.put = function(num, length) { 1069 | for (var i = 0; i < length; i += 1) { 1070 | _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1); 1071 | } 1072 | }; 1073 | 1074 | _this.getLengthInBits = function() { 1075 | return _length; 1076 | }; 1077 | 1078 | _this.putBit = function(bit) { 1079 | 1080 | var bufIndex = Math.floor(_length / 8); 1081 | if (_buffer.length <= bufIndex) { 1082 | _buffer.push(0); 1083 | } 1084 | 1085 | if (bit) { 1086 | _buffer[bufIndex] |= (0x80 >>> (_length % 8) ); 1087 | } 1088 | 1089 | _length += 1; 1090 | }; 1091 | 1092 | return _this; 1093 | }; 1094 | 1095 | //--------------------------------------------------------------------- 1096 | // qr8BitByte 1097 | //--------------------------------------------------------------------- 1098 | 1099 | var qr8BitByte = function(data) { 1100 | 1101 | var _mode = QRMode.MODE_8BIT_BYTE; 1102 | var _data = data; 1103 | var _parsedData = []; 1104 | 1105 | var _this = {}; 1106 | 1107 | 1108 | // Added to support UTF-8 Characters 1109 | for (var i = 0, l = _data.length; i < l; i++) { 1110 | var byteArray = []; 1111 | var code = _data.charCodeAt(i); 1112 | 1113 | if (code > 0x10000) { 1114 | byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); 1115 | byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); 1116 | byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); 1117 | byteArray[3] = 0x80 | (code & 0x3F); 1118 | } else if (code > 0x800) { 1119 | byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); 1120 | byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); 1121 | byteArray[2] = 0x80 | (code & 0x3F); 1122 | } else if (code > 0x80) { 1123 | byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); 1124 | byteArray[1] = 0x80 | (code & 0x3F); 1125 | } else { 1126 | byteArray[0] = code; 1127 | } 1128 | 1129 | // Fix Unicode corruption bug 1130 | _parsedData.push(byteArray); 1131 | } 1132 | 1133 | _parsedData = Array.prototype.concat.apply([], _parsedData); 1134 | 1135 | if (_parsedData.length != _data.length) { 1136 | _parsedData.unshift(191); 1137 | _parsedData.unshift(187); 1138 | _parsedData.unshift(239); 1139 | } 1140 | 1141 | var _bytes = _parsedData; 1142 | 1143 | _this.getMode = function() { 1144 | return _mode; 1145 | }; 1146 | 1147 | _this.getLength = function(buffer) { 1148 | return _bytes.length; 1149 | }; 1150 | 1151 | _this.write = function(buffer) { 1152 | for (var i = 0; i < _bytes.length; i += 1) { 1153 | buffer.put(_bytes[i], 8); 1154 | } 1155 | }; 1156 | 1157 | return _this; 1158 | }; 1159 | 1160 | //===================================================================== 1161 | // GIF Support etc. 1162 | // 1163 | 1164 | //--------------------------------------------------------------------- 1165 | // byteArrayOutputStream 1166 | //--------------------------------------------------------------------- 1167 | 1168 | var byteArrayOutputStream = function() { 1169 | 1170 | var _bytes = new Array(); 1171 | 1172 | var _this = {}; 1173 | 1174 | _this.writeByte = function(b) { 1175 | _bytes.push(b & 0xff); 1176 | }; 1177 | 1178 | _this.writeShort = function(i) { 1179 | _this.writeByte(i); 1180 | _this.writeByte(i >>> 8); 1181 | }; 1182 | 1183 | _this.writeBytes = function(b, off, len) { 1184 | off = off || 0; 1185 | len = len || b.length; 1186 | for (var i = 0; i < len; i += 1) { 1187 | _this.writeByte(b[i + off]); 1188 | } 1189 | }; 1190 | 1191 | _this.writeString = function(s) { 1192 | for (var i = 0; i < s.length; i += 1) { 1193 | _this.writeByte(s.charCodeAt(i) ); 1194 | } 1195 | }; 1196 | 1197 | _this.toByteArray = function() { 1198 | return _bytes; 1199 | }; 1200 | 1201 | _this.toString = function() { 1202 | var s = ''; 1203 | s += '['; 1204 | for (var i = 0; i < _bytes.length; i += 1) { 1205 | if (i > 0) { 1206 | s += ','; 1207 | } 1208 | s += _bytes[i]; 1209 | } 1210 | s += ']'; 1211 | return s; 1212 | }; 1213 | 1214 | return _this; 1215 | }; 1216 | 1217 | //--------------------------------------------------------------------- 1218 | // base64EncodeOutputStream 1219 | //--------------------------------------------------------------------- 1220 | 1221 | var base64EncodeOutputStream = function() { 1222 | 1223 | var _buffer = 0; 1224 | var _buflen = 0; 1225 | var _length = 0; 1226 | var _base64 = ''; 1227 | 1228 | var _this = {}; 1229 | 1230 | var writeEncoded = function(b) { 1231 | _base64 += String.fromCharCode(encode(b & 0x3f) ); 1232 | }; 1233 | 1234 | var encode = function(n) { 1235 | if (n < 0) { 1236 | // error. 1237 | } else if (n < 26) { 1238 | return 0x41 + n; 1239 | } else if (n < 52) { 1240 | return 0x61 + (n - 26); 1241 | } else if (n < 62) { 1242 | return 0x30 + (n - 52); 1243 | } else if (n == 62) { 1244 | return 0x2b; 1245 | } else if (n == 63) { 1246 | return 0x2f; 1247 | } 1248 | throw new Error('n:' + n); 1249 | }; 1250 | 1251 | _this.writeByte = function(n) { 1252 | 1253 | _buffer = (_buffer << 8) | (n & 0xff); 1254 | _buflen += 8; 1255 | _length += 1; 1256 | 1257 | while (_buflen >= 6) { 1258 | writeEncoded(_buffer >>> (_buflen - 6) ); 1259 | _buflen -= 6; 1260 | } 1261 | }; 1262 | 1263 | _this.flush = function() { 1264 | 1265 | if (_buflen > 0) { 1266 | writeEncoded(_buffer << (6 - _buflen) ); 1267 | _buffer = 0; 1268 | _buflen = 0; 1269 | } 1270 | 1271 | if (_length % 3 != 0) { 1272 | // padding 1273 | var padlen = 3 - _length % 3; 1274 | for (var i = 0; i < padlen; i += 1) { 1275 | _base64 += '='; 1276 | } 1277 | } 1278 | }; 1279 | 1280 | _this.toString = function() { 1281 | return _base64; 1282 | }; 1283 | 1284 | return _this; 1285 | }; 1286 | 1287 | //--------------------------------------------------------------------- 1288 | // base64DecodeInputStream 1289 | //--------------------------------------------------------------------- 1290 | 1291 | var base64DecodeInputStream = function(str) { 1292 | 1293 | var _str = str; 1294 | var _pos = 0; 1295 | var _buffer = 0; 1296 | var _buflen = 0; 1297 | 1298 | var _this = {}; 1299 | 1300 | _this.read = function() { 1301 | 1302 | while (_buflen < 8) { 1303 | 1304 | if (_pos >= _str.length) { 1305 | if (_buflen == 0) { 1306 | return -1; 1307 | } 1308 | throw new Error('unexpected end of file./' + _buflen); 1309 | } 1310 | 1311 | var c = _str.charAt(_pos); 1312 | _pos += 1; 1313 | 1314 | if (c == '=') { 1315 | _buflen = 0; 1316 | return -1; 1317 | } else if (c.match(/^\s$/) ) { 1318 | // ignore if whitespace. 1319 | continue; 1320 | } 1321 | 1322 | _buffer = (_buffer << 6) | decode(c.charCodeAt(0) ); 1323 | _buflen += 6; 1324 | } 1325 | 1326 | var n = (_buffer >>> (_buflen - 8) ) & 0xff; 1327 | _buflen -= 8; 1328 | return n; 1329 | }; 1330 | 1331 | var decode = function(c) { 1332 | if (0x41 <= c && c <= 0x5a) { 1333 | return c - 0x41; 1334 | } else if (0x61 <= c && c <= 0x7a) { 1335 | return c - 0x61 + 26; 1336 | } else if (0x30 <= c && c <= 0x39) { 1337 | return c - 0x30 + 52; 1338 | } else if (c == 0x2b) { 1339 | return 62; 1340 | } else if (c == 0x2f) { 1341 | return 63; 1342 | } else { 1343 | throw new Error('c:' + c); 1344 | } 1345 | }; 1346 | 1347 | return _this; 1348 | }; 1349 | 1350 | //--------------------------------------------------------------------- 1351 | // gifImage (B/W) 1352 | //--------------------------------------------------------------------- 1353 | 1354 | var gifImage = function(width, height) { 1355 | 1356 | var _width = width; 1357 | var _height = height; 1358 | var _data = new Array(width * height); 1359 | 1360 | var _this = {}; 1361 | 1362 | _this.setPixel = function(x, y, pixel) { 1363 | _data[y * _width + x] = pixel; 1364 | }; 1365 | 1366 | _this.write = function(out) { 1367 | 1368 | //--------------------------------- 1369 | // GIF Signature 1370 | 1371 | out.writeString('GIF87a'); 1372 | 1373 | //--------------------------------- 1374 | // Screen Descriptor 1375 | 1376 | out.writeShort(_width); 1377 | out.writeShort(_height); 1378 | 1379 | out.writeByte(0x80); // 2bit 1380 | out.writeByte(0); 1381 | out.writeByte(0); 1382 | 1383 | //--------------------------------- 1384 | // Global Color Map 1385 | 1386 | // black 1387 | out.writeByte(0x00); 1388 | out.writeByte(0x00); 1389 | out.writeByte(0x00); 1390 | 1391 | // white 1392 | out.writeByte(0xff); 1393 | out.writeByte(0xff); 1394 | out.writeByte(0xff); 1395 | 1396 | //--------------------------------- 1397 | // Image Descriptor 1398 | 1399 | out.writeString(','); 1400 | out.writeShort(0); 1401 | out.writeShort(0); 1402 | out.writeShort(_width); 1403 | out.writeShort(_height); 1404 | out.writeByte(0); 1405 | 1406 | //--------------------------------- 1407 | // Local Color Map 1408 | 1409 | //--------------------------------- 1410 | // Raster Data 1411 | 1412 | var lzwMinCodeSize = 2; 1413 | var raster = getLZWRaster(lzwMinCodeSize); 1414 | 1415 | out.writeByte(lzwMinCodeSize); 1416 | 1417 | var offset = 0; 1418 | 1419 | while (raster.length - offset > 255) { 1420 | out.writeByte(255); 1421 | out.writeBytes(raster, offset, 255); 1422 | offset += 255; 1423 | } 1424 | 1425 | out.writeByte(raster.length - offset); 1426 | out.writeBytes(raster, offset, raster.length - offset); 1427 | out.writeByte(0x00); 1428 | 1429 | //--------------------------------- 1430 | // GIF Terminator 1431 | out.writeString(';'); 1432 | }; 1433 | 1434 | var bitOutputStream = function(out) { 1435 | 1436 | var _out = out; 1437 | var _bitLength = 0; 1438 | var _bitBuffer = 0; 1439 | 1440 | var _this = {}; 1441 | 1442 | _this.write = function(data, length) { 1443 | 1444 | if ( (data >>> length) != 0) { 1445 | throw new Error('length over'); 1446 | } 1447 | 1448 | while (_bitLength + length >= 8) { 1449 | _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) ); 1450 | length -= (8 - _bitLength); 1451 | data >>>= (8 - _bitLength); 1452 | _bitBuffer = 0; 1453 | _bitLength = 0; 1454 | } 1455 | 1456 | _bitBuffer = (data << _bitLength) | _bitBuffer; 1457 | _bitLength = _bitLength + length; 1458 | }; 1459 | 1460 | _this.flush = function() { 1461 | if (_bitLength > 0) { 1462 | _out.writeByte(_bitBuffer); 1463 | } 1464 | }; 1465 | 1466 | return _this; 1467 | }; 1468 | 1469 | var getLZWRaster = function(lzwMinCodeSize) { 1470 | 1471 | var clearCode = 1 << lzwMinCodeSize; 1472 | var endCode = (1 << lzwMinCodeSize) + 1; 1473 | var bitLength = lzwMinCodeSize + 1; 1474 | 1475 | // Setup LZWTable 1476 | var table = lzwTable(); 1477 | 1478 | for (var i = 0; i < clearCode; i += 1) { 1479 | table.add(String.fromCharCode(i) ); 1480 | } 1481 | table.add(String.fromCharCode(clearCode) ); 1482 | table.add(String.fromCharCode(endCode) ); 1483 | 1484 | var byteOut = byteArrayOutputStream(); 1485 | var bitOut = bitOutputStream(byteOut); 1486 | 1487 | // clear code 1488 | bitOut.write(clearCode, bitLength); 1489 | 1490 | var dataIndex = 0; 1491 | 1492 | var s = String.fromCharCode(_data[dataIndex]); 1493 | dataIndex += 1; 1494 | 1495 | while (dataIndex < _data.length) { 1496 | 1497 | var c = String.fromCharCode(_data[dataIndex]); 1498 | dataIndex += 1; 1499 | 1500 | if (table.contains(s + c) ) { 1501 | 1502 | s = s + c; 1503 | 1504 | } else { 1505 | 1506 | bitOut.write(table.indexOf(s), bitLength); 1507 | 1508 | if (table.size() < 0xfff) { 1509 | 1510 | if (table.size() == (1 << bitLength) ) { 1511 | bitLength += 1; 1512 | } 1513 | 1514 | table.add(s + c); 1515 | } 1516 | 1517 | s = c; 1518 | } 1519 | } 1520 | 1521 | bitOut.write(table.indexOf(s), bitLength); 1522 | 1523 | // end code 1524 | bitOut.write(endCode, bitLength); 1525 | 1526 | bitOut.flush(); 1527 | 1528 | return byteOut.toByteArray(); 1529 | }; 1530 | 1531 | var lzwTable = function() { 1532 | 1533 | var _map = {}; 1534 | var _size = 0; 1535 | 1536 | var _this = {}; 1537 | 1538 | _this.add = function(key) { 1539 | if (_this.contains(key) ) { 1540 | throw new Error('dup key:' + key); 1541 | } 1542 | _map[key] = _size; 1543 | _size += 1; 1544 | }; 1545 | 1546 | _this.size = function() { 1547 | return _size; 1548 | }; 1549 | 1550 | _this.indexOf = function(key) { 1551 | return _map[key]; 1552 | }; 1553 | 1554 | _this.contains = function(key) { 1555 | return typeof _map[key] != 'undefined'; 1556 | }; 1557 | 1558 | return _this; 1559 | }; 1560 | 1561 | return _this; 1562 | }; 1563 | 1564 | var createImgTag = function(width, height, getPixel, alt) { 1565 | 1566 | var gif = gifImage(width, height); 1567 | for (var y = 0; y < height; y += 1) { 1568 | for (var x = 0; x < width; x += 1) { 1569 | gif.setPixel(x, y, getPixel(x, y) ); 1570 | } 1571 | } 1572 | 1573 | var b = byteArrayOutputStream(); 1574 | gif.write(b); 1575 | 1576 | var base64 = base64EncodeOutputStream(); 1577 | var bytes = b.toByteArray(); 1578 | for (var i = 0; i < bytes.length; i += 1) { 1579 | base64.writeByte(bytes[i]); 1580 | } 1581 | base64.flush(); 1582 | 1583 | var img = ''; 1584 | img += 'data:image/gif;base64,'; 1585 | img += base64; 1586 | 1587 | return img; 1588 | }; 1589 | 1590 | //--------------------------------------------------------------------- 1591 | // returns qrcode function. 1592 | 1593 | var drawImg = function(text, options) { 1594 | options = options || {}; 1595 | var typeNumber = options.typeNumber || 4; 1596 | var errorCorrectLevel = options.errorCorrectLevel || 'M'; 1597 | var size = options.size || 500; 1598 | 1599 | var qr; 1600 | 1601 | try { 1602 | qr = qrcode(typeNumber, errorCorrectLevel || 'M'); 1603 | qr.addData(text); 1604 | qr.make(); 1605 | } catch (e) { 1606 | if(typeNumber >= 40) { 1607 | throw new Error('Text too long to encode'); 1608 | } else { 1609 | return drawImg(text, { 1610 | size: size, 1611 | errorCorrectLevel: errorCorrectLevel, 1612 | typeNumber: typeNumber + 1 1613 | }); 1614 | } 1615 | } 1616 | 1617 | // calc cellsize and margin 1618 | var cellsize = parseInt(size / qr.getModuleCount()); 1619 | var margin = parseInt((size - qr.getModuleCount() * cellsize) / 2); 1620 | 1621 | return qr.createImgTag(cellsize, margin, size); 1622 | }; 1623 | module.exports = { 1624 | drawImg: drawImg 1625 | }; -------------------------------------------------------------------------------- /demo/weapp-demo/utils/weapp-qrcode.js: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------- 2 | // 3 | // QR Code Generator for JavaScript 4 | // 5 | // Copyright (c) 2009 Kazuhiko Arase 6 | // 7 | // URL: http://www.d-project.com/ 8 | // 9 | // Licensed under the MIT license: 10 | // http://www.opensource.org/licenses/mit-license.php 11 | // 12 | // The word 'QR Code' is registered trademark of 13 | // DENSO WAVE INCORPORATED 14 | // http://www.denso-wave.com/qrcode/faqpatent-e.html 15 | // 16 | //--------------------------------------------------------------------- 17 | 18 | //---------------微信小程序基于base64生成二维码插件修改------------------- 19 | /* 20 | * @Modified: Pudon 21 | * @demoURL: https://github.com/Pudon/weapp-qrcode 22 | * @Date: 2018-09-11 14:00:05 23 | * @Last Modified by: Pudon 24 | * @Last Modified time: 2018-09-12 16:33:19 25 | */ 26 | //--------------------------------------------------------------------- 27 | 28 | /** 29 | * qrcode 30 | * @param typeNumber 1 to 40 31 | * @param errorCorrectLevel 'L','M','Q','H' 32 | */ 33 | var qrcode = function(typeNumber, errorCorrectLevel) { 34 | 35 | var PAD0 = 0xEC; 36 | var PAD1 = 0x11; 37 | 38 | var _typeNumber = typeNumber; 39 | var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel]; 40 | var _modules = null; 41 | var _moduleCount = 0; 42 | var _dataCache = null; 43 | var _dataList = new Array(); 44 | 45 | var _this = {}; 46 | 47 | var makeImpl = function(test, maskPattern) { 48 | 49 | _moduleCount = _typeNumber * 4 + 17; 50 | _modules = function(moduleCount) { 51 | var modules = new Array(moduleCount); 52 | for (var row = 0; row < moduleCount; row += 1) { 53 | modules[row] = new Array(moduleCount); 54 | for (var col = 0; col < moduleCount; col += 1) { 55 | modules[row][col] = null; 56 | } 57 | } 58 | return modules; 59 | }(_moduleCount); 60 | 61 | setupPositionProbePattern(0, 0); 62 | setupPositionProbePattern(_moduleCount - 7, 0); 63 | setupPositionProbePattern(0, _moduleCount - 7); 64 | setupPositionAdjustPattern(); 65 | setupTimingPattern(); 66 | setupTypeInfo(test, maskPattern); 67 | 68 | if (_typeNumber >= 7) { 69 | setupTypeNumber(test); 70 | } 71 | 72 | if (_dataCache == null) { 73 | _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList); 74 | } 75 | 76 | mapData(_dataCache, maskPattern); 77 | }; 78 | 79 | var setupPositionProbePattern = function(row, col) { 80 | 81 | for (var r = -1; r <= 7; r += 1) { 82 | 83 | if (row + r <= -1 || _moduleCount <= row + r) continue; 84 | 85 | for (var c = -1; c <= 7; c += 1) { 86 | 87 | if (col + c <= -1 || _moduleCount <= col + c) continue; 88 | 89 | if ( (0 <= r && r <= 6 && (c == 0 || c == 6) ) 90 | || (0 <= c && c <= 6 && (r == 0 || r == 6) ) 91 | || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) { 92 | _modules[row + r][col + c] = true; 93 | } else { 94 | _modules[row + r][col + c] = false; 95 | } 96 | } 97 | } 98 | }; 99 | 100 | var getBestMaskPattern = function() { 101 | 102 | var minLostPoint = 0; 103 | var pattern = 0; 104 | 105 | for (var i = 0; i < 8; i += 1) { 106 | 107 | makeImpl(true, i); 108 | 109 | var lostPoint = QRUtil.getLostPoint(_this); 110 | 111 | if (i == 0 || minLostPoint > lostPoint) { 112 | minLostPoint = lostPoint; 113 | pattern = i; 114 | } 115 | } 116 | 117 | return pattern; 118 | }; 119 | 120 | var setupTimingPattern = function() { 121 | 122 | for (var r = 8; r < _moduleCount - 8; r += 1) { 123 | if (_modules[r][6] != null) { 124 | continue; 125 | } 126 | _modules[r][6] = (r % 2 == 0); 127 | } 128 | 129 | for (var c = 8; c < _moduleCount - 8; c += 1) { 130 | if (_modules[6][c] != null) { 131 | continue; 132 | } 133 | _modules[6][c] = (c % 2 == 0); 134 | } 135 | }; 136 | 137 | var setupPositionAdjustPattern = function() { 138 | 139 | var pos = QRUtil.getPatternPosition(_typeNumber); 140 | 141 | for (var i = 0; i < pos.length; i += 1) { 142 | 143 | for (var j = 0; j < pos.length; j += 1) { 144 | 145 | var row = pos[i]; 146 | var col = pos[j]; 147 | 148 | if (_modules[row][col] != null) { 149 | continue; 150 | } 151 | 152 | for (var r = -2; r <= 2; r += 1) { 153 | 154 | for (var c = -2; c <= 2; c += 1) { 155 | 156 | if (r == -2 || r == 2 || c == -2 || c == 2 157 | || (r == 0 && c == 0) ) { 158 | _modules[row + r][col + c] = true; 159 | } else { 160 | _modules[row + r][col + c] = false; 161 | } 162 | } 163 | } 164 | } 165 | } 166 | }; 167 | 168 | var setupTypeNumber = function(test) { 169 | 170 | var bits = QRUtil.getBCHTypeNumber(_typeNumber); 171 | 172 | for (var i = 0; i < 18; i += 1) { 173 | var mod = (!test && ( (bits >> i) & 1) == 1); 174 | _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod; 175 | } 176 | 177 | for (var i = 0; i < 18; i += 1) { 178 | var mod = (!test && ( (bits >> i) & 1) == 1); 179 | _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod; 180 | } 181 | }; 182 | 183 | var setupTypeInfo = function(test, maskPattern) { 184 | 185 | var data = (_errorCorrectLevel << 3) | maskPattern; 186 | var bits = QRUtil.getBCHTypeInfo(data); 187 | 188 | // vertical 189 | for (var i = 0; i < 15; i += 1) { 190 | 191 | var mod = (!test && ( (bits >> i) & 1) == 1); 192 | 193 | if (i < 6) { 194 | _modules[i][8] = mod; 195 | } else if (i < 8) { 196 | _modules[i + 1][8] = mod; 197 | } else { 198 | _modules[_moduleCount - 15 + i][8] = mod; 199 | } 200 | } 201 | 202 | // horizontal 203 | for (var i = 0; i < 15; i += 1) { 204 | 205 | var mod = (!test && ( (bits >> i) & 1) == 1); 206 | 207 | if (i < 8) { 208 | _modules[8][_moduleCount - i - 1] = mod; 209 | } else if (i < 9) { 210 | _modules[8][15 - i - 1 + 1] = mod; 211 | } else { 212 | _modules[8][15 - i - 1] = mod; 213 | } 214 | } 215 | 216 | // fixed module 217 | _modules[_moduleCount - 8][8] = (!test); 218 | }; 219 | 220 | var mapData = function(data, maskPattern) { 221 | 222 | var inc = -1; 223 | var row = _moduleCount - 1; 224 | var bitIndex = 7; 225 | var byteIndex = 0; 226 | var maskFunc = QRUtil.getMaskFunction(maskPattern); 227 | 228 | for (var col = _moduleCount - 1; col > 0; col -= 2) { 229 | 230 | if (col == 6) col -= 1; 231 | 232 | while (true) { 233 | 234 | for (var c = 0; c < 2; c += 1) { 235 | 236 | if (_modules[row][col - c] == null) { 237 | 238 | var dark = false; 239 | 240 | if (byteIndex < data.length) { 241 | dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1); 242 | } 243 | 244 | var mask = maskFunc(row, col - c); 245 | 246 | if (mask) { 247 | dark = !dark; 248 | } 249 | 250 | _modules[row][col - c] = dark; 251 | bitIndex -= 1; 252 | 253 | if (bitIndex == -1) { 254 | byteIndex += 1; 255 | bitIndex = 7; 256 | } 257 | } 258 | } 259 | 260 | row += inc; 261 | 262 | if (row < 0 || _moduleCount <= row) { 263 | row -= inc; 264 | inc = -inc; 265 | break; 266 | } 267 | } 268 | } 269 | }; 270 | 271 | var createBytes = function(buffer, rsBlocks) { 272 | 273 | var offset = 0; 274 | 275 | var maxDcCount = 0; 276 | var maxEcCount = 0; 277 | 278 | var dcdata = new Array(rsBlocks.length); 279 | var ecdata = new Array(rsBlocks.length); 280 | 281 | for (var r = 0; r < rsBlocks.length; r += 1) { 282 | 283 | var dcCount = rsBlocks[r].dataCount; 284 | var ecCount = rsBlocks[r].totalCount - dcCount; 285 | 286 | maxDcCount = Math.max(maxDcCount, dcCount); 287 | maxEcCount = Math.max(maxEcCount, ecCount); 288 | 289 | dcdata[r] = new Array(dcCount); 290 | 291 | for (var i = 0; i < dcdata[r].length; i += 1) { 292 | dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset]; 293 | } 294 | offset += dcCount; 295 | 296 | var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); 297 | var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1); 298 | 299 | var modPoly = rawPoly.mod(rsPoly); 300 | ecdata[r] = new Array(rsPoly.getLength() - 1); 301 | for (var i = 0; i < ecdata[r].length; i += 1) { 302 | var modIndex = i + modPoly.getLength() - ecdata[r].length; 303 | ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0; 304 | } 305 | } 306 | 307 | var totalCodeCount = 0; 308 | for (var i = 0; i < rsBlocks.length; i += 1) { 309 | totalCodeCount += rsBlocks[i].totalCount; 310 | } 311 | 312 | var data = new Array(totalCodeCount); 313 | var index = 0; 314 | 315 | for (var i = 0; i < maxDcCount; i += 1) { 316 | for (var r = 0; r < rsBlocks.length; r += 1) { 317 | if (i < dcdata[r].length) { 318 | data[index] = dcdata[r][i]; 319 | index += 1; 320 | } 321 | } 322 | } 323 | 324 | for (var i = 0; i < maxEcCount; i += 1) { 325 | for (var r = 0; r < rsBlocks.length; r += 1) { 326 | if (i < ecdata[r].length) { 327 | data[index] = ecdata[r][i]; 328 | index += 1; 329 | } 330 | } 331 | } 332 | 333 | return data; 334 | }; 335 | 336 | var createData = function(typeNumber, errorCorrectLevel, dataList) { 337 | 338 | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); 339 | 340 | var buffer = qrBitBuffer(); 341 | 342 | for (var i = 0; i < dataList.length; i += 1) { 343 | var data = dataList[i]; 344 | buffer.put(data.getMode(), 4); 345 | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) ); 346 | data.write(buffer); 347 | } 348 | 349 | // calc num max data. 350 | var totalDataCount = 0; 351 | for (var i = 0; i < rsBlocks.length; i += 1) { 352 | totalDataCount += rsBlocks[i].dataCount; 353 | } 354 | 355 | if (buffer.getLengthInBits() > totalDataCount * 8) { 356 | throw new Error('code length overflow. (' 357 | + buffer.getLengthInBits() 358 | + '>' 359 | + totalDataCount * 8 360 | + ')'); 361 | } 362 | 363 | // end code 364 | if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { 365 | buffer.put(0, 4); 366 | } 367 | 368 | // padding 369 | while (buffer.getLengthInBits() % 8 != 0) { 370 | buffer.putBit(false); 371 | } 372 | 373 | // padding 374 | while (true) { 375 | 376 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 377 | break; 378 | } 379 | buffer.put(PAD0, 8); 380 | 381 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 382 | break; 383 | } 384 | buffer.put(PAD1, 8); 385 | } 386 | 387 | return createBytes(buffer, rsBlocks); 388 | }; 389 | 390 | _this.addData = function(data) { 391 | var newData = qr8BitByte(data); 392 | _dataList.push(newData); 393 | _dataCache = null; 394 | }; 395 | 396 | _this.isDark = function(row, col) { 397 | if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) { 398 | throw new Error(row + ',' + col); 399 | } 400 | return _modules[row][col]; 401 | }; 402 | 403 | _this.getModuleCount = function() { 404 | return _moduleCount; 405 | }; 406 | 407 | _this.make = function() { 408 | makeImpl(false, getBestMaskPattern() ); 409 | }; 410 | 411 | _this.createTableTag = function(cellSize, margin) { 412 | 413 | cellSize = cellSize || 2; 414 | margin = (typeof margin == 'undefined')? cellSize * 4 : margin; 415 | 416 | var qrHtml = ''; 417 | 418 | qrHtml += ''; 423 | qrHtml += ''; 424 | 425 | for (var r = 0; r < _this.getModuleCount(); r += 1) { 426 | 427 | qrHtml += ''; 428 | 429 | for (var c = 0; c < _this.getModuleCount(); c += 1) { 430 | qrHtml += ''; 443 | } 444 | 445 | qrHtml += ''; 446 | qrHtml += '
'; 440 | } 441 | 442 | qrHtml += '
'; 447 | 448 | return qrHtml; 449 | }; 450 | 451 | _this.createImgTag = function(cellSize, margin, size) { 452 | 453 | cellSize = cellSize || 2; 454 | margin = (typeof margin == 'undefined')? cellSize * 4 : margin; 455 | 456 | var min = margin; 457 | var max = _this.getModuleCount() * cellSize + margin; 458 | 459 | return createImgTag(size, size, function(x, y) { 460 | if (min <= x && x < max && min <= y && y < max) { 461 | var c = Math.floor( (x - min) / cellSize); 462 | var r = Math.floor( (y - min) / cellSize); 463 | return _this.isDark(r, c)? 0 : 1; 464 | } else { 465 | return 1; 466 | } 467 | } ); 468 | }; 469 | 470 | return _this; 471 | }; 472 | 473 | //--------------------------------------------------------------------- 474 | // qrcode.stringToBytes 475 | //--------------------------------------------------------------------- 476 | 477 | qrcode.stringToBytes = function(s) { 478 | var bytes = new Array(); 479 | for (var i = 0; i < s.length; i += 1) { 480 | var c = s.charCodeAt(i); 481 | bytes.push(c & 0xff); 482 | } 483 | return bytes; 484 | }; 485 | 486 | //--------------------------------------------------------------------- 487 | // qrcode.createStringToBytes 488 | //--------------------------------------------------------------------- 489 | 490 | /** 491 | * @param unicodeData base64 string of byte array. 492 | * [16bit Unicode],[16bit Bytes], ... 493 | * @param numChars 494 | */ 495 | qrcode.createStringToBytes = function(unicodeData, numChars) { 496 | 497 | // create conversion map. 498 | 499 | var unicodeMap = function() { 500 | 501 | var bin = base64DecodeInputStream(unicodeData); 502 | var read = function() { 503 | var b = bin.read(); 504 | if (b == -1) throw new Error(); 505 | return b; 506 | }; 507 | 508 | var count = 0; 509 | var unicodeMap = {}; 510 | while (true) { 511 | var b0 = bin.read(); 512 | if (b0 == -1) break; 513 | var b1 = read(); 514 | var b2 = read(); 515 | var b3 = read(); 516 | var k = String.fromCharCode( (b0 << 8) | b1); 517 | var v = (b2 << 8) | b3; 518 | unicodeMap[k] = v; 519 | count += 1; 520 | } 521 | if (count != numChars) { 522 | throw new Error(count + ' != ' + numChars); 523 | } 524 | 525 | return unicodeMap; 526 | }(); 527 | 528 | var unknownChar = '?'.charCodeAt(0); 529 | 530 | return function(s) { 531 | var bytes = new Array(); 532 | for (var i = 0; i < s.length; i += 1) { 533 | var c = s.charCodeAt(i); 534 | if (c < 128) { 535 | bytes.push(c); 536 | } else { 537 | var b = unicodeMap[s.charAt(i)]; 538 | if (typeof b == 'number') { 539 | if ( (b & 0xff) == b) { 540 | // 1byte 541 | bytes.push(b); 542 | } else { 543 | // 2bytes 544 | bytes.push(b >>> 8); 545 | bytes.push(b & 0xff); 546 | } 547 | } else { 548 | bytes.push(unknownChar); 549 | } 550 | } 551 | } 552 | return bytes; 553 | }; 554 | }; 555 | 556 | //--------------------------------------------------------------------- 557 | // QRMode 558 | //--------------------------------------------------------------------- 559 | 560 | var QRMode = { 561 | MODE_NUMBER : 1 << 0, 562 | MODE_ALPHA_NUM : 1 << 1, 563 | MODE_8BIT_BYTE : 1 << 2, 564 | MODE_KANJI : 1 << 3 565 | }; 566 | 567 | //--------------------------------------------------------------------- 568 | // QRErrorCorrectLevel 569 | //--------------------------------------------------------------------- 570 | 571 | var QRErrorCorrectLevel = { 572 | L : 1, 573 | M : 0, 574 | Q : 3, 575 | H : 2 576 | }; 577 | 578 | //--------------------------------------------------------------------- 579 | // QRMaskPattern 580 | //--------------------------------------------------------------------- 581 | 582 | var QRMaskPattern = { 583 | PATTERN000 : 0, 584 | PATTERN001 : 1, 585 | PATTERN010 : 2, 586 | PATTERN011 : 3, 587 | PATTERN100 : 4, 588 | PATTERN101 : 5, 589 | PATTERN110 : 6, 590 | PATTERN111 : 7 591 | }; 592 | 593 | //--------------------------------------------------------------------- 594 | // QRUtil 595 | //--------------------------------------------------------------------- 596 | 597 | var QRUtil = function() { 598 | 599 | var PATTERN_POSITION_TABLE = [ 600 | [], 601 | [6, 18], 602 | [6, 22], 603 | [6, 26], 604 | [6, 30], 605 | [6, 34], 606 | [6, 22, 38], 607 | [6, 24, 42], 608 | [6, 26, 46], 609 | [6, 28, 50], 610 | [6, 30, 54], 611 | [6, 32, 58], 612 | [6, 34, 62], 613 | [6, 26, 46, 66], 614 | [6, 26, 48, 70], 615 | [6, 26, 50, 74], 616 | [6, 30, 54, 78], 617 | [6, 30, 56, 82], 618 | [6, 30, 58, 86], 619 | [6, 34, 62, 90], 620 | [6, 28, 50, 72, 94], 621 | [6, 26, 50, 74, 98], 622 | [6, 30, 54, 78, 102], 623 | [6, 28, 54, 80, 106], 624 | [6, 32, 58, 84, 110], 625 | [6, 30, 58, 86, 114], 626 | [6, 34, 62, 90, 118], 627 | [6, 26, 50, 74, 98, 122], 628 | [6, 30, 54, 78, 102, 126], 629 | [6, 26, 52, 78, 104, 130], 630 | [6, 30, 56, 82, 108, 134], 631 | [6, 34, 60, 86, 112, 138], 632 | [6, 30, 58, 86, 114, 142], 633 | [6, 34, 62, 90, 118, 146], 634 | [6, 30, 54, 78, 102, 126, 150], 635 | [6, 24, 50, 76, 102, 128, 154], 636 | [6, 28, 54, 80, 106, 132, 158], 637 | [6, 32, 58, 84, 110, 136, 162], 638 | [6, 26, 54, 82, 110, 138, 166], 639 | [6, 30, 58, 86, 114, 142, 170] 640 | ]; 641 | var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); 642 | var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0); 643 | var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1); 644 | 645 | var _this = {}; 646 | 647 | var getBCHDigit = function(data) { 648 | var digit = 0; 649 | while (data != 0) { 650 | digit += 1; 651 | data >>>= 1; 652 | } 653 | return digit; 654 | }; 655 | 656 | _this.getBCHTypeInfo = function(data) { 657 | var d = data << 10; 658 | while (getBCHDigit(d) - getBCHDigit(G15) >= 0) { 659 | d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) ); 660 | } 661 | return ( (data << 10) | d) ^ G15_MASK; 662 | }; 663 | 664 | _this.getBCHTypeNumber = function(data) { 665 | var d = data << 12; 666 | while (getBCHDigit(d) - getBCHDigit(G18) >= 0) { 667 | d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) ); 668 | } 669 | return (data << 12) | d; 670 | }; 671 | 672 | _this.getPatternPosition = function(typeNumber) { 673 | return PATTERN_POSITION_TABLE[typeNumber - 1]; 674 | }; 675 | 676 | _this.getMaskFunction = function(maskPattern) { 677 | 678 | switch (maskPattern) { 679 | 680 | case QRMaskPattern.PATTERN000 : 681 | return function(i, j) { return (i + j) % 2 == 0; }; 682 | case QRMaskPattern.PATTERN001 : 683 | return function(i, j) { return i % 2 == 0; }; 684 | case QRMaskPattern.PATTERN010 : 685 | return function(i, j) { return j % 3 == 0; }; 686 | case QRMaskPattern.PATTERN011 : 687 | return function(i, j) { return (i + j) % 3 == 0; }; 688 | case QRMaskPattern.PATTERN100 : 689 | return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; }; 690 | case QRMaskPattern.PATTERN101 : 691 | return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; }; 692 | case QRMaskPattern.PATTERN110 : 693 | return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; }; 694 | case QRMaskPattern.PATTERN111 : 695 | return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; }; 696 | 697 | default : 698 | throw new Error('bad maskPattern:' + maskPattern); 699 | } 700 | }; 701 | 702 | _this.getErrorCorrectPolynomial = function(errorCorrectLength) { 703 | var a = qrPolynomial([1], 0); 704 | for (var i = 0; i < errorCorrectLength; i += 1) { 705 | a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) ); 706 | } 707 | return a; 708 | }; 709 | 710 | _this.getLengthInBits = function(mode, type) { 711 | 712 | if (1 <= type && type < 10) { 713 | 714 | // 1 - 9 715 | 716 | switch(mode) { 717 | case QRMode.MODE_NUMBER : return 10; 718 | case QRMode.MODE_ALPHA_NUM : return 9; 719 | case QRMode.MODE_8BIT_BYTE : return 8; 720 | case QRMode.MODE_KANJI : return 8; 721 | default : 722 | throw new Error('mode:' + mode); 723 | } 724 | 725 | } else if (type < 27) { 726 | 727 | // 10 - 26 728 | 729 | switch(mode) { 730 | case QRMode.MODE_NUMBER : return 12; 731 | case QRMode.MODE_ALPHA_NUM : return 11; 732 | case QRMode.MODE_8BIT_BYTE : return 16; 733 | case QRMode.MODE_KANJI : return 10; 734 | default : 735 | throw new Error('mode:' + mode); 736 | } 737 | 738 | } else if (type < 41) { 739 | 740 | // 27 - 40 741 | 742 | switch(mode) { 743 | case QRMode.MODE_NUMBER : return 14; 744 | case QRMode.MODE_ALPHA_NUM : return 13; 745 | case QRMode.MODE_8BIT_BYTE : return 16; 746 | case QRMode.MODE_KANJI : return 12; 747 | default : 748 | throw new Error('mode:' + mode); 749 | } 750 | 751 | } else { 752 | throw new Error('type:' + type); 753 | } 754 | }; 755 | 756 | _this.getLostPoint = function(qrcode) { 757 | 758 | var moduleCount = qrcode.getModuleCount(); 759 | 760 | var lostPoint = 0; 761 | 762 | // LEVEL1 763 | 764 | for (var row = 0; row < moduleCount; row += 1) { 765 | for (var col = 0; col < moduleCount; col += 1) { 766 | 767 | var sameCount = 0; 768 | var dark = qrcode.isDark(row, col); 769 | 770 | for (var r = -1; r <= 1; r += 1) { 771 | 772 | if (row + r < 0 || moduleCount <= row + r) { 773 | continue; 774 | } 775 | 776 | for (var c = -1; c <= 1; c += 1) { 777 | 778 | if (col + c < 0 || moduleCount <= col + c) { 779 | continue; 780 | } 781 | 782 | if (r == 0 && c == 0) { 783 | continue; 784 | } 785 | 786 | if (dark == qrcode.isDark(row + r, col + c) ) { 787 | sameCount += 1; 788 | } 789 | } 790 | } 791 | 792 | if (sameCount > 5) { 793 | lostPoint += (3 + sameCount - 5); 794 | } 795 | } 796 | }; 797 | 798 | // LEVEL2 799 | 800 | for (var row = 0; row < moduleCount - 1; row += 1) { 801 | for (var col = 0; col < moduleCount - 1; col += 1) { 802 | var count = 0; 803 | if (qrcode.isDark(row, col) ) count += 1; 804 | if (qrcode.isDark(row + 1, col) ) count += 1; 805 | if (qrcode.isDark(row, col + 1) ) count += 1; 806 | if (qrcode.isDark(row + 1, col + 1) ) count += 1; 807 | if (count == 0 || count == 4) { 808 | lostPoint += 3; 809 | } 810 | } 811 | } 812 | 813 | // LEVEL3 814 | 815 | for (var row = 0; row < moduleCount; row += 1) { 816 | for (var col = 0; col < moduleCount - 6; col += 1) { 817 | if (qrcode.isDark(row, col) 818 | && !qrcode.isDark(row, col + 1) 819 | && qrcode.isDark(row, col + 2) 820 | && qrcode.isDark(row, col + 3) 821 | && qrcode.isDark(row, col + 4) 822 | && !qrcode.isDark(row, col + 5) 823 | && qrcode.isDark(row, col + 6) ) { 824 | lostPoint += 40; 825 | } 826 | } 827 | } 828 | 829 | for (var col = 0; col < moduleCount; col += 1) { 830 | for (var row = 0; row < moduleCount - 6; row += 1) { 831 | if (qrcode.isDark(row, col) 832 | && !qrcode.isDark(row + 1, col) 833 | && qrcode.isDark(row + 2, col) 834 | && qrcode.isDark(row + 3, col) 835 | && qrcode.isDark(row + 4, col) 836 | && !qrcode.isDark(row + 5, col) 837 | && qrcode.isDark(row + 6, col) ) { 838 | lostPoint += 40; 839 | } 840 | } 841 | } 842 | 843 | // LEVEL4 844 | 845 | var darkCount = 0; 846 | 847 | for (var col = 0; col < moduleCount; col += 1) { 848 | for (var row = 0; row < moduleCount; row += 1) { 849 | if (qrcode.isDark(row, col) ) { 850 | darkCount += 1; 851 | } 852 | } 853 | } 854 | 855 | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; 856 | lostPoint += ratio * 10; 857 | 858 | return lostPoint; 859 | }; 860 | 861 | return _this; 862 | }(); 863 | 864 | //--------------------------------------------------------------------- 865 | // QRMath 866 | //--------------------------------------------------------------------- 867 | 868 | var QRMath = function() { 869 | 870 | var EXP_TABLE = new Array(256); 871 | var LOG_TABLE = new Array(256); 872 | 873 | // initialize tables 874 | for (var i = 0; i < 8; i += 1) { 875 | EXP_TABLE[i] = 1 << i; 876 | } 877 | for (var i = 8; i < 256; i += 1) { 878 | EXP_TABLE[i] = EXP_TABLE[i - 4] 879 | ^ EXP_TABLE[i - 5] 880 | ^ EXP_TABLE[i - 6] 881 | ^ EXP_TABLE[i - 8]; 882 | } 883 | for (var i = 0; i < 255; i += 1) { 884 | LOG_TABLE[EXP_TABLE[i] ] = i; 885 | } 886 | 887 | var _this = {}; 888 | 889 | _this.glog = function(n) { 890 | 891 | if (n < 1) { 892 | throw new Error('glog(' + n + ')'); 893 | } 894 | 895 | return LOG_TABLE[n]; 896 | }; 897 | 898 | _this.gexp = function(n) { 899 | 900 | while (n < 0) { 901 | n += 255; 902 | } 903 | 904 | while (n >= 256) { 905 | n -= 255; 906 | } 907 | 908 | return EXP_TABLE[n]; 909 | }; 910 | 911 | return _this; 912 | }(); 913 | 914 | //--------------------------------------------------------------------- 915 | // qrPolynomial 916 | //--------------------------------------------------------------------- 917 | 918 | function qrPolynomial(num, shift) { 919 | 920 | if (typeof num.length == 'undefined') { 921 | throw new Error(num.length + '/' + shift); 922 | } 923 | 924 | var _num = function() { 925 | var offset = 0; 926 | while (offset < num.length && num[offset] == 0) { 927 | offset += 1; 928 | } 929 | var _num = new Array(num.length - offset + shift); 930 | for (var i = 0; i < num.length - offset; i += 1) { 931 | _num[i] = num[i + offset]; 932 | } 933 | return _num; 934 | }(); 935 | 936 | var _this = {}; 937 | 938 | _this.getAt = function(index) { 939 | return _num[index]; 940 | }; 941 | 942 | _this.getLength = function() { 943 | return _num.length; 944 | }; 945 | 946 | _this.multiply = function(e) { 947 | 948 | var num = new Array(_this.getLength() + e.getLength() - 1); 949 | 950 | for (var i = 0; i < _this.getLength(); i += 1) { 951 | for (var j = 0; j < e.getLength(); j += 1) { 952 | num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) ); 953 | } 954 | } 955 | 956 | return qrPolynomial(num, 0); 957 | }; 958 | 959 | _this.mod = function(e) { 960 | 961 | if (_this.getLength() - e.getLength() < 0) { 962 | return _this; 963 | } 964 | 965 | var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) ); 966 | 967 | var num = new Array(_this.getLength() ); 968 | for (var i = 0; i < _this.getLength(); i += 1) { 969 | num[i] = _this.getAt(i); 970 | } 971 | 972 | for (var i = 0; i < e.getLength(); i += 1) { 973 | num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio); 974 | } 975 | 976 | // recursive call 977 | return qrPolynomial(num, 0).mod(e); 978 | }; 979 | 980 | return _this; 981 | }; 982 | 983 | //--------------------------------------------------------------------- 984 | // QRRSBlock 985 | //--------------------------------------------------------------------- 986 | 987 | var QRRSBlock = function() { 988 | 989 | 990 | // [1: [L, M, Q, H], ..] 991 | var RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]]; 992 | 993 | var qrRSBlock = function(totalCount, dataCount) { 994 | var _this = {}; 995 | _this.totalCount = totalCount; 996 | _this.dataCount = dataCount; 997 | return _this; 998 | }; 999 | 1000 | var _this = {}; 1001 | 1002 | var getRsBlockTable = function(typeNumber, errorCorrectLevel) { 1003 | 1004 | switch(errorCorrectLevel) { 1005 | case QRErrorCorrectLevel.L : 1006 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; 1007 | case QRErrorCorrectLevel.M : 1008 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; 1009 | case QRErrorCorrectLevel.Q : 1010 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; 1011 | case QRErrorCorrectLevel.H : 1012 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; 1013 | default : 1014 | return undefined; 1015 | } 1016 | }; 1017 | 1018 | _this.getRSBlocks = function(typeNumber, errorCorrectLevel) { 1019 | 1020 | var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel); 1021 | 1022 | if (typeof rsBlock == 'undefined') { 1023 | throw new Error('bad rs block @ typeNumber:' + typeNumber + 1024 | '/errorCorrectLevel:' + errorCorrectLevel); 1025 | } 1026 | 1027 | var length = rsBlock.length / 3; 1028 | 1029 | var list = new Array(); 1030 | 1031 | for (var i = 0; i < length; i += 1) { 1032 | 1033 | var count = rsBlock[i * 3 + 0]; 1034 | var totalCount = rsBlock[i * 3 + 1]; 1035 | var dataCount = rsBlock[i * 3 + 2]; 1036 | 1037 | for (var j = 0; j < count; j += 1) { 1038 | list.push(qrRSBlock(totalCount, dataCount) ); 1039 | } 1040 | } 1041 | 1042 | return list; 1043 | }; 1044 | 1045 | return _this; 1046 | }(); 1047 | 1048 | //--------------------------------------------------------------------- 1049 | // qrBitBuffer 1050 | //--------------------------------------------------------------------- 1051 | 1052 | var qrBitBuffer = function() { 1053 | 1054 | var _buffer = new Array(); 1055 | var _length = 0; 1056 | 1057 | var _this = {}; 1058 | 1059 | _this.getBuffer = function() { 1060 | return _buffer; 1061 | }; 1062 | 1063 | _this.getAt = function(index) { 1064 | var bufIndex = Math.floor(index / 8); 1065 | return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1; 1066 | }; 1067 | 1068 | _this.put = function(num, length) { 1069 | for (var i = 0; i < length; i += 1) { 1070 | _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1); 1071 | } 1072 | }; 1073 | 1074 | _this.getLengthInBits = function() { 1075 | return _length; 1076 | }; 1077 | 1078 | _this.putBit = function(bit) { 1079 | 1080 | var bufIndex = Math.floor(_length / 8); 1081 | if (_buffer.length <= bufIndex) { 1082 | _buffer.push(0); 1083 | } 1084 | 1085 | if (bit) { 1086 | _buffer[bufIndex] |= (0x80 >>> (_length % 8) ); 1087 | } 1088 | 1089 | _length += 1; 1090 | }; 1091 | 1092 | return _this; 1093 | }; 1094 | 1095 | //--------------------------------------------------------------------- 1096 | // qr8BitByte 1097 | //--------------------------------------------------------------------- 1098 | 1099 | var qr8BitByte = function(data) { 1100 | 1101 | var _mode = QRMode.MODE_8BIT_BYTE; 1102 | var _data = data; 1103 | var _parsedData = []; 1104 | 1105 | var _this = {}; 1106 | 1107 | 1108 | // Added to support UTF-8 Characters 1109 | for (var i = 0, l = _data.length; i < l; i++) { 1110 | var byteArray = []; 1111 | var code = _data.charCodeAt(i); 1112 | 1113 | if (code > 0x10000) { 1114 | byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); 1115 | byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); 1116 | byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); 1117 | byteArray[3] = 0x80 | (code & 0x3F); 1118 | } else if (code > 0x800) { 1119 | byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); 1120 | byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); 1121 | byteArray[2] = 0x80 | (code & 0x3F); 1122 | } else if (code > 0x80) { 1123 | byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); 1124 | byteArray[1] = 0x80 | (code & 0x3F); 1125 | } else { 1126 | byteArray[0] = code; 1127 | } 1128 | 1129 | // Fix Unicode corruption bug 1130 | _parsedData.push(byteArray); 1131 | } 1132 | 1133 | _parsedData = Array.prototype.concat.apply([], _parsedData); 1134 | 1135 | if (_parsedData.length != _data.length) { 1136 | _parsedData.unshift(191); 1137 | _parsedData.unshift(187); 1138 | _parsedData.unshift(239); 1139 | } 1140 | 1141 | var _bytes = _parsedData; 1142 | 1143 | _this.getMode = function() { 1144 | return _mode; 1145 | }; 1146 | 1147 | _this.getLength = function(buffer) { 1148 | return _bytes.length; 1149 | }; 1150 | 1151 | _this.write = function(buffer) { 1152 | for (var i = 0; i < _bytes.length; i += 1) { 1153 | buffer.put(_bytes[i], 8); 1154 | } 1155 | }; 1156 | 1157 | return _this; 1158 | }; 1159 | 1160 | //===================================================================== 1161 | // GIF Support etc. 1162 | // 1163 | 1164 | //--------------------------------------------------------------------- 1165 | // byteArrayOutputStream 1166 | //--------------------------------------------------------------------- 1167 | 1168 | var byteArrayOutputStream = function() { 1169 | 1170 | var _bytes = new Array(); 1171 | 1172 | var _this = {}; 1173 | 1174 | _this.writeByte = function(b) { 1175 | _bytes.push(b & 0xff); 1176 | }; 1177 | 1178 | _this.writeShort = function(i) { 1179 | _this.writeByte(i); 1180 | _this.writeByte(i >>> 8); 1181 | }; 1182 | 1183 | _this.writeBytes = function(b, off, len) { 1184 | off = off || 0; 1185 | len = len || b.length; 1186 | for (var i = 0; i < len; i += 1) { 1187 | _this.writeByte(b[i + off]); 1188 | } 1189 | }; 1190 | 1191 | _this.writeString = function(s) { 1192 | for (var i = 0; i < s.length; i += 1) { 1193 | _this.writeByte(s.charCodeAt(i) ); 1194 | } 1195 | }; 1196 | 1197 | _this.toByteArray = function() { 1198 | return _bytes; 1199 | }; 1200 | 1201 | _this.toString = function() { 1202 | var s = ''; 1203 | s += '['; 1204 | for (var i = 0; i < _bytes.length; i += 1) { 1205 | if (i > 0) { 1206 | s += ','; 1207 | } 1208 | s += _bytes[i]; 1209 | } 1210 | s += ']'; 1211 | return s; 1212 | }; 1213 | 1214 | return _this; 1215 | }; 1216 | 1217 | //--------------------------------------------------------------------- 1218 | // base64EncodeOutputStream 1219 | //--------------------------------------------------------------------- 1220 | 1221 | var base64EncodeOutputStream = function() { 1222 | 1223 | var _buffer = 0; 1224 | var _buflen = 0; 1225 | var _length = 0; 1226 | var _base64 = ''; 1227 | 1228 | var _this = {}; 1229 | 1230 | var writeEncoded = function(b) { 1231 | _base64 += String.fromCharCode(encode(b & 0x3f) ); 1232 | }; 1233 | 1234 | var encode = function(n) { 1235 | if (n < 0) { 1236 | // error. 1237 | } else if (n < 26) { 1238 | return 0x41 + n; 1239 | } else if (n < 52) { 1240 | return 0x61 + (n - 26); 1241 | } else if (n < 62) { 1242 | return 0x30 + (n - 52); 1243 | } else if (n == 62) { 1244 | return 0x2b; 1245 | } else if (n == 63) { 1246 | return 0x2f; 1247 | } 1248 | throw new Error('n:' + n); 1249 | }; 1250 | 1251 | _this.writeByte = function(n) { 1252 | 1253 | _buffer = (_buffer << 8) | (n & 0xff); 1254 | _buflen += 8; 1255 | _length += 1; 1256 | 1257 | while (_buflen >= 6) { 1258 | writeEncoded(_buffer >>> (_buflen - 6) ); 1259 | _buflen -= 6; 1260 | } 1261 | }; 1262 | 1263 | _this.flush = function() { 1264 | 1265 | if (_buflen > 0) { 1266 | writeEncoded(_buffer << (6 - _buflen) ); 1267 | _buffer = 0; 1268 | _buflen = 0; 1269 | } 1270 | 1271 | if (_length % 3 != 0) { 1272 | // padding 1273 | var padlen = 3 - _length % 3; 1274 | for (var i = 0; i < padlen; i += 1) { 1275 | _base64 += '='; 1276 | } 1277 | } 1278 | }; 1279 | 1280 | _this.toString = function() { 1281 | return _base64; 1282 | }; 1283 | 1284 | return _this; 1285 | }; 1286 | 1287 | //--------------------------------------------------------------------- 1288 | // base64DecodeInputStream 1289 | //--------------------------------------------------------------------- 1290 | 1291 | var base64DecodeInputStream = function(str) { 1292 | 1293 | var _str = str; 1294 | var _pos = 0; 1295 | var _buffer = 0; 1296 | var _buflen = 0; 1297 | 1298 | var _this = {}; 1299 | 1300 | _this.read = function() { 1301 | 1302 | while (_buflen < 8) { 1303 | 1304 | if (_pos >= _str.length) { 1305 | if (_buflen == 0) { 1306 | return -1; 1307 | } 1308 | throw new Error('unexpected end of file./' + _buflen); 1309 | } 1310 | 1311 | var c = _str.charAt(_pos); 1312 | _pos += 1; 1313 | 1314 | if (c == '=') { 1315 | _buflen = 0; 1316 | return -1; 1317 | } else if (c.match(/^\s$/) ) { 1318 | // ignore if whitespace. 1319 | continue; 1320 | } 1321 | 1322 | _buffer = (_buffer << 6) | decode(c.charCodeAt(0) ); 1323 | _buflen += 6; 1324 | } 1325 | 1326 | var n = (_buffer >>> (_buflen - 8) ) & 0xff; 1327 | _buflen -= 8; 1328 | return n; 1329 | }; 1330 | 1331 | var decode = function(c) { 1332 | if (0x41 <= c && c <= 0x5a) { 1333 | return c - 0x41; 1334 | } else if (0x61 <= c && c <= 0x7a) { 1335 | return c - 0x61 + 26; 1336 | } else if (0x30 <= c && c <= 0x39) { 1337 | return c - 0x30 + 52; 1338 | } else if (c == 0x2b) { 1339 | return 62; 1340 | } else if (c == 0x2f) { 1341 | return 63; 1342 | } else { 1343 | throw new Error('c:' + c); 1344 | } 1345 | }; 1346 | 1347 | return _this; 1348 | }; 1349 | 1350 | //--------------------------------------------------------------------- 1351 | // gifImage (B/W) 1352 | //--------------------------------------------------------------------- 1353 | 1354 | var gifImage = function(width, height) { 1355 | 1356 | var _width = width; 1357 | var _height = height; 1358 | var _data = new Array(width * height); 1359 | 1360 | var _this = {}; 1361 | 1362 | _this.setPixel = function(x, y, pixel) { 1363 | _data[y * _width + x] = pixel; 1364 | }; 1365 | 1366 | _this.write = function(out) { 1367 | 1368 | //--------------------------------- 1369 | // GIF Signature 1370 | 1371 | out.writeString('GIF87a'); 1372 | 1373 | //--------------------------------- 1374 | // Screen Descriptor 1375 | 1376 | out.writeShort(_width); 1377 | out.writeShort(_height); 1378 | 1379 | out.writeByte(0x80); // 2bit 1380 | out.writeByte(0); 1381 | out.writeByte(0); 1382 | 1383 | //--------------------------------- 1384 | // Global Color Map 1385 | 1386 | // black 1387 | out.writeByte(0x00); 1388 | out.writeByte(0x00); 1389 | out.writeByte(0x00); 1390 | 1391 | // white 1392 | out.writeByte(0xff); 1393 | out.writeByte(0xff); 1394 | out.writeByte(0xff); 1395 | 1396 | //--------------------------------- 1397 | // Image Descriptor 1398 | 1399 | out.writeString(','); 1400 | out.writeShort(0); 1401 | out.writeShort(0); 1402 | out.writeShort(_width); 1403 | out.writeShort(_height); 1404 | out.writeByte(0); 1405 | 1406 | //--------------------------------- 1407 | // Local Color Map 1408 | 1409 | //--------------------------------- 1410 | // Raster Data 1411 | 1412 | var lzwMinCodeSize = 2; 1413 | var raster = getLZWRaster(lzwMinCodeSize); 1414 | 1415 | out.writeByte(lzwMinCodeSize); 1416 | 1417 | var offset = 0; 1418 | 1419 | while (raster.length - offset > 255) { 1420 | out.writeByte(255); 1421 | out.writeBytes(raster, offset, 255); 1422 | offset += 255; 1423 | } 1424 | 1425 | out.writeByte(raster.length - offset); 1426 | out.writeBytes(raster, offset, raster.length - offset); 1427 | out.writeByte(0x00); 1428 | 1429 | //--------------------------------- 1430 | // GIF Terminator 1431 | out.writeString(';'); 1432 | }; 1433 | 1434 | var bitOutputStream = function(out) { 1435 | 1436 | var _out = out; 1437 | var _bitLength = 0; 1438 | var _bitBuffer = 0; 1439 | 1440 | var _this = {}; 1441 | 1442 | _this.write = function(data, length) { 1443 | 1444 | if ( (data >>> length) != 0) { 1445 | throw new Error('length over'); 1446 | } 1447 | 1448 | while (_bitLength + length >= 8) { 1449 | _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) ); 1450 | length -= (8 - _bitLength); 1451 | data >>>= (8 - _bitLength); 1452 | _bitBuffer = 0; 1453 | _bitLength = 0; 1454 | } 1455 | 1456 | _bitBuffer = (data << _bitLength) | _bitBuffer; 1457 | _bitLength = _bitLength + length; 1458 | }; 1459 | 1460 | _this.flush = function() { 1461 | if (_bitLength > 0) { 1462 | _out.writeByte(_bitBuffer); 1463 | } 1464 | }; 1465 | 1466 | return _this; 1467 | }; 1468 | 1469 | var getLZWRaster = function(lzwMinCodeSize) { 1470 | 1471 | var clearCode = 1 << lzwMinCodeSize; 1472 | var endCode = (1 << lzwMinCodeSize) + 1; 1473 | var bitLength = lzwMinCodeSize + 1; 1474 | 1475 | // Setup LZWTable 1476 | var table = lzwTable(); 1477 | 1478 | for (var i = 0; i < clearCode; i += 1) { 1479 | table.add(String.fromCharCode(i) ); 1480 | } 1481 | table.add(String.fromCharCode(clearCode) ); 1482 | table.add(String.fromCharCode(endCode) ); 1483 | 1484 | var byteOut = byteArrayOutputStream(); 1485 | var bitOut = bitOutputStream(byteOut); 1486 | 1487 | // clear code 1488 | bitOut.write(clearCode, bitLength); 1489 | 1490 | var dataIndex = 0; 1491 | 1492 | var s = String.fromCharCode(_data[dataIndex]); 1493 | dataIndex += 1; 1494 | 1495 | while (dataIndex < _data.length) { 1496 | 1497 | var c = String.fromCharCode(_data[dataIndex]); 1498 | dataIndex += 1; 1499 | 1500 | if (table.contains(s + c) ) { 1501 | 1502 | s = s + c; 1503 | 1504 | } else { 1505 | 1506 | bitOut.write(table.indexOf(s), bitLength); 1507 | 1508 | if (table.size() < 0xfff) { 1509 | 1510 | if (table.size() == (1 << bitLength) ) { 1511 | bitLength += 1; 1512 | } 1513 | 1514 | table.add(s + c); 1515 | } 1516 | 1517 | s = c; 1518 | } 1519 | } 1520 | 1521 | bitOut.write(table.indexOf(s), bitLength); 1522 | 1523 | // end code 1524 | bitOut.write(endCode, bitLength); 1525 | 1526 | bitOut.flush(); 1527 | 1528 | return byteOut.toByteArray(); 1529 | }; 1530 | 1531 | var lzwTable = function() { 1532 | 1533 | var _map = {}; 1534 | var _size = 0; 1535 | 1536 | var _this = {}; 1537 | 1538 | _this.add = function(key) { 1539 | if (_this.contains(key) ) { 1540 | throw new Error('dup key:' + key); 1541 | } 1542 | _map[key] = _size; 1543 | _size += 1; 1544 | }; 1545 | 1546 | _this.size = function() { 1547 | return _size; 1548 | }; 1549 | 1550 | _this.indexOf = function(key) { 1551 | return _map[key]; 1552 | }; 1553 | 1554 | _this.contains = function(key) { 1555 | return typeof _map[key] != 'undefined'; 1556 | }; 1557 | 1558 | return _this; 1559 | }; 1560 | 1561 | return _this; 1562 | }; 1563 | 1564 | var createImgTag = function(width, height, getPixel, alt) { 1565 | 1566 | var gif = gifImage(width, height); 1567 | for (var y = 0; y < height; y += 1) { 1568 | for (var x = 0; x < width; x += 1) { 1569 | gif.setPixel(x, y, getPixel(x, y) ); 1570 | } 1571 | } 1572 | 1573 | var b = byteArrayOutputStream(); 1574 | gif.write(b); 1575 | 1576 | var base64 = base64EncodeOutputStream(); 1577 | var bytes = b.toByteArray(); 1578 | for (var i = 0; i < bytes.length; i += 1) { 1579 | base64.writeByte(bytes[i]); 1580 | } 1581 | base64.flush(); 1582 | 1583 | var img = ''; 1584 | img += 'data:image/gif;base64,'; 1585 | img += base64; 1586 | 1587 | return img; 1588 | }; 1589 | 1590 | //--------------------------------------------------------------------- 1591 | // returns qrcode function. 1592 | 1593 | var drawImg = function(text, options) { 1594 | options = options || {}; 1595 | var typeNumber = options.typeNumber || 4; 1596 | var errorCorrectLevel = options.errorCorrectLevel || 'M'; 1597 | var size = options.size || 500; 1598 | 1599 | var qr; 1600 | 1601 | try { 1602 | qr = qrcode(typeNumber, errorCorrectLevel || 'M'); 1603 | qr.addData(text); 1604 | qr.make(); 1605 | } catch (e) { 1606 | if(typeNumber >= 40) { 1607 | throw new Error('Text too long to encode'); 1608 | } else { 1609 | return drawImg(text, { 1610 | size: size, 1611 | errorCorrectLevel: errorCorrectLevel, 1612 | typeNumber: typeNumber + 1 1613 | }); 1614 | } 1615 | } 1616 | 1617 | // calc cellsize and margin 1618 | var cellsize = parseInt(size / qr.getModuleCount()); 1619 | var margin = parseInt((size - qr.getModuleCount() * cellsize) / 2); 1620 | 1621 | return qr.createImgTag(cellsize, margin, size); 1622 | }; 1623 | module.exports = { 1624 | drawImg: drawImg 1625 | }; --------------------------------------------------------------------------------