qrcode.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. let QRCode={};
  2. (function(){
  3. function unicodeFormat8(code){
  4. var c0,c1,c2;
  5. if(code<128){
  6. return[code];
  7. }else if(code<2048){
  8. c0=192+(code>>6);
  9. c1=128+(code&63);
  10. return[c0,c1];
  11. }else{
  12. c0=224+(code>>12);
  13. c1=128+(code>>6&63);
  14. c2=128+(code&63);
  15. return[c0,c1,c2];
  16. }
  17. }
  18. function getUTF8Bytes(string){
  19. var utf8codes=[];
  20. for(var i=0;i<string.length;i++){
  21. var code=string.charCodeAt(i);
  22. var utf8=unicodeFormat8(code);
  23. for(var j=0;j<utf8.length;j++){
  24. utf8codes.push(utf8[j]);
  25. }
  26. }
  27. return utf8codes;
  28. }
  29. function QRCodeAlg(data,twodimensionalcodeee5conversionmethod){
  30. this.typeNumber=-1;
  31. this.errorCorrectLevel=twodimensionalcodeee5conversionmethod;
  32. this.modules=null;
  33. this.moduleCount=0;
  34. this.dataCache=null;
  35. this.rsBlocks=null;
  36. this.totalDataCount=-1;
  37. this.data=data;
  38. this.utf8bytes=getUTF8Bytes(data);
  39. this.make();
  40. }
  41. QRCodeAlg.prototype={
  42. constructor:QRCodeAlg,
  43. getModuleCount:function(){
  44. return this.moduleCount;
  45. },
  46. make:function(){
  47. this.getRightType();
  48. this.dataCache=this.createData();
  49. this.createQrcode();
  50. },
  51. makeImpl:function(maskPattern){
  52. this.moduleCount=this.typeNumber*4+17;
  53. this.modules=new Array(this.moduleCount);
  54. for(var row=0;row<this.moduleCount;row++){
  55. this.modules[row]=new Array(this.moduleCount);
  56. }
  57. this.setupPositionProbePattern(0,0);
  58. this.setupPositionProbePattern(this.moduleCount-7,0);
  59. this.setupPositionProbePattern(0,this.moduleCount-7);
  60. this.setupPositionAdjustPattern();
  61. this.setupTimingPattern();
  62. this.setupTypeInfo(true,maskPattern);
  63. if(this.typeNumber>=7){
  64. this.setupTypeNumber(true);
  65. }
  66. this.mapData(this.dataCache,maskPattern);
  67. },
  68. setupPositionProbePattern:function(row,col){
  69. for(var r=-1;r<=7;r++){
  70. if(row+r<=-1||this.moduleCount<=row+r)continue;
  71. for(var c=-1;c<=7;c++){
  72. if(col+c<=-1||this.moduleCount<=col+c)continue;
  73. if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){
  74. this.modules[row+r][col+c]=true;
  75. }else{
  76. this.modules[row+r][col+c]=false;
  77. }
  78. }
  79. }
  80. },
  81. createQrcode:function(){
  82. var minLostPoint=0;
  83. var pattern=0;
  84. var bestModules=null;
  85. for(var i=0;i<8;i++){
  86. this.makeImpl(i);
  87. var lostPoint=QRUtil.getLostPoint(this);
  88. if(i==0||minLostPoint>lostPoint){
  89. minLostPoint=lostPoint;
  90. pattern=i;
  91. bestModules=this.modules;
  92. }
  93. }
  94. this.modules=bestModules;
  95. this.setupTypeInfo(false,pattern);
  96. if(this.typeNumber>=7){
  97. this.setupTypeNumber(false);
  98. }
  99. },
  100. setupTimingPattern:function(){
  101. for(var r=8;r<this.moduleCount-8;r++){
  102. if(this.modules[r][6]!=null){
  103. continue;
  104. }
  105. this.modules[r][6]=(r%2==0);
  106. if(this.modules[6][r]!=null){
  107. continue;
  108. }
  109. this.modules[6][r]=(r%2==0);
  110. }
  111. },
  112. setupPositionAdjustPattern:function(){
  113. var pos=QRUtil.getPatternPosition(this.typeNumber);
  114. for(var i=0;i<pos.length;i++){
  115. for(var j=0;j<pos.length;j++){
  116. var row=pos[i];
  117. var col=pos[j];
  118. if(this.modules[row][col]!=null){
  119. continue;
  120. }
  121. for(var r=-2;r<=2;r++){
  122. for(var c=-2;c<=2;c++){
  123. if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){
  124. this.modules[row+r][col+c]=true;
  125. }else{
  126. this.modules[row+r][col+c]=false;
  127. }
  128. }
  129. }
  130. }
  131. }
  132. },
  133. setupTypeNumber:function(test){
  134. var bits=QRUtil.getBCHTypeNumber(this.typeNumber);
  135. for(var i=0;i<18;i++){
  136. var mod=(!test&&((bits>>i)&1)==1);
  137. this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;
  138. this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;
  139. }
  140. },
  141. setupTypeInfo:function(test,maskPattern){
  142. var data=(QRErrorCorrectLevel[this.errorCorrectLevel]<<3)|maskPattern;
  143. var bits=QRUtil.getBCHTypeInfo(data);
  144. for(var i=0;i<15;i++){
  145. var mod=(!test&&((bits>>i)&1)==1);
  146. if(i<6){
  147. this.modules[i][8]=mod;
  148. }else if(i<8){
  149. this.modules[i+1][8]=mod;
  150. }else{
  151. this.modules[this.moduleCount-15+i][8]=mod;
  152. }
  153. var mod=(!test&&((bits>>i)&1)==1);
  154. if(i<8){
  155. this.modules[8][this.moduleCount-i-1]=mod;
  156. }else if(i<9){
  157. this.modules[8][15-i-1+1]=mod;
  158. }else{
  159. this.modules[8][15-i-1]=mod;
  160. }
  161. }
  162. this.modules[this.moduleCount-8][8]=(!test);
  163. },
  164. createData:function(){
  165. var buffer=new QRBitBuffer();
  166. var lengthBits=this.typeNumber>9?16:8;
  167. buffer.put(4,4);
  168. buffer.put(this.utf8bytes.length,lengthBits);
  169. for(var i=0,l=this.utf8bytes.length;i<l;i++){
  170. buffer.put(this.utf8bytes[i],8);
  171. }
  172. if(buffer.length+4<=this.totalDataCount*8){
  173. buffer.put(0,4);
  174. }
  175. while(buffer.length%8!=0){
  176. buffer.putBit(false);
  177. }
  178. while(true){
  179. if(buffer.length>=this.totalDataCount*8){
  180. break;
  181. }
  182. buffer.put(QRCodeAlg.PAD0,8);
  183. if(buffer.length>=this.totalDataCount*8){
  184. break;
  185. }
  186. buffer.put(QRCodeAlg.PAD1,8);
  187. }
  188. return this.createBytes(buffer);
  189. },
  190. createBytes:function(buffer){
  191. var offset=0;
  192. var maxDcCount=0;
  193. var maxEcCount=0;
  194. var length=this.rsBlock.length/3;
  195. var rsBlocks=new Array();
  196. for(var i=0;i<length;i++){
  197. var count=this.rsBlock[i*3+0];
  198. var totalCount=this.rsBlock[i*3+1];
  199. var dataCount=this.rsBlock[i*3+2];
  200. for(var j=0;j<count;j++){
  201. rsBlocks.push([dataCount,totalCount]);
  202. }
  203. }
  204. var dcdata=new Array(rsBlocks.length);
  205. var ecdata=new Array(rsBlocks.length);
  206. for(var r=0;r<rsBlocks.length;r++){
  207. var dcCount=rsBlocks[r][0];
  208. var ecCount=rsBlocks[r][1]-dcCount;
  209. maxDcCount=Math.max(maxDcCount,dcCount);
  210. maxEcCount=Math.max(maxEcCount,ecCount);
  211. dcdata[r]=new Array(dcCount);
  212. for(var i=0;i<dcdata[r].length;i++){
  213. dcdata[r][i]=0xff&buffer.buffer[i+offset];
  214. }
  215. offset+=dcCount;
  216. var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);
  217. var rawPoly=new QRPolynomial(dcdata[r],rsPoly.getLength()-1);
  218. var modPoly=rawPoly.mod(rsPoly);
  219. ecdata[r]=new Array(rsPoly.getLength()-1);
  220. for(var i=0;i<ecdata[r].length;i++){
  221. var modIndex=i+modPoly.getLength()-ecdata[r].length;
  222. ecdata[r][i]=(modIndex>=0)?modPoly.get(modIndex):0;
  223. }
  224. }
  225. var data=new Array(this.totalDataCount);
  226. var index=0;
  227. for(var i=0;i<maxDcCount;i++){
  228. for(var r=0;r<rsBlocks.length;r++){
  229. if(i<dcdata[r].length){
  230. data[index++]=dcdata[r][i];
  231. }
  232. }
  233. }
  234. for(var i=0;i<maxEcCount;i++){
  235. for(var r=0;r<rsBlocks.length;r++){
  236. if(i<ecdata[r].length){
  237. data[index++]=ecdata[r][i];
  238. }
  239. }
  240. }
  241. return data;
  242. },
  243. mapData:function(data,maskPattern){
  244. var inc=-1;
  245. var row=this.moduleCount-1;
  246. var bitIndex=7;
  247. var byteIndex=0;
  248. for(var col=this.moduleCount-1;col>0;col-=2){
  249. if(col==6)col--;
  250. while(true){
  251. for(var c=0;c<2;c++){
  252. if(this.modules[row][col-c]==null){
  253. var dark=false;
  254. if(byteIndex<data.length){
  255. dark=(((data[byteIndex]>>>bitIndex)&1)==1);
  256. }
  257. var mask=QRUtil.getMask(maskPattern,row,col-c);
  258. if(mask){
  259. dark=!dark;
  260. }
  261. this.modules[row][col-c]=dark;
  262. bitIndex--;
  263. if(bitIndex==-1){
  264. byteIndex++;
  265. bitIndex=7;
  266. }
  267. }
  268. }
  269. row+=inc;
  270. if(row<0||this.moduleCount<=row){
  271. row-=inc;
  272. inc=-inc;
  273. break;
  274. }
  275. }
  276. }
  277. }
  278. };
  279. QRCodeAlg.PAD0=0xEC;
  280. QRCodeAlg.PAD1=0x11;
  281. var QRErrorCorrectLevel=[1,0,3,2];
  282. var QRMaskPattern={
  283. PATTERN000:0,
  284. PATTERN001:1,
  285. PATTERN010:2,
  286. PATTERN011:3,
  287. PATTERN100:4,
  288. PATTERN101:5,
  289. PATTERN110:6,
  290. PATTERN111:7
  291. };
  292. var QRUtil={
  293. PATTERN_POSITION_TABLE:[
  294. [],
  295. [6,18],
  296. [6,22],
  297. [6,26],
  298. [6,30],
  299. [6,34],
  300. [6,22,38],
  301. [6,24,42],
  302. [6,26,46],
  303. [6,28,50],
  304. [6,30,54],
  305. [6,32,58],
  306. [6,34,62],
  307. [6,26,46,66],
  308. [6,26,48,70],
  309. [6,26,50,74],
  310. [6,30,54,78],
  311. [6,30,56,82],
  312. [6,30,58,86],
  313. [6,34,62,90],
  314. [6,28,50,72,94],
  315. [6,26,50,74,98],
  316. [6,30,54,78,102],
  317. [6,28,54,80,106],
  318. [6,32,58,84,110],
  319. [6,30,58,86,114],
  320. [6,34,62,90,118],
  321. [6,26,50,74,98,122],
  322. [6,30,54,78,102,126],
  323. [6,26,52,78,104,130],
  324. [6,30,56,82,108,134],
  325. [6,34,60,86,112,138],
  326. [6,30,58,86,114,142],
  327. [6,34,62,90,118,146],
  328. [6,30,54,78,102,126,150],
  329. [6,24,50,76,102,128,154],
  330. [6,28,54,80,106,132,158],
  331. [6,32,58,84,110,136,162],
  332. [6,26,54,82,110,138,166],
  333. [6,30,58,86,114,142,170]
  334. ],
  335. G15:(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0),
  336. G18:(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0),
  337. G15_MASK:(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1),
  338. getBCHTypeInfo:function(data){
  339. var d=data<<10;
  340. while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)>=0){
  341. d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));
  342. }
  343. return((data<<10)|d)^QRUtil.G15_MASK;
  344. },
  345. getBCHTypeNumber:function(data){
  346. var d=data<<12;
  347. while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){
  348. d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));
  349. }
  350. return(data<<12)|d;
  351. },
  352. getBCHDigit:function(data){
  353. var digit=0;
  354. while(data!=0){
  355. digit++;
  356. data>>>=1;
  357. }
  358. return digit;
  359. },
  360. getPatternPosition:function(typeNumber){
  361. return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];
  362. },
  363. getMask:function(maskPattern,i,j){
  364. switch(maskPattern){
  365. case QRMaskPattern.PATTERN000:
  366. return(i+j)%2==0;
  367. case QRMaskPattern.PATTERN001:
  368. return i%2==0;
  369. case QRMaskPattern.PATTERN010:
  370. return j%3==0;
  371. case QRMaskPattern.PATTERN011:
  372. return(i+j)%3==0;
  373. case QRMaskPattern.PATTERN100:
  374. return(Math.floor(i/2)+Math.floor(j/3))%2==0;
  375. case QRMaskPattern.PATTERN101:
  376. return(i*j)%2+(i*j)%3==0;
  377. case QRMaskPattern.PATTERN110:
  378. return((i*j)%2+(i*j)%3)%2==0;
  379. case QRMaskPattern.PATTERN111:
  380. return((i*j)%3+(i+j)%2)%2==0;
  381. default:
  382. throw new Error("bad maskPattern:"+maskPattern);
  383. }
  384. },
  385. getErrorCorrectPolynomial:function(errorCorrectLength){
  386. var a=new QRPolynomial([1],0);
  387. for(var i=0;i<errorCorrectLength;i++){
  388. a=a.multiply(new QRPolynomial([1,QRMath.gexp(i)],0));
  389. }
  390. return a;
  391. },
  392. getLostPoint:function(qrCode){
  393. var moduleCount=qrCode.getModuleCount(),
  394. lostPoint=0,
  395. darkCount=0;
  396. for(var row=0;row<moduleCount;row++){
  397. var sameCount=0;
  398. var head=qrCode.modules[row][0];
  399. for(var col=0;col<moduleCount;col++){
  400. var current=qrCode.modules[row][col];
  401. if(col<moduleCount-6){
  402. if(current&&!qrCode.modules[row][col+1]&&qrCode.modules[row][col+2]&&qrCode.modules[row][col+3]&&qrCode.modules[row][col+4]&&!qrCode.modules[row][col+5]&&qrCode.modules[row][col+6]){
  403. if(col<moduleCount-10){
  404. if(qrCode.modules[row][col+7]&&qrCode.modules[row][col+8]&&qrCode.modules[row][col+9]&&qrCode.modules[row][col+10]){
  405. lostPoint+=40;
  406. }
  407. }else if(col>3){
  408. if(qrCode.modules[row][col-1]&&qrCode.modules[row][col-2]&&qrCode.modules[row][col-3]&&qrCode.modules[row][col-4]){
  409. lostPoint+=40;
  410. }
  411. }
  412. }
  413. }
  414. if((row<moduleCount-1)&&(col<moduleCount-1)){
  415. var count=0;
  416. if(current)count++;
  417. if(qrCode.modules[row+1][col])count++;
  418. if(qrCode.modules[row][col+1])count++;
  419. if(qrCode.modules[row+1][col+1])count++;
  420. if(count==0||count==4){
  421. lostPoint+=3;
  422. }
  423. }
  424. if(head^current){
  425. sameCount++;
  426. }else{
  427. head=current;
  428. if(sameCount>=5){
  429. lostPoint+=(3+sameCount-5);
  430. }
  431. sameCount=1;
  432. }
  433. if(current){
  434. darkCount++;
  435. }
  436. }
  437. }
  438. for(var col=0;col<moduleCount;col++){
  439. var sameCount=0;
  440. var head=qrCode.modules[0][col];
  441. for(var row=0;row<moduleCount;row++){
  442. var current=qrCode.modules[row][col];
  443. if(row<moduleCount-6){
  444. if(current&&!qrCode.modules[row+1][col]&&qrCode.modules[row+2][col]&&qrCode.modules[row+3][col]&&qrCode.modules[row+4][col]&&!qrCode.modules[row+5][col]&&qrCode.modules[row+6][col]){
  445. if(row<moduleCount-10){
  446. if(qrCode.modules[row+7][col]&&qrCode.modules[row+8][col]&&qrCode.modules[row+9][col]&&qrCode.modules[row+10][col]){
  447. lostPoint+=40;
  448. }
  449. }else if(row>3){
  450. if(qrCode.modules[row-1][col]&&qrCode.modules[row-2][col]&&qrCode.modules[row-3][col]&&qrCode.modules[row-4][col]){
  451. lostPoint+=40;
  452. }
  453. }
  454. }
  455. }
  456. if(head^current){
  457. sameCount++;
  458. }else{
  459. head=current;
  460. if(sameCount>=5){
  461. lostPoint+=(3+sameCount-5);
  462. }
  463. sameCount=1;
  464. }
  465. }
  466. }
  467. var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;
  468. lostPoint+=ratio*10;
  469. return lostPoint;
  470. }
  471. };
  472. var QRMath={
  473. glog:function(n){
  474. if(n<1){
  475. throw new Error("glog("+n+")");
  476. }
  477. return QRMath.LOG_TABLE[n];
  478. },
  479. gexp:function(n){
  480. while(n<0){
  481. n+=255;
  482. }
  483. while(n>=256){
  484. n-=255;
  485. }
  486. return QRMath.EXP_TABLE[n];
  487. },
  488. EXP_TABLE:new Array(256),
  489. LOG_TABLE:new Array(256)
  490. };
  491. for(var i=0;i<8;i++){
  492. QRMath.EXP_TABLE[i]=1<<i;
  493. }
  494. for(var i=8;i<256;i++){
  495. QRMath.EXP_TABLE[i]=QRMath.EXP_TABLE[i-4]^QRMath.EXP_TABLE[i-5]^QRMath.EXP_TABLE[i-6]^QRMath.EXP_TABLE[i-8];
  496. }
  497. for(var i=0;i<255;i++){
  498. QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]]=i;
  499. }
  500. function QRPolynomial(num,shift){
  501. if(num.length==undefined){
  502. throw new Error(num.length+"/"+shift);
  503. }
  504. var offset=0;
  505. while(offset<num.length&&num[offset]==0){
  506. offset++;
  507. }
  508. this.num=new Array(num.length-offset+shift);
  509. for(var i=0;i<num.length-offset;i++){
  510. this.num[i]=num[i+offset];
  511. }
  512. }
  513. QRPolynomial.prototype={
  514. get:function(index){
  515. return this.num[index];
  516. },
  517. getLength:function(){
  518. return this.num.length;
  519. },
  520. multiply:function(e){
  521. var num=new Array(this.getLength()+e.getLength()-1);
  522. for(var i=0;i<this.getLength();i++){
  523. for(var j=0;j<e.getLength();j++){
  524. num[i+j]^=QRMath.gexp(QRMath.glog(this.get(i))+QRMath.glog(e.get(j)));
  525. }
  526. }
  527. return new QRPolynomial(num,0);
  528. },
  529. mod:function(e){
  530. var tl=this.getLength(),
  531. el=e.getLength();
  532. if(tl-el<0){
  533. return this;
  534. }
  535. var num=new Array(tl);
  536. for(var i=0;i<tl;i++){
  537. num[i]=this.get(i);
  538. }
  539. while(num.length>=el){
  540. var ratio=QRMath.glog(num[0])-QRMath.glog(e.get(0));
  541. for(var i=0;i<e.getLength();i++){
  542. num[i]^=QRMath.gexp(QRMath.glog(e.get(i))+ratio);
  543. }
  544. while(num[0]==0){
  545. num.shift();
  546. }
  547. }
  548. return new QRPolynomial(num,0);
  549. }
  550. };
  551. var RS_BLOCK_TABLE=[
  552. [1,26,19],
  553. [1,26,16],
  554. [1,26,13],
  555. [1,26,9],
  556. [1,44,34],
  557. [1,44,28],
  558. [1,44,22],
  559. [1,44,16],
  560. [1,70,55],
  561. [1,70,44],
  562. [2,35,17],
  563. [2,35,13],
  564. [1,100,80],
  565. [2,50,32],
  566. [2,50,24],
  567. [4,25,9],
  568. [1,134,108],
  569. [2,67,43],
  570. [2,33,15,2,34,16],
  571. [2,33,11,2,34,12],
  572. [2,86,68],
  573. [4,43,27],
  574. [4,43,19],
  575. [4,43,15],
  576. [2,98,78],
  577. [4,49,31],
  578. [2,32,14,4,33,15],
  579. [4,39,13,1,40,14],
  580. [2,121,97],
  581. [2,60,38,2,61,39],
  582. [4,40,18,2,41,19],
  583. [4,40,14,2,41,15],
  584. [2,146,116],
  585. [3,58,36,2,59,37],
  586. [4,36,16,4,37,17],
  587. [4,36,12,4,37,13],
  588. [2,86,68,2,87,69],
  589. [4,69,43,1,70,44],
  590. [6,43,19,2,44,20],
  591. [6,43,15,2,44,16],
  592. [4,101,81],
  593. [1,80,50,4,81,51],
  594. [4,50,22,4,51,23],
  595. [3,36,12,8,37,13],
  596. [2,116,92,2,117,93],
  597. [6,58,36,2,59,37],
  598. [4,46,20,6,47,21],
  599. [7,42,14,4,43,15],
  600. [4,133,107],
  601. [8,59,37,1,60,38],
  602. [8,44,20,4,45,21],
  603. [12,33,11,4,34,12],
  604. [3,145,115,1,146,116],
  605. [4,64,40,5,65,41],
  606. [11,36,16,5,37,17],
  607. [11,36,12,5,37,13],
  608. [5,109,87,1,110,88],
  609. [5,65,41,5,66,42],
  610. [5,54,24,7,55,25],
  611. [11,36,12],
  612. [5,122,98,1,123,99],
  613. [7,73,45,3,74,46],
  614. [15,43,19,2,44,20],
  615. [3,45,15,13,46,16],
  616. [1,135,107,5,136,108],
  617. [10,74,46,1,75,47],
  618. [1,50,22,15,51,23],
  619. [2,42,14,17,43,15],
  620. [5,150,120,1,151,121],
  621. [9,69,43,4,70,44],
  622. [17,50,22,1,51,23],
  623. [2,42,14,19,43,15],
  624. [3,141,113,4,142,114],
  625. [3,70,44,11,71,45],
  626. [17,47,21,4,48,22],
  627. [9,39,13,16,40,14],
  628. [3,135,107,5,136,108],
  629. [3,67,41,13,68,42],
  630. [15,54,24,5,55,25],
  631. [15,43,15,10,44,16],
  632. [4,144,116,4,145,117],
  633. [17,68,42],
  634. [17,50,22,6,51,23],
  635. [19,46,16,6,47,17],
  636. [2,139,111,7,140,112],
  637. [17,74,46],
  638. [7,54,24,16,55,25],
  639. [34,37,13],
  640. [4,151,121,5,152,122],
  641. [4,75,47,14,76,48],
  642. [11,54,24,14,55,25],
  643. [16,45,15,14,46,16],
  644. [6,147,117,4,148,118],
  645. [6,73,45,14,74,46],
  646. [11,54,24,16,55,25],
  647. [30,46,16,2,47,17],
  648. [8,132,106,4,133,107],
  649. [8,75,47,13,76,48],
  650. [7,54,24,22,55,25],
  651. [22,45,15,13,46,16],
  652. [10,142,114,2,143,115],
  653. [19,74,46,4,75,47],
  654. [28,50,22,6,51,23],
  655. [33,46,16,4,47,17],
  656. [8,152,122,4,153,123],
  657. [22,73,45,3,74,46],
  658. [8,53,23,26,54,24],
  659. [12,45,15,28,46,16],
  660. [3,147,117,10,148,118],
  661. [3,73,45,23,74,46],
  662. [4,54,24,31,55,25],
  663. [11,45,15,31,46,16],
  664. [7,146,116,7,147,117],
  665. [21,73,45,7,74,46],
  666. [1,53,23,37,54,24],
  667. [19,45,15,26,46,16],
  668. [5,145,115,10,146,116],
  669. [19,75,47,10,76,48],
  670. [15,54,24,25,55,25],
  671. [23,45,15,25,46,16],
  672. [13,145,115,3,146,116],
  673. [2,74,46,29,75,47],
  674. [42,54,24,1,55,25],
  675. [23,45,15,28,46,16],
  676. [17,145,115],
  677. [10,74,46,23,75,47],
  678. [10,54,24,35,55,25],
  679. [19,45,15,35,46,16],
  680. [17,145,115,1,146,116],
  681. [14,74,46,21,75,47],
  682. [29,54,24,19,55,25],
  683. [11,45,15,46,46,16],
  684. [13,145,115,6,146,116],
  685. [14,74,46,23,75,47],
  686. [44,54,24,7,55,25],
  687. [59,46,16,1,47,17],
  688. [12,151,121,7,152,122],
  689. [12,75,47,26,76,48],
  690. [39,54,24,14,55,25],
  691. [22,45,15,41,46,16],
  692. [6,151,121,14,152,122],
  693. [6,75,47,34,76,48],
  694. [46,54,24,10,55,25],
  695. [2,45,15,64,46,16],
  696. [17,152,122,4,153,123],
  697. [29,74,46,14,75,47],
  698. [49,54,24,10,55,25],
  699. [24,45,15,46,46,16],
  700. [4,152,122,18,153,123],
  701. [13,74,46,32,75,47],
  702. [48,54,24,14,55,25],
  703. [42,45,15,32,46,16],
  704. [20,147,117,4,148,118],
  705. [40,75,47,7,76,48],
  706. [43,54,24,22,55,25],
  707. [10,45,15,67,46,16],
  708. [19,148,118,6,149,119],
  709. [18,75,47,31,76,48],
  710. [34,54,24,34,55,25],
  711. [20,45,15,61,46,16]
  712. ];
  713. QRCodeAlg.prototype.getRightType=function(){
  714. for(var typeNumber=1;typeNumber<41;typeNumber++){
  715. var rsBlock=RS_BLOCK_TABLE[(typeNumber-1)*4+this.errorCorrectLevel];
  716. if(rsBlock==undefined){
  717. throw new Error("bad rs block @ typeNumber:"+typeNumber+"/errorCorrectLevel:"+this.errorCorrectLevel);
  718. }
  719. var length=rsBlock.length/3;
  720. var totalDataCount=0;
  721. for(var i=0;i<length;i++){
  722. var count=rsBlock[i*3+0];
  723. var dataCount=rsBlock[i*3+2];
  724. totalDataCount+=dataCount*count;
  725. }
  726. var lengthBytes=typeNumber>9?2:1;
  727. if(this.utf8bytes.length+lengthBytes<totalDataCount||typeNumber==40){
  728. this.typeNumber=typeNumber;
  729. this.rsBlock=rsBlock;
  730. this.totalDataCount=totalDataCount;
  731. break;
  732. }
  733. }
  734. };
  735. function QRBitBuffer(){
  736. this.buffer=new Array();
  737. this.length=0;
  738. }
  739. QRBitBuffer.prototype={
  740. get:function(index){
  741. var bufIndex=Math.floor(index/8);
  742. return((this.buffer[bufIndex]>>>(7-index%8))&1);
  743. },
  744. put:function(num,length){
  745. for(var i=0;i<length;i++){
  746. this.putBit(((num>>>(length-i-1))&1));
  747. }
  748. },
  749. putBit:function(bit){
  750. var bufIndex=Math.floor(this.length/8);
  751. if(this.buffer.length<=bufIndex){
  752. this.buffer.push(0);
  753. }
  754. if(bit){
  755. this.buffer[bufIndex]|=(0x80>>>(this.length%8));
  756. }
  757. this.length++;
  758. }
  759. };
  760. let qrcodeAlgObjCache=[];
  761. QRCode=function(opt){
  762. this.options={
  763. text:'',
  764. size:256,
  765. correctLevel:3,
  766. background:'#ffffff',
  767. foreground:'#000000',
  768. pdground:'#000000',
  769. image:'',
  770. imageSize:30,
  771. canvasId:opt.canvasId,
  772. context:opt.context,
  773. usingComponents:opt.usingComponents,
  774. showLoading:opt.showLoading,
  775. loadingText:opt.loadingText,
  776. };
  777. if(typeof opt==='string'){
  778. opt={
  779. text:opt
  780. };
  781. }
  782. if(opt){
  783. for(var i in opt){
  784. this.options[i]=opt[i];
  785. }
  786. }
  787. var qrCodeAlg=null;
  788. for(var i=0,l=qrcodeAlgObjCache.length;i<l;i++){
  789. if(qrcodeAlgObjCache[i].text==this.options.text&&qrcodeAlgObjCache[i].text.correctLevel==this.options.correctLevel){
  790. qrCodeAlg=qrcodeAlgObjCache[i].obj;
  791. break;
  792. }
  793. }
  794. if(i==l){
  795. qrCodeAlg=new QRCodeAlg(this.options.text,this.options.correctLevel);
  796. qrcodeAlgObjCache.push({
  797. text:this.options.text,
  798. correctLevel:this.options.correctLevel,
  799. obj:qrCodeAlg
  800. });
  801. }
  802. let getForeGround=function(config){
  803. var options=config.options;
  804. if(options.pdground&&(
  805. (config.row>1&&config.row<5&&config.col>1&&config.col<5)||
  806. (config.row>(config.count-6)&&config.row<(config.count-2)&&config.col>1&&config.col<5)||
  807. (config.row>1&&config.row<5&&config.col>(config.count-6)&&config.col<(config.count-2))
  808. )){
  809. return options.pdground;
  810. }
  811. return options.foreground;
  812. }
  813. let createCanvas=function(options){
  814. if(options.showLoading){
  815. uni.showLoading({
  816. title:options.loadingText,
  817. mask:true
  818. });
  819. }
  820. var ctx=uni.createCanvasContext(options.canvasId,options.context);
  821. var count=qrCodeAlg.getModuleCount();
  822. var ratioSize=options.size;
  823. var ratioImgSize=options.imageSize;
  824. var tileW=(ratioSize/count).toPrecision(4);
  825. var tileH=(ratioSize/count).toPrecision(4);
  826. for(var row=0;row<count;row++){
  827. for(var col=0;col<count;col++){
  828. var w=(Math.ceil((col+1)*tileW)-Math.floor(col*tileW));
  829. var h=(Math.ceil((row+1)*tileW)-Math.floor(row*tileW));
  830. var foreground=getForeGround({
  831. row:row,
  832. col:col,
  833. count:count,
  834. options:options
  835. });
  836. ctx.setFillStyle(qrCodeAlg.modules[row][col]?foreground:options.background);
  837. ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH),w,h);
  838. }
  839. }
  840. if(options.image){
  841. var x=Number(((ratioSize-ratioImgSize)/2).toFixed(2));
  842. var y=Number(((ratioSize-ratioImgSize)/2).toFixed(2));
  843. drawRoundedRect(ctx,x,y,ratioImgSize,ratioImgSize,2,6,true,true)
  844. ctx.drawImage(options.image,x,y,ratioImgSize,ratioImgSize);
  845. function drawRoundedRect(ctxi,x,y,width,height,r,lineWidth,fill,stroke){
  846. ctxi.setLineWidth(lineWidth);
  847. ctxi.setFillStyle(options.background);
  848. ctxi.setStrokeStyle(options.background);
  849. ctxi.beginPath();
  850. ctxi.moveTo(x+r,y);
  851. ctxi.arcTo(x+width,y,x+width,y+r,r);
  852. ctxi.arcTo(x+width,y+height,x+width-r,y+height,r);
  853. ctxi.arcTo(x,y+height,x,y+height-r,r);
  854. ctxi.arcTo(x,y,x+r,y,r);
  855. ctxi.closePath();
  856. if(fill){
  857. ctxi.fill();
  858. }
  859. if(stroke){
  860. ctxi.stroke();
  861. }
  862. }
  863. }
  864. setTimeout(()=>{
  865. ctx.draw(true,()=>{
  866. setTimeout(()=>{
  867. uni.canvasToTempFilePath({
  868. width:options.width,
  869. height:options.height,
  870. destWidth:options.width,
  871. destHeight:options.height,
  872. canvasId:options.canvasId,
  873. quality:Number(1),
  874. success:function(res){
  875. if(options.cbResult){
  876. options.cbResult(res.tempFilePath)
  877. }
  878. },
  879. fail:function(res){
  880. if(options.cbResult){
  881. options.cbResult(res)
  882. }
  883. },
  884. complete:function(){
  885. if(options.showLoading){
  886. uni.hideLoading();
  887. }
  888. },
  889. },options.context);
  890. },options.text.length+100);
  891. });
  892. },options.usingComponents?0:150);
  893. }
  894. createCanvas(this.options);
  895. let empty=function(v){
  896. let tp=typeof v,
  897. rt=false;
  898. if(tp=="number"&&String(v)==""){
  899. rt=true
  900. }else if(tp=="undefined"){
  901. rt=true
  902. }else if(tp=="object"){
  903. if(JSON.stringify(v)=="{}"||JSON.stringify(v)=="[]"||v==null)rt=true
  904. }else if(tp=="string"){
  905. if(v==""||v=="undefined"||v=="null"||v=="{}"||v=="[]")rt=true
  906. }else if(tp=="function"){
  907. rt=false
  908. }
  909. return rt
  910. }
  911. };
  912. QRCode.prototype.clear=function(fn){
  913. var ctx=uni.createCanvasContext(this.options.canvasId,this.options.context)
  914. ctx.clearRect(0,0,this.options.size,this.options.size)
  915. ctx.draw(false,()=>{
  916. if(fn){
  917. fn()
  918. }
  919. })
  920. };
  921. })()
  922. export default QRCode