You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1624 lines
38 KiB

1 year ago
  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. //---------------微信小程序基于base64生成二维码插件修改-------------------
  18. /*
  19. * @Modified: Pudon
  20. * @demoURL: https://github.com/Pudon/weapp-qrcode
  21. * @Date: 2018-09-11 14:00:05
  22. * @Last Modified by: Pudon
  23. * @Last Modified time: 2018-09-12 16:33:19
  24. */
  25. //---------------------------------------------------------------------
  26. /**
  27. * qrcode
  28. * @param typeNumber 1 to 40
  29. * @param errorCorrectLevel 'L','M','Q','H'
  30. */
  31. var qrcode = function(typeNumber, errorCorrectLevel) {
  32. var PAD0 = 0xEC;
  33. var PAD1 = 0x11;
  34. var _typeNumber = typeNumber;
  35. var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];
  36. var _modules = null;
  37. var _moduleCount = 0;
  38. var _dataCache = null;
  39. var _dataList = new Array();
  40. var _this = {};
  41. var makeImpl = function(test, maskPattern) {
  42. _moduleCount = _typeNumber * 4 + 17;
  43. _modules = function(moduleCount) {
  44. var modules = new Array(moduleCount);
  45. for (var row = 0; row < moduleCount; row += 1) {
  46. modules[row] = new Array(moduleCount);
  47. for (var col = 0; col < moduleCount; col += 1) {
  48. modules[row][col] = null;
  49. }
  50. }
  51. return modules;
  52. }(_moduleCount);
  53. setupPositionProbePattern(0, 0);
  54. setupPositionProbePattern(_moduleCount - 7, 0);
  55. setupPositionProbePattern(0, _moduleCount - 7);
  56. setupPositionAdjustPattern();
  57. setupTimingPattern();
  58. setupTypeInfo(test, maskPattern);
  59. if (_typeNumber >= 7) {
  60. setupTypeNumber(test);
  61. }
  62. if (_dataCache == null) {
  63. _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);
  64. }
  65. mapData(_dataCache, maskPattern);
  66. };
  67. var setupPositionProbePattern = function(row, col) {
  68. for (var r = -1; r <= 7; r += 1) {
  69. if (row + r <= -1 || _moduleCount <= row + r) continue;
  70. for (var c = -1; c <= 7; c += 1) {
  71. if (col + c <= -1 || _moduleCount <= col + c) continue;
  72. if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
  73. || (0 <= c && c <= 6 && (r == 0 || r == 6) )
  74. || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
  75. _modules[row + r][col + c] = true;
  76. } else {
  77. _modules[row + r][col + c] = false;
  78. }
  79. }
  80. }
  81. };
  82. var getBestMaskPattern = function() {
  83. var minLostPoint = 0;
  84. var pattern = 0;
  85. for (var i = 0; i < 8; i += 1) {
  86. makeImpl(true, i);
  87. var lostPoint = QRUtil.getLostPoint(_this);
  88. if (i == 0 || minLostPoint > lostPoint) {
  89. minLostPoint = lostPoint;
  90. pattern = i;
  91. }
  92. }
  93. return pattern;
  94. };
  95. var setupTimingPattern = function() {
  96. for (var r = 8; r < _moduleCount - 8; r += 1) {
  97. if (_modules[r][6] != null) {
  98. continue;
  99. }
  100. _modules[r][6] = (r % 2 == 0);
  101. }
  102. for (var c = 8; c < _moduleCount - 8; c += 1) {
  103. if (_modules[6][c] != null) {
  104. continue;
  105. }
  106. _modules[6][c] = (c % 2 == 0);
  107. }
  108. };
  109. var setupPositionAdjustPattern = function() {
  110. var pos = QRUtil.getPatternPosition(_typeNumber);
  111. for (var i = 0; i < pos.length; i += 1) {
  112. for (var j = 0; j < pos.length; j += 1) {
  113. var row = pos[i];
  114. var col = pos[j];
  115. if (_modules[row][col] != null) {
  116. continue;
  117. }
  118. for (var r = -2; r <= 2; r += 1) {
  119. for (var c = -2; c <= 2; c += 1) {
  120. if (r == -2 || r == 2 || c == -2 || c == 2
  121. || (r == 0 && c == 0) ) {
  122. _modules[row + r][col + c] = true;
  123. } else {
  124. _modules[row + r][col + c] = false;
  125. }
  126. }
  127. }
  128. }
  129. }
  130. };
  131. var setupTypeNumber = function(test) {
  132. var bits = QRUtil.getBCHTypeNumber(_typeNumber);
  133. for (var i = 0; i < 18; i += 1) {
  134. var mod = (!test && ( (bits >> i) & 1) == 1);
  135. _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
  136. }
  137. for (var i = 0; i < 18; i += 1) {
  138. var mod = (!test && ( (bits >> i) & 1) == 1);
  139. _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
  140. }
  141. };
  142. var setupTypeInfo = function(test, maskPattern) {
  143. var data = (_errorCorrectLevel << 3) | maskPattern;
  144. var bits = QRUtil.getBCHTypeInfo(data);
  145. // vertical
  146. for (var i = 0; i < 15; i += 1) {
  147. var mod = (!test && ( (bits >> i) & 1) == 1);
  148. if (i < 6) {
  149. _modules[i][8] = mod;
  150. } else if (i < 8) {
  151. _modules[i + 1][8] = mod;
  152. } else {
  153. _modules[_moduleCount - 15 + i][8] = mod;
  154. }
  155. }
  156. // horizontal
  157. for (var i = 0; i < 15; i += 1) {
  158. var mod = (!test && ( (bits >> i) & 1) == 1);
  159. if (i < 8) {
  160. _modules[8][_moduleCount - i - 1] = mod;
  161. } else if (i < 9) {
  162. _modules[8][15 - i - 1 + 1] = mod;
  163. } else {
  164. _modules[8][15 - i - 1] = mod;
  165. }
  166. }
  167. // fixed module
  168. _modules[_moduleCount - 8][8] = (!test);
  169. };
  170. var mapData = function(data, maskPattern) {
  171. var inc = -1;
  172. var row = _moduleCount - 1;
  173. var bitIndex = 7;
  174. var byteIndex = 0;
  175. var maskFunc = QRUtil.getMaskFunction(maskPattern);
  176. for (var col = _moduleCount - 1; col > 0; col -= 2) {
  177. if (col == 6) col -= 1;
  178. while (true) {
  179. for (var c = 0; c < 2; c += 1) {
  180. if (_modules[row][col - c] == null) {
  181. var dark = false;
  182. if (byteIndex < data.length) {
  183. dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
  184. }
  185. var mask = maskFunc(row, col - c);
  186. if (mask) {
  187. dark = !dark;
  188. }
  189. _modules[row][col - c] = dark;
  190. bitIndex -= 1;
  191. if (bitIndex == -1) {
  192. byteIndex += 1;
  193. bitIndex = 7;
  194. }
  195. }
  196. }
  197. row += inc;
  198. if (row < 0 || _moduleCount <= row) {
  199. row -= inc;
  200. inc = -inc;
  201. break;
  202. }
  203. }
  204. }
  205. };
  206. var createBytes = function(buffer, rsBlocks) {
  207. var offset = 0;
  208. var maxDcCount = 0;
  209. var maxEcCount = 0;
  210. var dcdata = new Array(rsBlocks.length);
  211. var ecdata = new Array(rsBlocks.length);
  212. for (var r = 0; r < rsBlocks.length; r += 1) {
  213. var dcCount = rsBlocks[r].dataCount;
  214. var ecCount = rsBlocks[r].totalCount - dcCount;
  215. maxDcCount = Math.max(maxDcCount, dcCount);
  216. maxEcCount = Math.max(maxEcCount, ecCount);
  217. dcdata[r] = new Array(dcCount);
  218. for (var i = 0; i < dcdata[r].length; i += 1) {
  219. dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
  220. }
  221. offset += dcCount;
  222. var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
  223. var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);
  224. var modPoly = rawPoly.mod(rsPoly);
  225. ecdata[r] = new Array(rsPoly.getLength() - 1);
  226. for (var i = 0; i < ecdata[r].length; i += 1) {
  227. var modIndex = i + modPoly.getLength() - ecdata[r].length;
  228. ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;
  229. }
  230. }
  231. var totalCodeCount = 0;
  232. for (var i = 0; i < rsBlocks.length; i += 1) {
  233. totalCodeCount += rsBlocks[i].totalCount;
  234. }
  235. var data = new Array(totalCodeCount);
  236. var index = 0;
  237. for (var i = 0; i < maxDcCount; i += 1) {
  238. for (var r = 0; r < rsBlocks.length; r += 1) {
  239. if (i < dcdata[r].length) {
  240. data[index] = dcdata[r][i];
  241. index += 1;
  242. }
  243. }
  244. }
  245. for (var i = 0; i < maxEcCount; i += 1) {
  246. for (var r = 0; r < rsBlocks.length; r += 1) {
  247. if (i < ecdata[r].length) {
  248. data[index] = ecdata[r][i];
  249. index += 1;
  250. }
  251. }
  252. }
  253. return data;
  254. };
  255. var createData = function(typeNumber, errorCorrectLevel, dataList) {
  256. var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
  257. var buffer = qrBitBuffer();
  258. for (var i = 0; i < dataList.length; i += 1) {
  259. var data = dataList[i];
  260. buffer.put(data.getMode(), 4);
  261. buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
  262. data.write(buffer);
  263. }
  264. // calc num max data.
  265. var totalDataCount = 0;
  266. for (var i = 0; i < rsBlocks.length; i += 1) {
  267. totalDataCount += rsBlocks[i].dataCount;
  268. }
  269. if (buffer.getLengthInBits() > totalDataCount * 8) {
  270. throw new Error('code length overflow. ('
  271. + buffer.getLengthInBits()
  272. + '>'
  273. + totalDataCount * 8
  274. + ')');
  275. }
  276. // end code
  277. if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
  278. buffer.put(0, 4);
  279. }
  280. // padding
  281. while (buffer.getLengthInBits() % 8 != 0) {
  282. buffer.putBit(false);
  283. }
  284. // padding
  285. while (true) {
  286. if (buffer.getLengthInBits() >= totalDataCount * 8) {
  287. break;
  288. }
  289. buffer.put(PAD0, 8);
  290. if (buffer.getLengthInBits() >= totalDataCount * 8) {
  291. break;
  292. }
  293. buffer.put(PAD1, 8);
  294. }
  295. return createBytes(buffer, rsBlocks);
  296. };
  297. _this.addData = function(data) {
  298. var newData = qr8BitByte(data);
  299. _dataList.push(newData);
  300. _dataCache = null;
  301. };
  302. _this.isDark = function(row, col) {
  303. if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
  304. throw new Error(row + ',' + col);
  305. }
  306. return _modules[row][col];
  307. };
  308. _this.getModuleCount = function() {
  309. return _moduleCount;
  310. };
  311. _this.make = function() {
  312. makeImpl(false, getBestMaskPattern() );
  313. };
  314. _this.createTableTag = function(cellSize, margin) {
  315. cellSize = cellSize || 2;
  316. margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
  317. var qrHtml = '';
  318. qrHtml += '<table style="';
  319. qrHtml += ' border-width: 0px; border-style: none;';
  320. qrHtml += ' border-collapse: collapse;';
  321. qrHtml += ' padding: 0px; margin: ' + margin + 'px;';
  322. qrHtml += '">';
  323. qrHtml += '<tbody>';
  324. for (var r = 0; r < _this.getModuleCount(); r += 1) {
  325. qrHtml += '<tr>';
  326. for (var c = 0; c < _this.getModuleCount(); c += 1) {
  327. qrHtml += '<td style="';
  328. qrHtml += ' border-width: 0px; border-style: none;';
  329. qrHtml += ' border-collapse: collapse;';
  330. qrHtml += ' padding: 0px; margin: 0px;';
  331. qrHtml += ' width: ' + cellSize + 'px;';
  332. qrHtml += ' height: ' + cellSize + 'px;';
  333. qrHtml += ' background-color: ';
  334. qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';
  335. qrHtml += ';';
  336. qrHtml += '"/>';
  337. }
  338. qrHtml += '</tr>';
  339. }
  340. qrHtml += '</tbody>';
  341. qrHtml += '</table>';
  342. return qrHtml;
  343. };
  344. _this.createImgTag = function(cellSize, margin, size) {
  345. cellSize = cellSize || 2;
  346. margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
  347. var min = margin;
  348. var max = _this.getModuleCount() * cellSize + margin;
  349. return createImgTag(size, size, function(x, y) {
  350. if (min <= x && x < max && min <= y && y < max) {
  351. var c = Math.floor( (x - min) / cellSize);
  352. var r = Math.floor( (y - min) / cellSize);
  353. return _this.isDark(r, c)? 0 : 1;
  354. } else {
  355. return 1;
  356. }
  357. } );
  358. };
  359. return _this;
  360. };
  361. //---------------------------------------------------------------------
  362. // qrcode.stringToBytes
  363. //---------------------------------------------------------------------
  364. qrcode.stringToBytes = function(s) {
  365. var bytes = new Array();
  366. for (var i = 0; i < s.length; i += 1) {
  367. var c = s.charCodeAt(i);
  368. bytes.push(c & 0xff);
  369. }
  370. return bytes;
  371. };
  372. //---------------------------------------------------------------------
  373. // qrcode.createStringToBytes
  374. //---------------------------------------------------------------------
  375. /**
  376. * @param unicodeData base64 string of byte array.
  377. * [16bit Unicode],[16bit Bytes], ...
  378. * @param numChars
  379. */
  380. qrcode.createStringToBytes = function(unicodeData, numChars) {
  381. // create conversion map.
  382. var unicodeMap = function() {
  383. var bin = base64DecodeInputStream(unicodeData);
  384. var read = function() {
  385. var b = bin.read();
  386. if (b == -1) throw new Error();
  387. return b;
  388. };
  389. var count = 0;
  390. var unicodeMap = {};
  391. while (true) {
  392. var b0 = bin.read();
  393. if (b0 == -1) break;
  394. var b1 = read();
  395. var b2 = read();
  396. var b3 = read();
  397. var k = String.fromCharCode( (b0 << 8) | b1);
  398. var v = (b2 << 8) | b3;
  399. unicodeMap[k] = v;
  400. count += 1;
  401. }
  402. if (count != numChars) {
  403. throw new Error(count + ' != ' + numChars);
  404. }
  405. return unicodeMap;
  406. }();
  407. var unknownChar = '?'.charCodeAt(0);
  408. return function(s) {
  409. var bytes = new Array();
  410. for (var i = 0; i < s.length; i += 1) {
  411. var c = s.charCodeAt(i);
  412. if (c < 128) {
  413. bytes.push(c);
  414. } else {
  415. var b = unicodeMap[s.charAt(i)];
  416. if (typeof b == 'number') {
  417. if ( (b & 0xff) == b) {
  418. // 1byte
  419. bytes.push(b);
  420. } else {
  421. // 2bytes
  422. bytes.push(b >>> 8);
  423. bytes.push(b & 0xff);
  424. }
  425. } else {
  426. bytes.push(unknownChar);
  427. }
  428. }
  429. }
  430. return bytes;
  431. };
  432. };
  433. //---------------------------------------------------------------------
  434. // QRMode
  435. //---------------------------------------------------------------------
  436. var QRMode = {
  437. MODE_NUMBER : 1 << 0,
  438. MODE_ALPHA_NUM : 1 << 1,
  439. MODE_8BIT_BYTE : 1 << 2,
  440. MODE_KANJI : 1 << 3
  441. };
  442. //---------------------------------------------------------------------
  443. // QRErrorCorrectLevel
  444. //---------------------------------------------------------------------
  445. var QRErrorCorrectLevel = {
  446. L : 1,
  447. M : 0,
  448. Q : 3,
  449. H : 2
  450. };
  451. //---------------------------------------------------------------------
  452. // QRMaskPattern
  453. //---------------------------------------------------------------------
  454. var QRMaskPattern = {
  455. PATTERN000 : 0,
  456. PATTERN001 : 1,
  457. PATTERN010 : 2,
  458. PATTERN011 : 3,
  459. PATTERN100 : 4,
  460. PATTERN101 : 5,
  461. PATTERN110 : 6,
  462. PATTERN111 : 7
  463. };
  464. //---------------------------------------------------------------------
  465. // QRUtil
  466. //---------------------------------------------------------------------
  467. var QRUtil = function() {
  468. var PATTERN_POSITION_TABLE = [
  469. [],
  470. [6, 18],
  471. [6, 22],
  472. [6, 26],
  473. [6, 30],
  474. [6, 34],
  475. [6, 22, 38],
  476. [6, 24, 42],
  477. [6, 26, 46],
  478. [6, 28, 50],
  479. [6, 30, 54],
  480. [6, 32, 58],
  481. [6, 34, 62],
  482. [6, 26, 46, 66],
  483. [6, 26, 48, 70],
  484. [6, 26, 50, 74],
  485. [6, 30, 54, 78],
  486. [6, 30, 56, 82],
  487. [6, 30, 58, 86],
  488. [6, 34, 62, 90],
  489. [6, 28, 50, 72, 94],
  490. [6, 26, 50, 74, 98],
  491. [6, 30, 54, 78, 102],
  492. [6, 28, 54, 80, 106],
  493. [6, 32, 58, 84, 110],
  494. [6, 30, 58, 86, 114],
  495. [6, 34, 62, 90, 118],
  496. [6, 26, 50, 74, 98, 122],
  497. [6, 30, 54, 78, 102, 126],
  498. [6, 26, 52, 78, 104, 130],
  499. [6, 30, 56, 82, 108, 134],
  500. [6, 34, 60, 86, 112, 138],
  501. [6, 30, 58, 86, 114, 142],
  502. [6, 34, 62, 90, 118, 146],
  503. [6, 30, 54, 78, 102, 126, 150],
  504. [6, 24, 50, 76, 102, 128, 154],
  505. [6, 28, 54, 80, 106, 132, 158],
  506. [6, 32, 58, 84, 110, 136, 162],
  507. [6, 26, 54, 82, 110, 138, 166],
  508. [6, 30, 58, 86, 114, 142, 170]
  509. ];
  510. var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
  511. var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
  512. var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
  513. var _this = {};
  514. var getBCHDigit = function(data) {
  515. var digit = 0;
  516. while (data != 0) {
  517. digit += 1;
  518. data >>>= 1;
  519. }
  520. return digit;
  521. };
  522. _this.getBCHTypeInfo = function(data) {
  523. var d = data << 10;
  524. while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
  525. d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
  526. }
  527. return ( (data << 10) | d) ^ G15_MASK;
  528. };
  529. _this.getBCHTypeNumber = function(data) {
  530. var d = data << 12;
  531. while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
  532. d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
  533. }
  534. return (data << 12) | d;
  535. };
  536. _this.getPatternPosition = function(typeNumber) {
  537. return PATTERN_POSITION_TABLE[typeNumber - 1];
  538. };
  539. _this.getMaskFunction = function(maskPattern) {
  540. switch (maskPattern) {
  541. case QRMaskPattern.PATTERN000 :
  542. return function(i, j) { return (i + j) % 2 == 0; };
  543. case QRMaskPattern.PATTERN001 :
  544. return function(i, j) { return i % 2 == 0; };
  545. case QRMaskPattern.PATTERN010 :
  546. return function(i, j) { return j % 3 == 0; };
  547. case QRMaskPattern.PATTERN011 :
  548. return function(i, j) { return (i + j) % 3 == 0; };
  549. case QRMaskPattern.PATTERN100 :
  550. return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
  551. case QRMaskPattern.PATTERN101 :
  552. return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
  553. case QRMaskPattern.PATTERN110 :
  554. return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
  555. case QRMaskPattern.PATTERN111 :
  556. return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };
  557. default :
  558. throw new Error('bad maskPattern:' + maskPattern);
  559. }
  560. };
  561. _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
  562. var a = qrPolynomial([1], 0);
  563. for (var i = 0; i < errorCorrectLength; i += 1) {
  564. a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
  565. }
  566. return a;
  567. };
  568. _this.getLengthInBits = function(mode, type) {
  569. if (1 <= type && type < 10) {
  570. // 1 - 9
  571. switch(mode) {
  572. case QRMode.MODE_NUMBER : return 10;
  573. case QRMode.MODE_ALPHA_NUM : return 9;
  574. case QRMode.MODE_8BIT_BYTE : return 8;
  575. case QRMode.MODE_KANJI : return 8;
  576. default :
  577. throw new Error('mode:' + mode);
  578. }
  579. } else if (type < 27) {
  580. // 10 - 26
  581. switch(mode) {
  582. case QRMode.MODE_NUMBER : return 12;
  583. case QRMode.MODE_ALPHA_NUM : return 11;
  584. case QRMode.MODE_8BIT_BYTE : return 16;
  585. case QRMode.MODE_KANJI : return 10;
  586. default :
  587. throw new Error('mode:' + mode);
  588. }
  589. } else if (type < 41) {
  590. // 27 - 40
  591. switch(mode) {
  592. case QRMode.MODE_NUMBER : return 14;
  593. case QRMode.MODE_ALPHA_NUM : return 13;
  594. case QRMode.MODE_8BIT_BYTE : return 16;
  595. case QRMode.MODE_KANJI : return 12;
  596. default :
  597. throw new Error('mode:' + mode);
  598. }
  599. } else {
  600. throw new Error('type:' + type);
  601. }
  602. };
  603. _this.getLostPoint = function(qrcode) {
  604. var moduleCount = qrcode.getModuleCount();
  605. var lostPoint = 0;
  606. // LEVEL1
  607. for (var row = 0; row < moduleCount; row += 1) {
  608. for (var col = 0; col < moduleCount; col += 1) {
  609. var sameCount = 0;
  610. var dark = qrcode.isDark(row, col);
  611. for (var r = -1; r <= 1; r += 1) {
  612. if (row + r < 0 || moduleCount <= row + r) {
  613. continue;
  614. }
  615. for (var c = -1; c <= 1; c += 1) {
  616. if (col + c < 0 || moduleCount <= col + c) {
  617. continue;
  618. }
  619. if (r == 0 && c == 0) {
  620. continue;
  621. }
  622. if (dark == qrcode.isDark(row + r, col + c) ) {
  623. sameCount += 1;
  624. }
  625. }
  626. }
  627. if (sameCount > 5) {
  628. lostPoint += (3 + sameCount - 5);
  629. }
  630. }
  631. };
  632. // LEVEL2
  633. for (var row = 0; row < moduleCount - 1; row += 1) {
  634. for (var col = 0; col < moduleCount - 1; col += 1) {
  635. var count = 0;
  636. if (qrcode.isDark(row, col) ) count += 1;
  637. if (qrcode.isDark(row + 1, col) ) count += 1;
  638. if (qrcode.isDark(row, col + 1) ) count += 1;
  639. if (qrcode.isDark(row + 1, col + 1) ) count += 1;
  640. if (count == 0 || count == 4) {
  641. lostPoint += 3;
  642. }
  643. }
  644. }
  645. // LEVEL3
  646. for (var row = 0; row < moduleCount; row += 1) {
  647. for (var col = 0; col < moduleCount - 6; col += 1) {
  648. if (qrcode.isDark(row, col)
  649. && !qrcode.isDark(row, col + 1)
  650. && qrcode.isDark(row, col + 2)
  651. && qrcode.isDark(row, col + 3)
  652. && qrcode.isDark(row, col + 4)
  653. && !qrcode.isDark(row, col + 5)
  654. && qrcode.isDark(row, col + 6) ) {
  655. lostPoint += 40;
  656. }
  657. }
  658. }
  659. for (var col = 0; col < moduleCount; col += 1) {
  660. for (var row = 0; row < moduleCount - 6; row += 1) {
  661. if (qrcode.isDark(row, col)
  662. && !qrcode.isDark(row + 1, col)
  663. && qrcode.isDark(row + 2, col)
  664. && qrcode.isDark(row + 3, col)
  665. && qrcode.isDark(row + 4, col)
  666. && !qrcode.isDark(row + 5, col)
  667. && qrcode.isDark(row + 6, col) ) {
  668. lostPoint += 40;
  669. }
  670. }
  671. }
  672. // LEVEL4
  673. var darkCount = 0;
  674. for (var col = 0; col < moduleCount; col += 1) {
  675. for (var row = 0; row < moduleCount; row += 1) {
  676. if (qrcode.isDark(row, col) ) {
  677. darkCount += 1;
  678. }
  679. }
  680. }
  681. var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
  682. lostPoint += ratio * 10;
  683. return lostPoint;
  684. };
  685. return _this;
  686. }();
  687. //---------------------------------------------------------------------
  688. // QRMath
  689. //---------------------------------------------------------------------
  690. var QRMath = function() {
  691. var EXP_TABLE = new Array(256);
  692. var LOG_TABLE = new Array(256);
  693. // initialize tables
  694. for (var i = 0; i < 8; i += 1) {
  695. EXP_TABLE[i] = 1 << i;
  696. }
  697. for (var i = 8; i < 256; i += 1) {
  698. EXP_TABLE[i] = EXP_TABLE[i - 4]
  699. ^ EXP_TABLE[i - 5]
  700. ^ EXP_TABLE[i - 6]
  701. ^ EXP_TABLE[i - 8];
  702. }
  703. for (var i = 0; i < 255; i += 1) {
  704. LOG_TABLE[EXP_TABLE[i] ] = i;
  705. }
  706. var _this = {};
  707. _this.glog = function(n) {
  708. if (n < 1) {
  709. throw new Error('glog(' + n + ')');
  710. }
  711. return LOG_TABLE[n];
  712. };
  713. _this.gexp = function(n) {
  714. while (n < 0) {
  715. n += 255;
  716. }
  717. while (n >= 256) {
  718. n -= 255;
  719. }
  720. return EXP_TABLE[n];
  721. };
  722. return _this;
  723. }();
  724. //---------------------------------------------------------------------
  725. // qrPolynomial
  726. //---------------------------------------------------------------------
  727. function qrPolynomial(num, shift) {
  728. if (typeof num.length == 'undefined') {
  729. throw new Error(num.length + '/' + shift);
  730. }
  731. var _num = function() {
  732. var offset = 0;
  733. while (offset < num.length && num[offset] == 0) {
  734. offset += 1;
  735. }
  736. var _num = new Array(num.length - offset + shift);
  737. for (var i = 0; i < num.length - offset; i += 1) {
  738. _num[i] = num[i + offset];
  739. }
  740. return _num;
  741. }();
  742. var _this = {};
  743. _this.getAt = function(index) {
  744. return _num[index];
  745. };
  746. _this.getLength = function() {
  747. return _num.length;
  748. };
  749. _this.multiply = function(e) {
  750. var num = new Array(_this.getLength() + e.getLength() - 1);
  751. for (var i = 0; i < _this.getLength(); i += 1) {
  752. for (var j = 0; j < e.getLength(); j += 1) {
  753. num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );
  754. }
  755. }
  756. return qrPolynomial(num, 0);
  757. };
  758. _this.mod = function(e) {
  759. if (_this.getLength() - e.getLength() < 0) {
  760. return _this;
  761. }
  762. var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );
  763. var num = new Array(_this.getLength() );
  764. for (var i = 0; i < _this.getLength(); i += 1) {
  765. num[i] = _this.getAt(i);
  766. }
  767. for (var i = 0; i < e.getLength(); i += 1) {
  768. num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
  769. }
  770. // recursive call
  771. return qrPolynomial(num, 0).mod(e);
  772. };
  773. return _this;
  774. };
  775. //---------------------------------------------------------------------
  776. // QRRSBlock
  777. //---------------------------------------------------------------------
  778. var QRRSBlock = function() {
  779. // [1: [L, M, Q, H], ..]
  780. 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]];
  781. var qrRSBlock = function(totalCount, dataCount) {
  782. var _this = {};
  783. _this.totalCount = totalCount;
  784. _this.dataCount = dataCount;
  785. return _this;
  786. };
  787. var _this = {};
  788. var getRsBlockTable = function(typeNumber, errorCorrectLevel) {
  789. switch(errorCorrectLevel) {
  790. case QRErrorCorrectLevel.L :
  791. return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
  792. case QRErrorCorrectLevel.M :
  793. return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
  794. case QRErrorCorrectLevel.Q :
  795. return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
  796. case QRErrorCorrectLevel.H :
  797. return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
  798. default :
  799. return undefined;
  800. }
  801. };
  802. _this.getRSBlocks = function(typeNumber, errorCorrectLevel) {
  803. var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);
  804. if (typeof rsBlock == 'undefined') {
  805. throw new Error('bad rs block @ typeNumber:' + typeNumber +
  806. '/errorCorrectLevel:' + errorCorrectLevel);
  807. }
  808. var length = rsBlock.length / 3;
  809. var list = new Array();
  810. for (var i = 0; i < length; i += 1) {
  811. var count = rsBlock[i * 3 + 0];
  812. var totalCount = rsBlock[i * 3 + 1];
  813. var dataCount = rsBlock[i * 3 + 2];
  814. for (var j = 0; j < count; j += 1) {
  815. list.push(qrRSBlock(totalCount, dataCount) );
  816. }
  817. }
  818. return list;
  819. };
  820. return _this;
  821. }();
  822. //---------------------------------------------------------------------
  823. // qrBitBuffer
  824. //---------------------------------------------------------------------
  825. var qrBitBuffer = function() {
  826. var _buffer = new Array();
  827. var _length = 0;
  828. var _this = {};
  829. _this.getBuffer = function() {
  830. return _buffer;
  831. };
  832. _this.getAt = function(index) {
  833. var bufIndex = Math.floor(index / 8);
  834. return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
  835. };
  836. _this.put = function(num, length) {
  837. for (var i = 0; i < length; i += 1) {
  838. _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
  839. }
  840. };
  841. _this.getLengthInBits = function() {
  842. return _length;
  843. };
  844. _this.putBit = function(bit) {
  845. var bufIndex = Math.floor(_length / 8);
  846. if (_buffer.length <= bufIndex) {
  847. _buffer.push(0);
  848. }
  849. if (bit) {
  850. _buffer[bufIndex] |= (0x80 >>> (_length % 8) );
  851. }
  852. _length += 1;
  853. };
  854. return _this;
  855. };
  856. //---------------------------------------------------------------------
  857. // qr8BitByte
  858. //---------------------------------------------------------------------
  859. var qr8BitByte = function(data) {
  860. var _mode = QRMode.MODE_8BIT_BYTE;
  861. var _data = data;
  862. var _parsedData = [];
  863. var _this = {};
  864. // Added to support UTF-8 Characters
  865. for (var i = 0, l = _data.length; i < l; i++) {
  866. var byteArray = [];
  867. var code = _data.charCodeAt(i);
  868. if (code > 0x10000) {
  869. byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
  870. byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
  871. byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
  872. byteArray[3] = 0x80 | (code & 0x3F);
  873. } else if (code > 0x800) {
  874. byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
  875. byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
  876. byteArray[2] = 0x80 | (code & 0x3F);
  877. } else if (code > 0x80) {
  878. byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
  879. byteArray[1] = 0x80 | (code & 0x3F);
  880. } else {
  881. byteArray[0] = code;
  882. }
  883. // Fix Unicode corruption bug
  884. _parsedData.push(byteArray);
  885. }
  886. _parsedData = Array.prototype.concat.apply([], _parsedData);
  887. if (_parsedData.length != _data.length) {
  888. _parsedData.unshift(191);
  889. _parsedData.unshift(187);
  890. _parsedData.unshift(239);
  891. }
  892. var _bytes = _parsedData;
  893. _this.getMode = function() {
  894. return _mode;
  895. };
  896. _this.getLength = function(buffer) {
  897. return _bytes.length;
  898. };
  899. _this.write = function(buffer) {
  900. for (var i = 0; i < _bytes.length; i += 1) {
  901. buffer.put(_bytes[i], 8);
  902. }
  903. };
  904. return _this;
  905. };
  906. //=====================================================================
  907. // GIF Support etc.
  908. //
  909. //---------------------------------------------------------------------
  910. // byteArrayOutputStream
  911. //---------------------------------------------------------------------
  912. var byteArrayOutputStream = function() {
  913. var _bytes = new Array();
  914. var _this = {};
  915. _this.writeByte = function(b) {
  916. _bytes.push(b & 0xff);
  917. };
  918. _this.writeShort = function(i) {
  919. _this.writeByte(i);
  920. _this.writeByte(i >>> 8);
  921. };
  922. _this.writeBytes = function(b, off, len) {
  923. off = off || 0;
  924. len = len || b.length;
  925. for (var i = 0; i < len; i += 1) {
  926. _this.writeByte(b[i + off]);
  927. }
  928. };
  929. _this.writeString = function(s) {
  930. for (var i = 0; i < s.length; i += 1) {
  931. _this.writeByte(s.charCodeAt(i) );
  932. }
  933. };
  934. _this.toByteArray = function() {
  935. return _bytes;
  936. };
  937. _this.toString = function() {
  938. var s = '';
  939. s += '[';
  940. for (var i = 0; i < _bytes.length; i += 1) {
  941. if (i > 0) {
  942. s += ',';
  943. }
  944. s += _bytes[i];
  945. }
  946. s += ']';
  947. return s;
  948. };
  949. return _this;
  950. };
  951. //---------------------------------------------------------------------
  952. // base64EncodeOutputStream
  953. //---------------------------------------------------------------------
  954. var base64EncodeOutputStream = function() {
  955. var _buffer = 0;
  956. var _buflen = 0;
  957. var _length = 0;
  958. var _base64 = '';
  959. var _this = {};
  960. var writeEncoded = function(b) {
  961. _base64 += String.fromCharCode(encode(b & 0x3f) );
  962. };
  963. var encode = function(n) {
  964. if (n < 0) {
  965. // error.
  966. } else if (n < 26) {
  967. return 0x41 + n;
  968. } else if (n < 52) {
  969. return 0x61 + (n - 26);
  970. } else if (n < 62) {
  971. return 0x30 + (n - 52);
  972. } else if (n == 62) {
  973. return 0x2b;
  974. } else if (n == 63) {
  975. return 0x2f;
  976. }
  977. throw new Error('n:' + n);
  978. };
  979. _this.writeByte = function(n) {
  980. _buffer = (_buffer << 8) | (n & 0xff);
  981. _buflen += 8;
  982. _length += 1;
  983. while (_buflen >= 6) {
  984. writeEncoded(_buffer >>> (_buflen - 6) );
  985. _buflen -= 6;
  986. }
  987. };
  988. _this.flush = function() {
  989. if (_buflen > 0) {
  990. writeEncoded(_buffer << (6 - _buflen) );
  991. _buffer = 0;
  992. _buflen = 0;
  993. }
  994. if (_length % 3 != 0) {
  995. // padding
  996. var padlen = 3 - _length % 3;
  997. for (var i = 0; i < padlen; i += 1) {
  998. _base64 += '=';
  999. }
  1000. }
  1001. };
  1002. _this.toString = function() {
  1003. return _base64;
  1004. };
  1005. return _this;
  1006. };
  1007. //---------------------------------------------------------------------
  1008. // base64DecodeInputStream
  1009. //---------------------------------------------------------------------
  1010. var base64DecodeInputStream = function(str) {
  1011. var _str = str;
  1012. var _pos = 0;
  1013. var _buffer = 0;
  1014. var _buflen = 0;
  1015. var _this = {};
  1016. _this.read = function() {
  1017. while (_buflen < 8) {
  1018. if (_pos >= _str.length) {
  1019. if (_buflen == 0) {
  1020. return -1;
  1021. }
  1022. throw new Error('unexpected end of file./' + _buflen);
  1023. }
  1024. var c = _str.charAt(_pos);
  1025. _pos += 1;
  1026. if (c == '=') {
  1027. _buflen = 0;
  1028. return -1;
  1029. } else if (c.match(/^\s$/) ) {
  1030. // ignore if whitespace.
  1031. continue;
  1032. }
  1033. _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
  1034. _buflen += 6;
  1035. }
  1036. var n = (_buffer >>> (_buflen - 8) ) & 0xff;
  1037. _buflen -= 8;
  1038. return n;
  1039. };
  1040. var decode = function(c) {
  1041. if (0x41 <= c && c <= 0x5a) {
  1042. return c - 0x41;
  1043. } else if (0x61 <= c && c <= 0x7a) {
  1044. return c - 0x61 + 26;
  1045. } else if (0x30 <= c && c <= 0x39) {
  1046. return c - 0x30 + 52;
  1047. } else if (c == 0x2b) {
  1048. return 62;
  1049. } else if (c == 0x2f) {
  1050. return 63;
  1051. } else {
  1052. throw new Error('c:' + c);
  1053. }
  1054. };
  1055. return _this;
  1056. };
  1057. //---------------------------------------------------------------------
  1058. // gifImage (B/W)
  1059. //---------------------------------------------------------------------
  1060. var gifImage = function(width, height) {
  1061. var _width = width;
  1062. var _height = height;
  1063. var _data = new Array(width * height);
  1064. var _this = {};
  1065. _this.setPixel = function(x, y, pixel) {
  1066. _data[y * _width + x] = pixel;
  1067. };
  1068. _this.write = function(out) {
  1069. //---------------------------------
  1070. // GIF Signature
  1071. out.writeString('GIF87a');
  1072. //---------------------------------
  1073. // Screen Descriptor
  1074. out.writeShort(_width);
  1075. out.writeShort(_height);
  1076. out.writeByte(0x80); // 2bit
  1077. out.writeByte(0);
  1078. out.writeByte(0);
  1079. //---------------------------------
  1080. // Global Color Map
  1081. // black
  1082. out.writeByte(0x00);
  1083. out.writeByte(0x00);
  1084. out.writeByte(0x00);
  1085. // white
  1086. out.writeByte(0xff);
  1087. out.writeByte(0xff);
  1088. out.writeByte(0xff);
  1089. //---------------------------------
  1090. // Image Descriptor
  1091. out.writeString(',');
  1092. out.writeShort(0);
  1093. out.writeShort(0);
  1094. out.writeShort(_width);
  1095. out.writeShort(_height);
  1096. out.writeByte(0);
  1097. //---------------------------------
  1098. // Local Color Map
  1099. //---------------------------------
  1100. // Raster Data
  1101. var lzwMinCodeSize = 2;
  1102. var raster = getLZWRaster(lzwMinCodeSize);
  1103. out.writeByte(lzwMinCodeSize);
  1104. var offset = 0;
  1105. while (raster.length - offset > 255) {
  1106. out.writeByte(255);
  1107. out.writeBytes(raster, offset, 255);
  1108. offset += 255;
  1109. }
  1110. out.writeByte(raster.length - offset);
  1111. out.writeBytes(raster, offset, raster.length - offset);
  1112. out.writeByte(0x00);
  1113. //---------------------------------
  1114. // GIF Terminator
  1115. out.writeString(';');
  1116. };
  1117. var bitOutputStream = function(out) {
  1118. var _out = out;
  1119. var _bitLength = 0;
  1120. var _bitBuffer = 0;
  1121. var _this = {};
  1122. _this.write = function(data, length) {
  1123. if ( (data >>> length) != 0) {
  1124. throw new Error('length over');
  1125. }
  1126. while (_bitLength + length >= 8) {
  1127. _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
  1128. length -= (8 - _bitLength);
  1129. data >>>= (8 - _bitLength);
  1130. _bitBuffer = 0;
  1131. _bitLength = 0;
  1132. }
  1133. _bitBuffer = (data << _bitLength) | _bitBuffer;
  1134. _bitLength = _bitLength + length;
  1135. };
  1136. _this.flush = function() {
  1137. if (_bitLength > 0) {
  1138. _out.writeByte(_bitBuffer);
  1139. }
  1140. };
  1141. return _this;
  1142. };
  1143. var getLZWRaster = function(lzwMinCodeSize) {
  1144. var clearCode = 1 << lzwMinCodeSize;
  1145. var endCode = (1 << lzwMinCodeSize) + 1;
  1146. var bitLength = lzwMinCodeSize + 1;
  1147. // Setup LZWTable
  1148. var table = lzwTable();
  1149. for (var i = 0; i < clearCode; i += 1) {
  1150. table.add(String.fromCharCode(i) );
  1151. }
  1152. table.add(String.fromCharCode(clearCode) );
  1153. table.add(String.fromCharCode(endCode) );
  1154. var byteOut = byteArrayOutputStream();
  1155. var bitOut = bitOutputStream(byteOut);
  1156. // clear code
  1157. bitOut.write(clearCode, bitLength);
  1158. var dataIndex = 0;
  1159. var s = String.fromCharCode(_data[dataIndex]);
  1160. dataIndex += 1;
  1161. while (dataIndex < _data.length) {
  1162. var c = String.fromCharCode(_data[dataIndex]);
  1163. dataIndex += 1;
  1164. if (table.contains(s + c) ) {
  1165. s = s + c;
  1166. } else {
  1167. bitOut.write(table.indexOf(s), bitLength);
  1168. if (table.size() < 0xfff) {
  1169. if (table.size() == (1 << bitLength) ) {
  1170. bitLength += 1;
  1171. }
  1172. table.add(s + c);
  1173. }
  1174. s = c;
  1175. }
  1176. }
  1177. bitOut.write(table.indexOf(s), bitLength);
  1178. // end code
  1179. bitOut.write(endCode, bitLength);
  1180. bitOut.flush();
  1181. return byteOut.toByteArray();
  1182. };
  1183. var lzwTable = function() {
  1184. var _map = {};
  1185. var _size = 0;
  1186. var _this = {};
  1187. _this.add = function(key) {
  1188. if (_this.contains(key) ) {
  1189. throw new Error('dup key:' + key);
  1190. }
  1191. _map[key] = _size;
  1192. _size += 1;
  1193. };
  1194. _this.size = function() {
  1195. return _size;
  1196. };
  1197. _this.indexOf = function(key) {
  1198. return _map[key];
  1199. };
  1200. _this.contains = function(key) {
  1201. return typeof _map[key] != 'undefined';
  1202. };
  1203. return _this;
  1204. };
  1205. return _this;
  1206. };
  1207. var createImgTag = function(width, height, getPixel, alt) {
  1208. var gif = gifImage(width, height);
  1209. for (var y = 0; y < height; y += 1) {
  1210. for (var x = 0; x < width; x += 1) {
  1211. gif.setPixel(x, y, getPixel(x, y) );
  1212. }
  1213. }
  1214. var b = byteArrayOutputStream();
  1215. gif.write(b);
  1216. var base64 = base64EncodeOutputStream();
  1217. var bytes = b.toByteArray();
  1218. for (var i = 0; i < bytes.length; i += 1) {
  1219. base64.writeByte(bytes[i]);
  1220. }
  1221. base64.flush();
  1222. var img = '';
  1223. img += 'data:image/gif;base64,';
  1224. img += base64;
  1225. return img;
  1226. };
  1227. //---------------------------------------------------------------------
  1228. // returns qrcode function.
  1229. var drawImg = function(text, options) {
  1230. options = options || {};
  1231. var typeNumber = options.typeNumber || 4;
  1232. var errorCorrectLevel = options.errorCorrectLevel || 'M';
  1233. var size = options.size || 500;
  1234. var qr;
  1235. try {
  1236. qr = qrcode(typeNumber, errorCorrectLevel || 'M');
  1237. qr.addData(text);
  1238. qr.make();
  1239. } catch (e) {
  1240. if(typeNumber >= 40) {
  1241. throw new Error('Text too long to encode');
  1242. } else {
  1243. return drawImg(text, {
  1244. size: size,
  1245. errorCorrectLevel: errorCorrectLevel,
  1246. typeNumber: typeNumber + 1
  1247. });
  1248. }
  1249. }
  1250. // calc cellsize and margin
  1251. var cellsize = parseInt(size / qr.getModuleCount());
  1252. var margin = parseInt((size - qr.getModuleCount() * cellsize) / 2);
  1253. return qr.createImgTag(cellsize, margin, size);
  1254. };
  1255. module.exports = {
  1256. drawImg: drawImg
  1257. };