wxqrcode.js 46 KB

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