小程序生成二维码--简化版

使用:

//wxml文件
<canvas id="qrcode" />
  
//js文件
import qrcode from '../../utils/qrcode'     //引入qrcode.js文件
Page({
    onLoad() {
       wx.createSelectorQuery().select('#qrcode').context(function(res){
            let code = '111'
            qrcode.api.draw(code, {
              ctx: res.context,
              width:170,
              height:170,
          })
      }).exec()
    }
})            

utils/qrcode.js

var QR = (function () {
 
  // alignment pattern
  var adelta = [
    0, 11, 15, 19, 23, 27, 31, // force 1 pat
    16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
    26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
    ];

  // version block
  var vpat = [
      0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d,
      0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9,
      0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75,
      0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64,
      0x541, 0xc69
  ];

  // final format bits with mask: level << 3 | mask
  var fmtword = [
      0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976,    //L
      0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0,    //M
      0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed,    //Q
      0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b    //H
  ];

  // 4 per version: number of blocks 1,2; data width; ecc width
  var eccblocks = [
      1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
      1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
      1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
      1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
      1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
      2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
      2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
      2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
      2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
      2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
      4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
      2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
      4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
      3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
      5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
      5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
      1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
      5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
      3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
      3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
      4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
      2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
      4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
      6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
      8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
      10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
      8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
      3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
      7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
      5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
      13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
      17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
      17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
      13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
      12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
      6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
      17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
      4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
      20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
      19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
  ];

  // Galois field log table
  var glog = [
      0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
      0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
      0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
      0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
      0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
      0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
      0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
      0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
      0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
      0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
      0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
      0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
      0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
      0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
      0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
      0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
  ];

  // Galios field exponent table
  var gexp = [
      0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
      0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
      0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
      0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
      0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
      0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
      0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
      0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
      0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
      0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
      0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
      0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
      0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
      0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
      0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
      0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
  ];

  // Working buffers:
  // data input and ecc append, image working buffer, fixed part of image, run lengths for badness
  var strinbuf=[], eccbuf=[], qrframe=[], framask=[], rlens=[]; 
  // Control values - width is based on version, last 4 are from table.
  var version, width, neccblk1, neccblk2, datablkw, eccblkwid;
  var ecclevel = 2;
  // set bit to indicate cell in qrframe is immutable.  symmetric around diagonal
  function setmask(x, y)
  {
      var bt;
      if (x > y) {
          bt = x;
          x = y;
          y = bt;
      }
      // y*y = 1+3+5...
      bt = y;
      bt *= y;
      bt += y;
      bt >>= 1;
      bt += x;
      framask[bt] = 1;
  }

  // enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
  function putalign(x, y)
  {
      var j;

      qrframe[x + width * y] = 1;
      for (j = -2; j < 2; j++) {
          qrframe[(x + j) + width * (y - 2)] = 1;
          qrframe[(x - 2) + width * (y + j + 1)] = 1;
          qrframe[(x + 2) + width * (y + j)] = 1;
          qrframe[(x + j + 1) + width * (y + 2)] = 1;
      }
      for (j = 0; j < 2; j++) {
          setmask(x - 1, y + j);
          setmask(x + 1, y - j);
          setmask(x - j, y - 1);
          setmask(x + j, y + 1);
      }
  }

  //========================================================================
  // Reed Solomon error correction
  // exponentiation mod N
  function modnn(x)
  {
      while (x >= 255) {
          x -= 255;
          x = (x >> 8) + (x & 255);
      }
      return x;
  }

  var genpoly = [];

  // Calculate and append ECC data to data block.  Block is in strinbuf, indexes to buffers given.
  function appendrs(data, dlen, ecbuf, eclen)
  {
      var i, j, fb;

      for (i = 0; i < eclen; i++)
          strinbuf[ecbuf + i] = 0;
      for (i = 0; i < dlen; i++) {
          fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]];
          if (fb != 255)     /* fb term is non-zero */
              for (j = 1; j < eclen; j++)
                  strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])];
          else
              for( j = ecbuf ; j < ecbuf + eclen; j++ )
                  strinbuf[j] = strinbuf[j + 1];
          strinbuf[ ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])];
      }
  }

  //========================================================================
  // Frame data insert following the path rules

  // check mask - since symmetrical use half.
  function ismasked(x, y)
  {
      var bt;
      if (x > y) {
          bt = x;
          x = y;
          y = bt;
      }
      bt = y;
      bt += y * y;
      bt >>= 1;
      bt += x;
      return framask[bt];
  }

  //========================================================================
  //  Apply the selected mask out of the 8.
  function  applymask(m)
  {
      var x, y, r3x, r3y;

      switch (m) {
      case 0:
          for (y = 0; y < width; y++)
              for (x = 0; x < width; x++)
                  if (!((x + y) & 1) && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
          break;
      case 1:
          for (y = 0; y < width; y++)
              for (x = 0; x < width; x++)
                  if (!(y & 1) && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
          break;
      case 2:
          for (y = 0; y < width; y++)
              for (r3x = 0, x = 0; x < width; x++, r3x++) {
                  if (r3x == 3)
                      r3x = 0;
                  if (!r3x && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
              }
          break;
      case 3:
          for (r3y = 0, y = 0; y < width; y++, r3y++) {
              if (r3y == 3)
                  r3y = 0;
              for (r3x = r3y, x = 0; x < width; x++, r3x++) {
                  if (r3x == 3)
                      r3x = 0;
                  if (!r3x && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
              }
          }
          break;
      case 4:
          for (y = 0; y < width; y++)
              for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) {
                  if (r3x == 3) {
                      r3x = 0;
                      r3y = !r3y;
                  }
                  if (!r3y && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
              }
          break;
      case 5:
          for (r3y = 0, y = 0; y < width; y++, r3y++) {
              if (r3y == 3)
                  r3y = 0;
              for (r3x = 0, x = 0; x < width; x++, r3x++) {
                  if (r3x == 3)
                      r3x = 0;
                  if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
              }
          }
          break;
      case 6:
          for (r3y = 0, y = 0; y < width; y++, r3y++) {
              if (r3y == 3)
                  r3y = 0;
              for (r3x = 0, x = 0; x < width; x++, r3x++) {
                  if (r3x == 3)
                      r3x = 0;
                  if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
              }
          }
          break;
      case 7:
          for (r3y = 0, y = 0; y < width; y++, r3y++) {
              if (r3y == 3)
                  r3y = 0;
              for (r3x = 0, x = 0; x < width; x++, r3x++) {
                  if (r3x == 3)
                      r3x = 0;
                  if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y))
                      qrframe[x + y * width] ^= 1;
              }
          }
          break;
      }
      return;
  }

  // Badness coefficients.
  var N1 = 3, N2 = 3, N3 = 40, N4 = 10;

  // Using the table of the length of each run, calculate the amount of bad image 
  // - long runs or those that look like finders; called twice, once each for X and Y
  function badruns(length)
  {
      var i;
      var runsbad = 0;
      for (i = 0; i <= length; i++)
          if (rlens[i] >= 5)
              runsbad += N1 + rlens[i] - 5;
      // BwBBBwB as in finder
      for (i = 3; i < length - 1; i += 2)
          if (rlens[i - 2] == rlens[i + 2]
              && rlens[i + 2] == rlens[i - 1]
              && rlens[i - 1] == rlens[i + 1]
              && rlens[i - 1] * 3 == rlens[i]
              // white around the black pattern? Not part of spec
              && (rlens[i - 3] == 0 // beginning
                  || i + 3 > length  // end
                  || rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4)
             )
              runsbad += N3;
      return runsbad;
  }

  // Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
  function badcheck()
  {
      var x, y, h, b, b1;
      var thisbad = 0;
      var bw = 0;

      // blocks of same color.
      for (y = 0; y < width - 1; y++)
          for (x = 0; x < width - 1; x++)
              if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y]
                   && qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
                  || !(qrframe[x + width * y] || qrframe[(x + 1) + width * y]
                       || qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
                  thisbad += N2;

      // X runs
      for (y = 0; y < width; y++) {
          rlens[0] = 0;
          for (h = b = x = 0; x < width; x++) {
              if ((b1 = qrframe[x + width * y]) == b)
                  rlens[h]++;
              else
                  rlens[++h] = 1;
              b = b1;
              bw += b ? 1 : -1;
          }
          thisbad += badruns(h);
      }

      // black/white imbalance
      if (bw < 0)
          bw = -bw;

      var big = bw;
      var count = 0;
      big += big << 2;
      big <<= 1;
      while (big > width * width)
          big -= width * width, count++;
      thisbad += count * N4;

      // Y runs
      for (x = 0; x < width; x++) {
          rlens[0] = 0;
          for (h = b = y = 0; y < width; y++) {
              if ((b1 = qrframe[x + width * y]) == b)
                  rlens[h]++;
              else
                  rlens[++h] = 1;
              b = b1;
          }
          thisbad += badruns(h);
      }
      return thisbad;
  }

  function genframe(instring)
  {
      var x, y, k, t, v, i, j, m;

  // find the smallest version that fits the string
      t = instring.length;
      version = 0;
      do {
          version++;
          k = (ecclevel - 1) * 4 + (version - 1) * 16;
          neccblk1 = eccblocks[k++];
          neccblk2 = eccblocks[k++];
          datablkw = eccblocks[k++];
          eccblkwid = eccblocks[k];
          k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9);
          if (t <= k)
              break;
      } while (version < 40);

  // FIXME - insure that it fits insted of being truncated
      width = 17 + 4 * version;

  // allocate, clear and setup data structures
      v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
      for( t = 0; t < v; t++ )
          eccbuf[t] = 0;
      strinbuf = instring.slice(0);

      for( t = 0; t < width * width; t++ )
          qrframe[t] = 0;

      for( t = 0 ; t < (width * (width + 1) + 1) / 2; t++)
          framask[t] = 0;

  // insert finders - black to frame, white to mask
      for (t = 0; t < 3; t++) {
          k = 0;
          y = 0;
          if (t == 1)
              k = (width - 7);
          if (t == 2)
              y = (width - 7);
          qrframe[(y + 3) + width * (k + 3)] = 1;
          for (x = 0; x < 6; x++) {
              qrframe[(y + x) + width * k] = 1;
              qrframe[y + width * (k + x + 1)] = 1;
              qrframe[(y + 6) + width * (k + x)] = 1;
              qrframe[(y + x + 1) + width * (k + 6)] = 1;
          }
          for (x = 1; x < 5; x++) {
              setmask(y + x, k + 1);
              setmask(y + 1, k + x + 1);
              setmask(y + 5, k + x);
              setmask(y + x + 1, k + 5);
          }
          for (x = 2; x < 4; x++) {
              qrframe[(y + x) + width * (k + 2)] = 1;
              qrframe[(y + 2) + width * (k + x + 1)] = 1;
              qrframe[(y + 4) + width * (k + x)] = 1;
              qrframe[(y + x + 1) + width * (k + 4)] = 1;
          }
      }

  // alignment blocks
      if (version > 1) {
          t = adelta[version];
          y = width - 7;
          for (;;) {
              x = width - 7;
              while (x > t - 3) {
                  putalign(x, y);
                  if (x < t)
                      break;
                  x -= t;
              }
              if (y <= t + 9)
                  break;
              y -= t;
              putalign(6, y);
              putalign(y, 6);
          }
      }

  // single black
      qrframe[8 + width * (width - 8)] = 1;

  // timing gap - mask only
      for (y = 0; y < 7; y++) {
          setmask(7, y);
          setmask(width - 8, y);
          setmask(7, y + width - 7);
      }
      for (x = 0; x < 8; x++) {
          setmask(x, 7);
          setmask(x + width - 8, 7);
          setmask(x, width - 8);
      }

  // reserve mask-format area
      for (x = 0; x < 9; x++)
          setmask(x, 8);
      for (x = 0; x < 8; x++) {
          setmask(x + width - 8, 8);
          setmask(8, x);
      }
      for (y = 0; y < 7; y++)
          setmask(8, y + width - 7);

  // timing row/col
      for (x = 0; x < width - 14; x++)
          if (x & 1) {
              setmask(8 + x, 6);
              setmask(6, 8 + x);
          }
          else {
              qrframe[(8 + x) + width * 6] = 1;
              qrframe[6 + width * (8 + x)] = 1;
          }

  // version block
      if (version > 6) {
          t = vpat[version - 7];
          k = 17;
          for (x = 0; x < 6; x++)
              for (y = 0; y < 3; y++, k--)
                  if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
                      qrframe[(5 - x) + width * (2 - y + width - 11)] = 1;
                      qrframe[(2 - y + width - 11) + width * (5 - x)] = 1;
                  }
          else {
              setmask(5 - x, 2 - y + width - 11);
              setmask(2 - y + width - 11, 5 - x);
          }
      }

  // sync mask bits - only set above for white spaces, so add in black bits
      for (y = 0; y < width; y++)
          for (x = 0; x <= y; x++)
              if (qrframe[x + width * y])
                  setmask(x, y);

  // convert string to bitstream
  // 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
      v = strinbuf.length;

  // string to array
      for( i = 0 ; i < v; i++ )
          eccbuf[i] = strinbuf.charCodeAt(i);
      strinbuf = eccbuf.slice(0);

  // calculate max string length
      x = datablkw * (neccblk1 + neccblk2) + neccblk2;
      if (v >= x - 2) {
          v = x - 2;
          if (version > 9)
              v--;
      }

  // shift and repack to insert length prefix
      i = v;
      if (version > 9) {
          strinbuf[i + 2] = 0;
          strinbuf[i + 3] = 0;
          while (i--) {
              t = strinbuf[i];
              strinbuf[i + 3] |= 255 & (t << 4);
              strinbuf[i + 2] = t >> 4;
          }
          strinbuf[2] |= 255 & (v << 4);
          strinbuf[1] = v >> 4;
          strinbuf[0] = 0x40 | (v >> 12);
      }
      else {
          strinbuf[i + 1] = 0;
          strinbuf[i + 2] = 0;
          while (i--) {
              t = strinbuf[i];
              strinbuf[i + 2] |= 255 & (t << 4);
              strinbuf[i + 1] = t >> 4;
          }
          strinbuf[1] |= 255 & (v << 4);
          strinbuf[0] = 0x40 | (v >> 4);
      }
  // fill to end with pad pattern
      i = v + 3 - (version < 10);
      while (i < x) {
          strinbuf[i++] = 0xec;
          // buffer has room    if (i == x)      break;
          strinbuf[i++] = 0x11;
      }

  // calculate and append ECC

  // calculate generator polynomial
      genpoly[0] = 1;
      for (i = 0; i < eccblkwid; i++) {
          genpoly[i + 1] = 1;
          for (j = i; j > 0; j--)
              genpoly[j] = genpoly[j]
              ? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1];
          genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)];
      }
      for (i = 0; i <= eccblkwid; i++)
          genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step

  // append ecc to data buffer
      k = x;
      y = 0;
      for (i = 0; i < neccblk1; i++) {
          appendrs(y, datablkw, k, eccblkwid);
          y += datablkw;
          k += eccblkwid;
      }
      for (i = 0; i < neccblk2; i++) {
          appendrs(y, datablkw + 1, k, eccblkwid);
          y += datablkw + 1;
          k += eccblkwid;
      }
  // interleave blocks
      y = 0;
      for (i = 0; i < datablkw; i++) {
          for (j = 0; j < neccblk1; j++)
              eccbuf[y++] = strinbuf[i + j * datablkw];
          for (j = 0; j < neccblk2; j++)
              eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
      }
      for (j = 0; j < neccblk2; j++)
          eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
      for (i = 0; i < eccblkwid; i++)
          for (j = 0; j < neccblk1 + neccblk2; j++)
              eccbuf[y++] = strinbuf[x + i + j * eccblkwid];
      strinbuf = eccbuf;

  // pack bits into frame avoiding masked area.
      x = y = width - 1;
      k = v = 1;         // up, minus
      /* inteleaved data and ecc codes */
      m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
      for (i = 0; i < m; i++) {
          t = strinbuf[i];
          for (j = 0; j < 8; j++, t <<= 1) {
              if (0x80 & t)
                  qrframe[x + width * y] = 1;
              do {        // find next fill position
                  if (v)
                      x--;
                  else {
                      x++;
                      if (k) {
                          if (y != 0)
                              y--;
                          else {
                              x -= 2;
                              k = !k;
                              if (x == 6) {
                                  x--;
                                  y = 9;
                              }
                          }
                      }
                      else {
                          if (y != width - 1)
                              y++;
                          else {
                              x -= 2;
                              k = !k;
                              if (x == 6) {
                                  x--;
                                  y -= 8;
                              }
                          }
                      }
                  }
                  v = !v;
              } while (ismasked(x, y));
          }
      }

  // save pre-mask copy of frame
      strinbuf = qrframe.slice(0);
      t = 0;           // best
      y = 30000;         // demerit
  // for instead of while since in original arduino code
  // if an early mask was "good enough" it wouldn't try for a better one
  // since they get more complex and take longer.
      for (k = 0; k < 8; k++) {
          applymask(k);      // returns black-white imbalance
          x = badcheck();
          if (x < y) { // current mask better than previous best?
              y = x;
              t = k;
          }
          if (t == 7)
              break;       // don't increment i to a void redoing mask
          qrframe = strinbuf.slice(0); // reset for next pass
      }
      if (t != k)         // redo best mask - none good enough, last wasn't t
          applymask(t);

  // add in final mask/ecclevel bytes
      y = fmtword[t + ((ecclevel - 1) << 3)];
      // low byte
      for (k = 0; k < 8; k++, y >>= 1)
          if (y & 1) {
              qrframe[(width - 1 - k) + width * 8] = 1;
              if (k < 6)
                  qrframe[8 + width * k] = 1;
              else
                  qrframe[8 + width * (k + 1)] = 1;
          }
      // high byte
      for (k = 0; k < 7; k++, y >>= 1)
          if (y & 1) {
              qrframe[8 + width * (width - 7 + k)] = 1;
              if (k)
                  qrframe[(6 - k) + width * 8] = 1;
              else
                  qrframe[7 + width * 8] = 1;
          }

  // return image
      return qrframe;
  }

  var _canvas = null,
      _size = null;

  var api = {

      get ecclevel () {
          return ecclevel;
      },

      set ecclevel (val) {
          ecclevel = val;
      },

      get size () {
          return _size;
      },

      set size (val) {
          _size = val
      },

      get canvas () {
          return _canvas;
      },

      set canvas (el) {
          _canvas = el;
      },

      getFrame: function (string) {
          return genframe(string);
      },

      draw: function (string, canvas, size, ecc) {

          ecclevel = ecc || ecclevel;
          canvas = canvas || _canvas;

          if (!canvas) {
              console.warn('No canvas provided to draw QR code in!')
              return;
          }

          size = size || _size || Math.min(canvas.width, canvas.height);

          var frame = genframe(string),
              ctx = canvas.ctx,
              px = Math.round(size / (width + 8));

          var roundedSize = px * (width + 8),
              offset = Math.floor((size - roundedSize) / 2);

          size = roundedSize;

          ctx.clearRect(0, 0, canvas.width, canvas.height);
          ctx.setFillStyle('#000000');
          for (var i = 0; i < width; i++) {
              for (var j = 0; j < width; j++) {
                  if (frame[j * width + i]) {
                      ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
                  }
              }
          }
          ctx.draw();
      }
  }

  module.exports = {
      api: api
  }

})()
View Code

 

posted @ 2023-10-27 15:46  小那  阅读(50)  评论(0编辑  收藏  举报