tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

qrcode.mjs (51921B)


      1 //---------------------------------------------------------------------
      2 //
      3 // QR Code Generator for JavaScript
      4 //
      5 // Copyright (c) 2009 Kazuhiko Arase
      6 //
      7 // URL: http://www.d-project.com/
      8 //
      9 // Licensed under the MIT license:
     10 //  http://www.opensource.org/licenses/mit-license.php
     11 //
     12 // The word 'QR Code' is registered trademark of
     13 // DENSO WAVE INCORPORATED
     14 //  http://www.denso-wave.com/qrcode/faqpatent-e.html
     15 //
     16 //---------------------------------------------------------------------
     17 
     18 //---------------------------------------------------------------------
     19 // qrcode
     20 //---------------------------------------------------------------------
     21 
     22 /**
     23 * qrcode
     24 * @param typeNumber 1 to 40
     25 * @param errorCorrectionLevel 'L','M','Q','H'
     26 */
     27 export const qrcode = function(typeNumber, errorCorrectionLevel) {
     28 
     29  const PAD0 = 0xEC;
     30  const PAD1 = 0x11;
     31 
     32  let _typeNumber = typeNumber;
     33  const _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];
     34  let _modules = null;
     35  let _moduleCount = 0;
     36  let _dataCache = null;
     37  const _dataList = [];
     38 
     39  const _this = {};
     40 
     41  const makeImpl = function(test, maskPattern) {
     42 
     43    _moduleCount = _typeNumber * 4 + 17;
     44    _modules = function(moduleCount) {
     45      const modules = new Array(moduleCount);
     46      for (let row = 0; row < moduleCount; row += 1) {
     47        modules[row] = new Array(moduleCount);
     48        for (let col = 0; col < moduleCount; col += 1) {
     49          modules[row][col] = null;
     50        }
     51      }
     52      return modules;
     53    }(_moduleCount);
     54 
     55    setupPositionProbePattern(0, 0);
     56    setupPositionProbePattern(_moduleCount - 7, 0);
     57    setupPositionProbePattern(0, _moduleCount - 7);
     58    setupPositionAdjustPattern();
     59    setupTimingPattern();
     60    setupTypeInfo(test, maskPattern);
     61 
     62    if (_typeNumber >= 7) {
     63      setupTypeNumber(test);
     64    }
     65 
     66    if (_dataCache == null) {
     67      _dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);
     68    }
     69 
     70    mapData(_dataCache, maskPattern);
     71  };
     72 
     73  const setupPositionProbePattern = function(row, col) {
     74 
     75    for (let r = -1; r <= 7; r += 1) {
     76 
     77      if (row + r <= -1 || _moduleCount <= row + r) continue;
     78 
     79      for (let c = -1; c <= 7; c += 1) {
     80 
     81        if (col + c <= -1 || _moduleCount <= col + c) continue;
     82 
     83        if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
     84            || (0 <= c && c <= 6 && (r == 0 || r == 6) )
     85            || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
     86          _modules[row + r][col + c] = true;
     87        } else {
     88          _modules[row + r][col + c] = false;
     89        }
     90      }
     91    }
     92  };
     93 
     94  const getBestMaskPattern = function() {
     95 
     96    let minLostPoint = 0;
     97    let pattern = 0;
     98 
     99    for (let i = 0; i < 8; i += 1) {
    100 
    101      makeImpl(true, i);
    102 
    103      const lostPoint = QRUtil.getLostPoint(_this);
    104 
    105      if (i == 0 || minLostPoint > lostPoint) {
    106        minLostPoint = lostPoint;
    107        pattern = i;
    108      }
    109    }
    110 
    111    return pattern;
    112  };
    113 
    114  const setupTimingPattern = function() {
    115 
    116    for (let r = 8; r < _moduleCount - 8; r += 1) {
    117      if (_modules[r][6] != null) {
    118        continue;
    119      }
    120      _modules[r][6] = (r % 2 == 0);
    121    }
    122 
    123    for (let c = 8; c < _moduleCount - 8; c += 1) {
    124      if (_modules[6][c] != null) {
    125        continue;
    126      }
    127      _modules[6][c] = (c % 2 == 0);
    128    }
    129  };
    130 
    131  const setupPositionAdjustPattern = function() {
    132 
    133    const pos = QRUtil.getPatternPosition(_typeNumber);
    134 
    135    for (let i = 0; i < pos.length; i += 1) {
    136 
    137      for (let j = 0; j < pos.length; j += 1) {
    138 
    139        const row = pos[i];
    140        const col = pos[j];
    141 
    142        if (_modules[row][col] != null) {
    143          continue;
    144        }
    145 
    146        for (let r = -2; r <= 2; r += 1) {
    147 
    148          for (let c = -2; c <= 2; c += 1) {
    149 
    150            if (r == -2 || r == 2 || c == -2 || c == 2
    151                || (r == 0 && c == 0) ) {
    152              _modules[row + r][col + c] = true;
    153            } else {
    154              _modules[row + r][col + c] = false;
    155            }
    156          }
    157        }
    158      }
    159    }
    160  };
    161 
    162  const setupTypeNumber = function(test) {
    163 
    164    const bits = QRUtil.getBCHTypeNumber(_typeNumber);
    165 
    166    for (let i = 0; i < 18; i += 1) {
    167      const mod = (!test && ( (bits >> i) & 1) == 1);
    168      _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
    169    }
    170 
    171    for (let i = 0; i < 18; i += 1) {
    172      const mod = (!test && ( (bits >> i) & 1) == 1);
    173      _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
    174    }
    175  };
    176 
    177  const setupTypeInfo = function(test, maskPattern) {
    178 
    179    const data = (_errorCorrectionLevel << 3) | maskPattern;
    180    const bits = QRUtil.getBCHTypeInfo(data);
    181 
    182    // vertical
    183    for (let i = 0; i < 15; i += 1) {
    184 
    185      const mod = (!test && ( (bits >> i) & 1) == 1);
    186 
    187      if (i < 6) {
    188        _modules[i][8] = mod;
    189      } else if (i < 8) {
    190        _modules[i + 1][8] = mod;
    191      } else {
    192        _modules[_moduleCount - 15 + i][8] = mod;
    193      }
    194    }
    195 
    196    // horizontal
    197    for (let i = 0; i < 15; i += 1) {
    198 
    199      const mod = (!test && ( (bits >> i) & 1) == 1);
    200 
    201      if (i < 8) {
    202        _modules[8][_moduleCount - i - 1] = mod;
    203      } else if (i < 9) {
    204        _modules[8][15 - i - 1 + 1] = mod;
    205      } else {
    206        _modules[8][15 - i - 1] = mod;
    207      }
    208    }
    209 
    210    // fixed module
    211    _modules[_moduleCount - 8][8] = (!test);
    212  };
    213 
    214  const mapData = function(data, maskPattern) {
    215 
    216    let inc = -1;
    217    let row = _moduleCount - 1;
    218    let bitIndex = 7;
    219    let byteIndex = 0;
    220    const maskFunc = QRUtil.getMaskFunction(maskPattern);
    221 
    222    for (let col = _moduleCount - 1; col > 0; col -= 2) {
    223 
    224      if (col == 6) col -= 1;
    225 
    226      while (true) {
    227 
    228        for (let c = 0; c < 2; c += 1) {
    229 
    230          if (_modules[row][col - c] == null) {
    231 
    232            let dark = false;
    233 
    234            if (byteIndex < data.length) {
    235              dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
    236            }
    237 
    238            const mask = maskFunc(row, col - c);
    239 
    240            if (mask) {
    241              dark = !dark;
    242            }
    243 
    244            _modules[row][col - c] = dark;
    245            bitIndex -= 1;
    246 
    247            if (bitIndex == -1) {
    248              byteIndex += 1;
    249              bitIndex = 7;
    250            }
    251          }
    252        }
    253 
    254        row += inc;
    255 
    256        if (row < 0 || _moduleCount <= row) {
    257          row -= inc;
    258          inc = -inc;
    259          break;
    260        }
    261      }
    262    }
    263  };
    264 
    265  const createBytes = function(buffer, rsBlocks) {
    266 
    267    let offset = 0;
    268 
    269    let maxDcCount = 0;
    270    let maxEcCount = 0;
    271 
    272    const dcdata = new Array(rsBlocks.length);
    273    const ecdata = new Array(rsBlocks.length);
    274 
    275    for (let r = 0; r < rsBlocks.length; r += 1) {
    276 
    277      const dcCount = rsBlocks[r].dataCount;
    278      const ecCount = rsBlocks[r].totalCount - dcCount;
    279 
    280      maxDcCount = Math.max(maxDcCount, dcCount);
    281      maxEcCount = Math.max(maxEcCount, ecCount);
    282 
    283      dcdata[r] = new Array(dcCount);
    284 
    285      for (let i = 0; i < dcdata[r].length; i += 1) {
    286        dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
    287      }
    288      offset += dcCount;
    289 
    290      const rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
    291      const rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);
    292 
    293      const modPoly = rawPoly.mod(rsPoly);
    294      ecdata[r] = new Array(rsPoly.getLength() - 1);
    295      for (let i = 0; i < ecdata[r].length; i += 1) {
    296        const modIndex = i + modPoly.getLength() - ecdata[r].length;
    297        ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;
    298      }
    299    }
    300 
    301    let totalCodeCount = 0;
    302    for (let i = 0; i < rsBlocks.length; i += 1) {
    303      totalCodeCount += rsBlocks[i].totalCount;
    304    }
    305 
    306    const data = new Array(totalCodeCount);
    307    let index = 0;
    308 
    309    for (let i = 0; i < maxDcCount; i += 1) {
    310      for (let r = 0; r < rsBlocks.length; r += 1) {
    311        if (i < dcdata[r].length) {
    312          data[index] = dcdata[r][i];
    313          index += 1;
    314        }
    315      }
    316    }
    317 
    318    for (let i = 0; i < maxEcCount; i += 1) {
    319      for (let r = 0; r < rsBlocks.length; r += 1) {
    320        if (i < ecdata[r].length) {
    321          data[index] = ecdata[r][i];
    322          index += 1;
    323        }
    324      }
    325    }
    326 
    327    return data;
    328  };
    329 
    330  const createData = function(typeNumber, errorCorrectionLevel, dataList) {
    331 
    332    const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);
    333 
    334    const buffer = qrBitBuffer();
    335 
    336    for (let i = 0; i < dataList.length; i += 1) {
    337      const data = dataList[i];
    338      buffer.put(data.getMode(), 4);
    339      buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
    340      data.write(buffer);
    341    }
    342 
    343    // calc num max data.
    344    let totalDataCount = 0;
    345    for (let i = 0; i < rsBlocks.length; i += 1) {
    346      totalDataCount += rsBlocks[i].dataCount;
    347    }
    348 
    349    if (buffer.getLengthInBits() > totalDataCount * 8) {
    350      throw 'code length overflow. ('
    351        + buffer.getLengthInBits()
    352        + '>'
    353        + totalDataCount * 8
    354        + ')';
    355    }
    356 
    357    // end code
    358    if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
    359      buffer.put(0, 4);
    360    }
    361 
    362    // padding
    363    while (buffer.getLengthInBits() % 8 != 0) {
    364      buffer.putBit(false);
    365    }
    366 
    367    // padding
    368    while (true) {
    369 
    370      if (buffer.getLengthInBits() >= totalDataCount * 8) {
    371        break;
    372      }
    373      buffer.put(PAD0, 8);
    374 
    375      if (buffer.getLengthInBits() >= totalDataCount * 8) {
    376        break;
    377      }
    378      buffer.put(PAD1, 8);
    379    }
    380 
    381    return createBytes(buffer, rsBlocks);
    382  };
    383 
    384  _this.addData = function(data, mode) {
    385 
    386    mode = mode || 'Byte';
    387 
    388    let newData = null;
    389 
    390    switch(mode) {
    391    case 'Numeric' :
    392      newData = qrNumber(data);
    393      break;
    394    case 'Alphanumeric' :
    395      newData = qrAlphaNum(data);
    396      break;
    397    case 'Byte' :
    398      newData = qr8BitByte(data);
    399      break;
    400    case 'Kanji' :
    401      newData = qrKanji(data);
    402      break;
    403    default :
    404      throw 'mode:' + mode;
    405    }
    406 
    407    _dataList.push(newData);
    408    _dataCache = null;
    409  };
    410 
    411  _this.isDark = function(row, col) {
    412    if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
    413      throw row + ',' + col;
    414    }
    415    return _modules[row][col];
    416  };
    417 
    418  _this.getModuleCount = function() {
    419    return _moduleCount;
    420  };
    421 
    422  _this.make = function() {
    423    if (_typeNumber < 1) {
    424      let typeNumber = 1;
    425 
    426      for (; typeNumber < 40; typeNumber++) {
    427        const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);
    428        const buffer = qrBitBuffer();
    429 
    430        for (let i = 0; i < _dataList.length; i++) {
    431          const data = _dataList[i];
    432          buffer.put(data.getMode(), 4);
    433          buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
    434          data.write(buffer);
    435        }
    436 
    437        let totalDataCount = 0;
    438        for (let i = 0; i < rsBlocks.length; i++) {
    439          totalDataCount += rsBlocks[i].dataCount;
    440        }
    441 
    442        if (buffer.getLengthInBits() <= totalDataCount * 8) {
    443          break;
    444        }
    445      }
    446 
    447      _typeNumber = typeNumber;
    448    }
    449 
    450    makeImpl(false, getBestMaskPattern() );
    451  };
    452 
    453  _this.createTableTag = function(cellSize, margin) {
    454 
    455    cellSize = cellSize || 2;
    456    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
    457 
    458    let qrHtml = '';
    459 
    460    qrHtml += '<table style="';
    461    qrHtml += ' border-width: 0px; border-style: none;';
    462    qrHtml += ' border-collapse: collapse;';
    463    qrHtml += ' padding: 0px; margin: ' + margin + 'px;';
    464    qrHtml += '">';
    465    qrHtml += '<tbody>';
    466 
    467    for (let r = 0; r < _this.getModuleCount(); r += 1) {
    468 
    469      qrHtml += '<tr>';
    470 
    471      for (let c = 0; c < _this.getModuleCount(); c += 1) {
    472        qrHtml += '<td style="';
    473        qrHtml += ' border-width: 0px; border-style: none;';
    474        qrHtml += ' border-collapse: collapse;';
    475        qrHtml += ' padding: 0px; margin: 0px;';
    476        qrHtml += ' width: ' + cellSize + 'px;';
    477        qrHtml += ' height: ' + cellSize + 'px;';
    478        qrHtml += ' background-color: ';
    479        qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';
    480        qrHtml += ';';
    481        qrHtml += '"/>';
    482      }
    483 
    484      qrHtml += '</tr>';
    485    }
    486 
    487    qrHtml += '</tbody>';
    488    qrHtml += '</table>';
    489 
    490    return qrHtml;
    491  };
    492 
    493  _this.createSvgTag = function(cellSize, margin, alt, title) {
    494 
    495    let opts = {};
    496    if (typeof arguments[0] == 'object') {
    497      // Called by options.
    498      opts = arguments[0];
    499      // overwrite cellSize and margin.
    500      cellSize = opts.cellSize;
    501      margin = opts.margin;
    502      alt = opts.alt;
    503      title = opts.title;
    504    }
    505 
    506    cellSize = cellSize || 2;
    507    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
    508 
    509    // Compose alt property surrogate
    510    alt = (typeof alt === 'string') ? {text: alt} : alt || {};
    511    alt.text = alt.text || null;
    512    alt.id = (alt.text) ? alt.id || 'qrcode-description' : null;
    513 
    514    // Compose title property surrogate
    515    title = (typeof title === 'string') ? {text: title} : title || {};
    516    title.text = title.text || null;
    517    title.id = (title.text) ? title.id || 'qrcode-title' : null;
    518 
    519    const size = _this.getModuleCount() * cellSize + margin * 2;
    520    let c, mc, r, mr, qrSvg='', rect;
    521 
    522    rect = 'l' + cellSize + ',0 0,' + cellSize +
    523      ' -' + cellSize + ',0 0,-' + cellSize + 'z ';
    524 
    525    qrSvg += '<svg version="1.1" xmlns="http://www.w3.org/2000/svg"';
    526    qrSvg += !opts.scalable ? ' width="' + size + 'px" height="' + size + 'px"' : '';
    527    qrSvg += ' viewBox="0 0 ' + size + ' ' + size + '" ';
    528    qrSvg += ' preserveAspectRatio="xMinYMin meet"';
    529    qrSvg += (title.text || alt.text) ? ' role="img" aria-labelledby="' +
    530        escapeXml([title.id, alt.id].join(' ').trim() ) + '"' : '';
    531    qrSvg += '>';
    532    qrSvg += (title.text) ? '<title id="' + escapeXml(title.id) + '">' +
    533        escapeXml(title.text) + '</title>' : '';
    534    qrSvg += (alt.text) ? '<description id="' + escapeXml(alt.id) + '">' +
    535        escapeXml(alt.text) + '</description>' : '';
    536    qrSvg += '<rect width="100%" height="100%" fill="white" cx="0" cy="0"/>';
    537    qrSvg += '<path d="';
    538 
    539    for (r = 0; r < _this.getModuleCount(); r += 1) {
    540      mr = r * cellSize + margin;
    541      for (c = 0; c < _this.getModuleCount(); c += 1) {
    542        if (_this.isDark(r, c) ) {
    543          mc = c*cellSize+margin;
    544          qrSvg += 'M' + mc + ',' + mr + rect;
    545        }
    546      }
    547    }
    548 
    549    qrSvg += '" stroke="transparent" fill="black"/>';
    550    qrSvg += '</svg>';
    551 
    552    return qrSvg;
    553  };
    554 
    555  _this.createDataURL = function(cellSize, margin) {
    556 
    557    cellSize = cellSize || 2;
    558    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
    559 
    560    const size = _this.getModuleCount() * cellSize + margin * 2;
    561    const min = margin;
    562    const max = size - margin;
    563 
    564    return createDataURL(size, size, function(x, y) {
    565      if (min <= x && x < max && min <= y && y < max) {
    566        const c = Math.floor( (x - min) / cellSize);
    567        const r = Math.floor( (y - min) / cellSize);
    568        return _this.isDark(r, c)? 0 : 1;
    569      } else {
    570        return 1;
    571      }
    572    } );
    573  };
    574 
    575  _this.createImgTag = function(cellSize, margin, alt) {
    576 
    577    cellSize = cellSize || 2;
    578    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
    579 
    580    const size = _this.getModuleCount() * cellSize + margin * 2;
    581 
    582    let img = '';
    583    img += '<img';
    584    img += '\u0020src="';
    585    img += _this.createDataURL(cellSize, margin);
    586    img += '"';
    587    img += '\u0020width="';
    588    img += size;
    589    img += '"';
    590    img += '\u0020height="';
    591    img += size;
    592    img += '"';
    593    if (alt) {
    594      img += '\u0020alt="';
    595      img += escapeXml(alt);
    596      img += '"';
    597    }
    598    img += '/>';
    599 
    600    return img;
    601  };
    602 
    603  const escapeXml = function(s) {
    604    let escaped = '';
    605    for (let i = 0; i < s.length; i += 1) {
    606      const c = s.charAt(i);
    607      switch(c) {
    608      case '<': escaped += '&lt;'; break;
    609      case '>': escaped += '&gt;'; break;
    610      case '&': escaped += '&amp;'; break;
    611      case '"': escaped += '&quot;'; break;
    612      default : escaped += c; break;
    613      }
    614    }
    615    return escaped;
    616  };
    617 
    618  const _createHalfASCII = function(margin) {
    619    const cellSize = 1;
    620    margin = (typeof margin == 'undefined')? cellSize * 2 : margin;
    621 
    622    const size = _this.getModuleCount() * cellSize + margin * 2;
    623    const min = margin;
    624    const max = size - margin;
    625 
    626    let y, x, r1, r2, p;
    627 
    628    const blocks = {
    629      '██': '█',
    630      'â–ˆ ': 'â–€',
    631      ' â–ˆ': 'â–„',
    632      '  ': ' '
    633    };
    634 
    635    const blocksLastLineNoMargin = {
    636      '██': '▀',
    637      'â–ˆ ': 'â–€',
    638      ' â–ˆ': ' ',
    639      '  ': ' '
    640    };
    641 
    642    let ascii = '';
    643    for (y = 0; y < size; y += 2) {
    644      r1 = Math.floor((y - min) / cellSize);
    645      r2 = Math.floor((y + 1 - min) / cellSize);
    646      for (x = 0; x < size; x += 1) {
    647        p = 'â–ˆ';
    648 
    649        if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) {
    650          p = ' ';
    651        }
    652 
    653        if (min <= x && x < max && min <= y+1 && y+1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) {
    654          p += ' ';
    655        }
    656        else {
    657          p += 'â–ˆ';
    658        }
    659 
    660        // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.
    661        ascii += (margin < 1 && y+1 >= max) ? blocksLastLineNoMargin[p] : blocks[p];
    662      }
    663 
    664      ascii += '\n';
    665    }
    666 
    667    if (size % 2 && margin > 0) {
    668      return ascii.substring(0, ascii.length - size - 1) + Array(size+1).join('â–€');
    669    }
    670 
    671    return ascii.substring(0, ascii.length-1);
    672  };
    673 
    674  _this.createASCII = function(cellSize, margin) {
    675    cellSize = cellSize || 1;
    676 
    677    if (cellSize < 2) {
    678      return _createHalfASCII(margin);
    679    }
    680 
    681    cellSize -= 1;
    682    margin = (typeof margin == 'undefined')? cellSize * 2 : margin;
    683 
    684    const size = _this.getModuleCount() * cellSize + margin * 2;
    685    const min = margin;
    686    const max = size - margin;
    687 
    688    let y, x, r, p;
    689 
    690    const white = Array(cellSize+1).join('██');
    691    const black = Array(cellSize+1).join('  ');
    692 
    693    let ascii = '';
    694    let line = '';
    695    for (y = 0; y < size; y += 1) {
    696      r = Math.floor( (y - min) / cellSize);
    697      line = '';
    698      for (x = 0; x < size; x += 1) {
    699        p = 1;
    700 
    701        if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) {
    702          p = 0;
    703        }
    704 
    705        // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.
    706        line += p ? white : black;
    707      }
    708 
    709      for (r = 0; r < cellSize; r += 1) {
    710        ascii += line + '\n';
    711      }
    712    }
    713 
    714    return ascii.substring(0, ascii.length-1);
    715  };
    716 
    717  _this.renderTo2dContext = function(context, cellSize) {
    718    cellSize = cellSize || 2;
    719    const length = _this.getModuleCount();
    720    for (let row = 0; row < length; row++) {
    721      for (let col = 0; col < length; col++) {
    722        context.fillStyle = _this.isDark(row, col) ? 'black' : 'white';
    723        context.fillRect(col * cellSize, row * cellSize, cellSize, cellSize);
    724      }
    725    }
    726  }
    727 
    728  return _this;
    729 };
    730 
    731 //---------------------------------------------------------------------
    732 // qrcode.stringToBytes
    733 //---------------------------------------------------------------------
    734 
    735 qrcode.stringToBytes = function(s) {
    736  const bytes = [];
    737  for (let i = 0; i < s.length; i += 1) {
    738    const c = s.charCodeAt(i);
    739    bytes.push(c & 0xff);
    740  }
    741  return bytes;
    742 };
    743 
    744 //---------------------------------------------------------------------
    745 // qrcode.createStringToBytes
    746 //---------------------------------------------------------------------
    747 
    748 /**
    749 * @param unicodeData base64 string of byte array.
    750 * [16bit Unicode],[16bit Bytes], ...
    751 * @param numChars
    752 */
    753 qrcode.createStringToBytes = function(unicodeData, numChars) {
    754 
    755  // create conversion map.
    756 
    757  const unicodeMap = function() {
    758 
    759    const bin = base64DecodeInputStream(unicodeData);
    760    const read = function() {
    761      const b = bin.read();
    762      if (b == -1) throw 'eof';
    763      return b;
    764    };
    765 
    766    let count = 0;
    767    const unicodeMap = {};
    768    while (true) {
    769      const b0 = bin.read();
    770      if (b0 == -1) break;
    771      const b1 = read();
    772      const b2 = read();
    773      const b3 = read();
    774      const k = String.fromCharCode( (b0 << 8) | b1);
    775      const v = (b2 << 8) | b3;
    776      unicodeMap[k] = v;
    777      count += 1;
    778    }
    779    if (count != numChars) {
    780      throw count + ' != ' + numChars;
    781    }
    782 
    783    return unicodeMap;
    784  }();
    785 
    786  const unknownChar = '?'.charCodeAt(0);
    787 
    788  return function(s) {
    789    const bytes = [];
    790    for (let i = 0; i < s.length; i += 1) {
    791      const c = s.charCodeAt(i);
    792      if (c < 128) {
    793        bytes.push(c);
    794      } else {
    795        const b = unicodeMap[s.charAt(i)];
    796        if (typeof b == 'number') {
    797          if ( (b & 0xff) == b) {
    798            // 1byte
    799            bytes.push(b);
    800          } else {
    801            // 2bytes
    802            bytes.push(b >>> 8);
    803            bytes.push(b & 0xff);
    804          }
    805        } else {
    806          bytes.push(unknownChar);
    807        }
    808      }
    809    }
    810    return bytes;
    811  };
    812 };
    813 
    814 //---------------------------------------------------------------------
    815 // QRMode
    816 //---------------------------------------------------------------------
    817 
    818 const QRMode = {
    819  MODE_NUMBER :    1 << 0,
    820  MODE_ALPHA_NUM : 1 << 1,
    821  MODE_8BIT_BYTE : 1 << 2,
    822  MODE_KANJI :     1 << 3
    823 };
    824 
    825 //---------------------------------------------------------------------
    826 // QRErrorCorrectionLevel
    827 //---------------------------------------------------------------------
    828 
    829 export const QRErrorCorrectionLevel = {
    830  L : 1,
    831  M : 0,
    832  Q : 3,
    833  H : 2
    834 };
    835 
    836 //---------------------------------------------------------------------
    837 // QRMaskPattern
    838 //---------------------------------------------------------------------
    839 
    840 const QRMaskPattern = {
    841  PATTERN000 : 0,
    842  PATTERN001 : 1,
    843  PATTERN010 : 2,
    844  PATTERN011 : 3,
    845  PATTERN100 : 4,
    846  PATTERN101 : 5,
    847  PATTERN110 : 6,
    848  PATTERN111 : 7
    849 };
    850 
    851 //---------------------------------------------------------------------
    852 // QRUtil
    853 //---------------------------------------------------------------------
    854 
    855 const QRUtil = function() {
    856 
    857  const PATTERN_POSITION_TABLE = [
    858    [],
    859    [6, 18],
    860    [6, 22],
    861    [6, 26],
    862    [6, 30],
    863    [6, 34],
    864    [6, 22, 38],
    865    [6, 24, 42],
    866    [6, 26, 46],
    867    [6, 28, 50],
    868    [6, 30, 54],
    869    [6, 32, 58],
    870    [6, 34, 62],
    871    [6, 26, 46, 66],
    872    [6, 26, 48, 70],
    873    [6, 26, 50, 74],
    874    [6, 30, 54, 78],
    875    [6, 30, 56, 82],
    876    [6, 30, 58, 86],
    877    [6, 34, 62, 90],
    878    [6, 28, 50, 72, 94],
    879    [6, 26, 50, 74, 98],
    880    [6, 30, 54, 78, 102],
    881    [6, 28, 54, 80, 106],
    882    [6, 32, 58, 84, 110],
    883    [6, 30, 58, 86, 114],
    884    [6, 34, 62, 90, 118],
    885    [6, 26, 50, 74, 98, 122],
    886    [6, 30, 54, 78, 102, 126],
    887    [6, 26, 52, 78, 104, 130],
    888    [6, 30, 56, 82, 108, 134],
    889    [6, 34, 60, 86, 112, 138],
    890    [6, 30, 58, 86, 114, 142],
    891    [6, 34, 62, 90, 118, 146],
    892    [6, 30, 54, 78, 102, 126, 150],
    893    [6, 24, 50, 76, 102, 128, 154],
    894    [6, 28, 54, 80, 106, 132, 158],
    895    [6, 32, 58, 84, 110, 136, 162],
    896    [6, 26, 54, 82, 110, 138, 166],
    897    [6, 30, 58, 86, 114, 142, 170]
    898  ];
    899  const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
    900  const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
    901  const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
    902 
    903  const _this = {};
    904 
    905  const getBCHDigit = function(data) {
    906    let digit = 0;
    907    while (data != 0) {
    908      digit += 1;
    909      data >>>= 1;
    910    }
    911    return digit;
    912  };
    913 
    914  _this.getBCHTypeInfo = function(data) {
    915    let d = data << 10;
    916    while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
    917      d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
    918    }
    919    return ( (data << 10) | d) ^ G15_MASK;
    920  };
    921 
    922  _this.getBCHTypeNumber = function(data) {
    923    let d = data << 12;
    924    while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
    925      d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
    926    }
    927    return (data << 12) | d;
    928  };
    929 
    930  _this.getPatternPosition = function(typeNumber) {
    931    return PATTERN_POSITION_TABLE[typeNumber - 1];
    932  };
    933 
    934  _this.getMaskFunction = function(maskPattern) {
    935 
    936    switch (maskPattern) {
    937 
    938    case QRMaskPattern.PATTERN000 :
    939      return function(i, j) { return (i + j) % 2 == 0; };
    940    case QRMaskPattern.PATTERN001 :
    941      return function(i, j) { return i % 2 == 0; };
    942    case QRMaskPattern.PATTERN010 :
    943      return function(i, j) { return j % 3 == 0; };
    944    case QRMaskPattern.PATTERN011 :
    945      return function(i, j) { return (i + j) % 3 == 0; };
    946    case QRMaskPattern.PATTERN100 :
    947      return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
    948    case QRMaskPattern.PATTERN101 :
    949      return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
    950    case QRMaskPattern.PATTERN110 :
    951      return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
    952    case QRMaskPattern.PATTERN111 :
    953      return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };
    954 
    955    default :
    956      throw 'bad maskPattern:' + maskPattern;
    957    }
    958  };
    959 
    960  _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
    961    let a = qrPolynomial([1], 0);
    962    for (let i = 0; i < errorCorrectLength; i += 1) {
    963      a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
    964    }
    965    return a;
    966  };
    967 
    968  _this.getLengthInBits = function(mode, type) {
    969 
    970    if (1 <= type && type < 10) {
    971 
    972      // 1 - 9
    973 
    974      switch(mode) {
    975      case QRMode.MODE_NUMBER    : return 10;
    976      case QRMode.MODE_ALPHA_NUM : return 9;
    977      case QRMode.MODE_8BIT_BYTE : return 8;
    978      case QRMode.MODE_KANJI     : return 8;
    979      default :
    980        throw 'mode:' + mode;
    981      }
    982 
    983    } else if (type < 27) {
    984 
    985      // 10 - 26
    986 
    987      switch(mode) {
    988      case QRMode.MODE_NUMBER    : return 12;
    989      case QRMode.MODE_ALPHA_NUM : return 11;
    990      case QRMode.MODE_8BIT_BYTE : return 16;
    991      case QRMode.MODE_KANJI     : return 10;
    992      default :
    993        throw 'mode:' + mode;
    994      }
    995 
    996    } else if (type < 41) {
    997 
    998      // 27 - 40
    999 
   1000      switch(mode) {
   1001      case QRMode.MODE_NUMBER    : return 14;
   1002      case QRMode.MODE_ALPHA_NUM : return 13;
   1003      case QRMode.MODE_8BIT_BYTE : return 16;
   1004      case QRMode.MODE_KANJI     : return 12;
   1005      default :
   1006        throw 'mode:' + mode;
   1007      }
   1008 
   1009    } else {
   1010      throw 'type:' + type;
   1011    }
   1012  };
   1013 
   1014  _this.getLostPoint = function(qrcode) {
   1015 
   1016    const moduleCount = qrcode.getModuleCount();
   1017 
   1018    let lostPoint = 0;
   1019 
   1020    // LEVEL1
   1021 
   1022    for (let row = 0; row < moduleCount; row += 1) {
   1023      for (let col = 0; col < moduleCount; col += 1) {
   1024 
   1025        let sameCount = 0;
   1026        const dark = qrcode.isDark(row, col);
   1027 
   1028        for (let r = -1; r <= 1; r += 1) {
   1029 
   1030          if (row + r < 0 || moduleCount <= row + r) {
   1031            continue;
   1032          }
   1033 
   1034          for (let c = -1; c <= 1; c += 1) {
   1035 
   1036            if (col + c < 0 || moduleCount <= col + c) {
   1037              continue;
   1038            }
   1039 
   1040            if (r == 0 && c == 0) {
   1041              continue;
   1042            }
   1043 
   1044            if (dark == qrcode.isDark(row + r, col + c) ) {
   1045              sameCount += 1;
   1046            }
   1047          }
   1048        }
   1049 
   1050        if (sameCount > 5) {
   1051          lostPoint += (3 + sameCount - 5);
   1052        }
   1053      }
   1054    };
   1055 
   1056    // LEVEL2
   1057 
   1058    for (let row = 0; row < moduleCount - 1; row += 1) {
   1059      for (let col = 0; col < moduleCount - 1; col += 1) {
   1060        let count = 0;
   1061        if (qrcode.isDark(row, col) ) count += 1;
   1062        if (qrcode.isDark(row + 1, col) ) count += 1;
   1063        if (qrcode.isDark(row, col + 1) ) count += 1;
   1064        if (qrcode.isDark(row + 1, col + 1) ) count += 1;
   1065        if (count == 0 || count == 4) {
   1066          lostPoint += 3;
   1067        }
   1068      }
   1069    }
   1070 
   1071    // LEVEL3
   1072 
   1073    for (let row = 0; row < moduleCount; row += 1) {
   1074      for (let col = 0; col < moduleCount - 6; col += 1) {
   1075        if (qrcode.isDark(row, col)
   1076            && !qrcode.isDark(row, col + 1)
   1077            &&  qrcode.isDark(row, col + 2)
   1078            &&  qrcode.isDark(row, col + 3)
   1079            &&  qrcode.isDark(row, col + 4)
   1080            && !qrcode.isDark(row, col + 5)
   1081            &&  qrcode.isDark(row, col + 6) ) {
   1082          lostPoint += 40;
   1083        }
   1084      }
   1085    }
   1086 
   1087    for (let col = 0; col < moduleCount; col += 1) {
   1088      for (let row = 0; row < moduleCount - 6; row += 1) {
   1089        if (qrcode.isDark(row, col)
   1090            && !qrcode.isDark(row + 1, col)
   1091            &&  qrcode.isDark(row + 2, col)
   1092            &&  qrcode.isDark(row + 3, col)
   1093            &&  qrcode.isDark(row + 4, col)
   1094            && !qrcode.isDark(row + 5, col)
   1095            &&  qrcode.isDark(row + 6, col) ) {
   1096          lostPoint += 40;
   1097        }
   1098      }
   1099    }
   1100 
   1101    // LEVEL4
   1102 
   1103    let darkCount = 0;
   1104 
   1105    for (let col = 0; col < moduleCount; col += 1) {
   1106      for (let row = 0; row < moduleCount; row += 1) {
   1107        if (qrcode.isDark(row, col) ) {
   1108          darkCount += 1;
   1109        }
   1110      }
   1111    }
   1112 
   1113    const ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
   1114    lostPoint += ratio * 10;
   1115 
   1116    return lostPoint;
   1117  };
   1118 
   1119  return _this;
   1120 }();
   1121 
   1122 //---------------------------------------------------------------------
   1123 // QRMath
   1124 //---------------------------------------------------------------------
   1125 
   1126 const QRMath = function() {
   1127 
   1128  const EXP_TABLE = new Array(256);
   1129  const LOG_TABLE = new Array(256);
   1130 
   1131  // initialize tables
   1132  for (let i = 0; i < 8; i += 1) {
   1133    EXP_TABLE[i] = 1 << i;
   1134  }
   1135  for (let i = 8; i < 256; i += 1) {
   1136    EXP_TABLE[i] = EXP_TABLE[i - 4]
   1137      ^ EXP_TABLE[i - 5]
   1138      ^ EXP_TABLE[i - 6]
   1139      ^ EXP_TABLE[i - 8];
   1140  }
   1141  for (let i = 0; i < 255; i += 1) {
   1142    LOG_TABLE[EXP_TABLE[i] ] = i;
   1143  }
   1144 
   1145  const _this = {};
   1146 
   1147  _this.glog = function(n) {
   1148 
   1149    if (n < 1) {
   1150      throw 'glog(' + n + ')';
   1151    }
   1152 
   1153    return LOG_TABLE[n];
   1154  };
   1155 
   1156  _this.gexp = function(n) {
   1157 
   1158    while (n < 0) {
   1159      n += 255;
   1160    }
   1161 
   1162    while (n >= 256) {
   1163      n -= 255;
   1164    }
   1165 
   1166    return EXP_TABLE[n];
   1167  };
   1168 
   1169  return _this;
   1170 }();
   1171 
   1172 //---------------------------------------------------------------------
   1173 // qrPolynomial
   1174 //---------------------------------------------------------------------
   1175 
   1176 const qrPolynomial = function(num, shift) {
   1177 
   1178  if (typeof num.length == 'undefined') {
   1179    throw num.length + '/' + shift;
   1180  }
   1181 
   1182  const _num = function() {
   1183    let offset = 0;
   1184    while (offset < num.length && num[offset] == 0) {
   1185      offset += 1;
   1186    }
   1187    const _num = new Array(num.length - offset + shift);
   1188    for (let i = 0; i < num.length - offset; i += 1) {
   1189      _num[i] = num[i + offset];
   1190    }
   1191    return _num;
   1192  }();
   1193 
   1194  const _this = {};
   1195 
   1196  _this.getAt = function(index) {
   1197    return _num[index];
   1198  };
   1199 
   1200  _this.getLength = function() {
   1201    return _num.length;
   1202  };
   1203 
   1204  _this.multiply = function(e) {
   1205 
   1206    const num = new Array(_this.getLength() + e.getLength() - 1);
   1207 
   1208    for (let i = 0; i < _this.getLength(); i += 1) {
   1209      for (let j = 0; j < e.getLength(); j += 1) {
   1210        num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );
   1211      }
   1212    }
   1213 
   1214    return qrPolynomial(num, 0);
   1215  };
   1216 
   1217  _this.mod = function(e) {
   1218 
   1219    if (_this.getLength() - e.getLength() < 0) {
   1220      return _this;
   1221    }
   1222 
   1223    const ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );
   1224 
   1225    const num = new Array(_this.getLength() );
   1226    for (let i = 0; i < _this.getLength(); i += 1) {
   1227      num[i] = _this.getAt(i);
   1228    }
   1229 
   1230    for (let i = 0; i < e.getLength(); i += 1) {
   1231      num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
   1232    }
   1233 
   1234    // recursive call
   1235    return qrPolynomial(num, 0).mod(e);
   1236  };
   1237 
   1238  return _this;
   1239 };
   1240 
   1241 //---------------------------------------------------------------------
   1242 // QRRSBlock
   1243 //---------------------------------------------------------------------
   1244 
   1245 export const QRRSBlock = function() {
   1246 
   1247  const RS_BLOCK_TABLE = [
   1248 
   1249    // L
   1250    // M
   1251    // Q
   1252    // H
   1253 
   1254    // 1
   1255    [1, 26, 19],
   1256    [1, 26, 16],
   1257    [1, 26, 13],
   1258    [1, 26, 9],
   1259 
   1260    // 2
   1261    [1, 44, 34],
   1262    [1, 44, 28],
   1263    [1, 44, 22],
   1264    [1, 44, 16],
   1265 
   1266    // 3
   1267    [1, 70, 55],
   1268    [1, 70, 44],
   1269    [2, 35, 17],
   1270    [2, 35, 13],
   1271 
   1272    // 4
   1273    [1, 100, 80],
   1274    [2, 50, 32],
   1275    [2, 50, 24],
   1276    [4, 25, 9],
   1277 
   1278    // 5
   1279    [1, 134, 108],
   1280    [2, 67, 43],
   1281    [2, 33, 15, 2, 34, 16],
   1282    [2, 33, 11, 2, 34, 12],
   1283 
   1284    // 6
   1285    [2, 86, 68],
   1286    [4, 43, 27],
   1287    [4, 43, 19],
   1288    [4, 43, 15],
   1289 
   1290    // 7
   1291    [2, 98, 78],
   1292    [4, 49, 31],
   1293    [2, 32, 14, 4, 33, 15],
   1294    [4, 39, 13, 1, 40, 14],
   1295 
   1296    // 8
   1297    [2, 121, 97],
   1298    [2, 60, 38, 2, 61, 39],
   1299    [4, 40, 18, 2, 41, 19],
   1300    [4, 40, 14, 2, 41, 15],
   1301 
   1302    // 9
   1303    [2, 146, 116],
   1304    [3, 58, 36, 2, 59, 37],
   1305    [4, 36, 16, 4, 37, 17],
   1306    [4, 36, 12, 4, 37, 13],
   1307 
   1308    // 10
   1309    [2, 86, 68, 2, 87, 69],
   1310    [4, 69, 43, 1, 70, 44],
   1311    [6, 43, 19, 2, 44, 20],
   1312    [6, 43, 15, 2, 44, 16],
   1313 
   1314    // 11
   1315    [4, 101, 81],
   1316    [1, 80, 50, 4, 81, 51],
   1317    [4, 50, 22, 4, 51, 23],
   1318    [3, 36, 12, 8, 37, 13],
   1319 
   1320    // 12
   1321    [2, 116, 92, 2, 117, 93],
   1322    [6, 58, 36, 2, 59, 37],
   1323    [4, 46, 20, 6, 47, 21],
   1324    [7, 42, 14, 4, 43, 15],
   1325 
   1326    // 13
   1327    [4, 133, 107],
   1328    [8, 59, 37, 1, 60, 38],
   1329    [8, 44, 20, 4, 45, 21],
   1330    [12, 33, 11, 4, 34, 12],
   1331 
   1332    // 14
   1333    [3, 145, 115, 1, 146, 116],
   1334    [4, 64, 40, 5, 65, 41],
   1335    [11, 36, 16, 5, 37, 17],
   1336    [11, 36, 12, 5, 37, 13],
   1337 
   1338    // 15
   1339    [5, 109, 87, 1, 110, 88],
   1340    [5, 65, 41, 5, 66, 42],
   1341    [5, 54, 24, 7, 55, 25],
   1342    [11, 36, 12, 7, 37, 13],
   1343 
   1344    // 16
   1345    [5, 122, 98, 1, 123, 99],
   1346    [7, 73, 45, 3, 74, 46],
   1347    [15, 43, 19, 2, 44, 20],
   1348    [3, 45, 15, 13, 46, 16],
   1349 
   1350    // 17
   1351    [1, 135, 107, 5, 136, 108],
   1352    [10, 74, 46, 1, 75, 47],
   1353    [1, 50, 22, 15, 51, 23],
   1354    [2, 42, 14, 17, 43, 15],
   1355 
   1356    // 18
   1357    [5, 150, 120, 1, 151, 121],
   1358    [9, 69, 43, 4, 70, 44],
   1359    [17, 50, 22, 1, 51, 23],
   1360    [2, 42, 14, 19, 43, 15],
   1361 
   1362    // 19
   1363    [3, 141, 113, 4, 142, 114],
   1364    [3, 70, 44, 11, 71, 45],
   1365    [17, 47, 21, 4, 48, 22],
   1366    [9, 39, 13, 16, 40, 14],
   1367 
   1368    // 20
   1369    [3, 135, 107, 5, 136, 108],
   1370    [3, 67, 41, 13, 68, 42],
   1371    [15, 54, 24, 5, 55, 25],
   1372    [15, 43, 15, 10, 44, 16],
   1373 
   1374    // 21
   1375    [4, 144, 116, 4, 145, 117],
   1376    [17, 68, 42],
   1377    [17, 50, 22, 6, 51, 23],
   1378    [19, 46, 16, 6, 47, 17],
   1379 
   1380    // 22
   1381    [2, 139, 111, 7, 140, 112],
   1382    [17, 74, 46],
   1383    [7, 54, 24, 16, 55, 25],
   1384    [34, 37, 13],
   1385 
   1386    // 23
   1387    [4, 151, 121, 5, 152, 122],
   1388    [4, 75, 47, 14, 76, 48],
   1389    [11, 54, 24, 14, 55, 25],
   1390    [16, 45, 15, 14, 46, 16],
   1391 
   1392    // 24
   1393    [6, 147, 117, 4, 148, 118],
   1394    [6, 73, 45, 14, 74, 46],
   1395    [11, 54, 24, 16, 55, 25],
   1396    [30, 46, 16, 2, 47, 17],
   1397 
   1398    // 25
   1399    [8, 132, 106, 4, 133, 107],
   1400    [8, 75, 47, 13, 76, 48],
   1401    [7, 54, 24, 22, 55, 25],
   1402    [22, 45, 15, 13, 46, 16],
   1403 
   1404    // 26
   1405    [10, 142, 114, 2, 143, 115],
   1406    [19, 74, 46, 4, 75, 47],
   1407    [28, 50, 22, 6, 51, 23],
   1408    [33, 46, 16, 4, 47, 17],
   1409 
   1410    // 27
   1411    [8, 152, 122, 4, 153, 123],
   1412    [22, 73, 45, 3, 74, 46],
   1413    [8, 53, 23, 26, 54, 24],
   1414    [12, 45, 15, 28, 46, 16],
   1415 
   1416    // 28
   1417    [3, 147, 117, 10, 148, 118],
   1418    [3, 73, 45, 23, 74, 46],
   1419    [4, 54, 24, 31, 55, 25],
   1420    [11, 45, 15, 31, 46, 16],
   1421 
   1422    // 29
   1423    [7, 146, 116, 7, 147, 117],
   1424    [21, 73, 45, 7, 74, 46],
   1425    [1, 53, 23, 37, 54, 24],
   1426    [19, 45, 15, 26, 46, 16],
   1427 
   1428    // 30
   1429    [5, 145, 115, 10, 146, 116],
   1430    [19, 75, 47, 10, 76, 48],
   1431    [15, 54, 24, 25, 55, 25],
   1432    [23, 45, 15, 25, 46, 16],
   1433 
   1434    // 31
   1435    [13, 145, 115, 3, 146, 116],
   1436    [2, 74, 46, 29, 75, 47],
   1437    [42, 54, 24, 1, 55, 25],
   1438    [23, 45, 15, 28, 46, 16],
   1439 
   1440    // 32
   1441    [17, 145, 115],
   1442    [10, 74, 46, 23, 75, 47],
   1443    [10, 54, 24, 35, 55, 25],
   1444    [19, 45, 15, 35, 46, 16],
   1445 
   1446    // 33
   1447    [17, 145, 115, 1, 146, 116],
   1448    [14, 74, 46, 21, 75, 47],
   1449    [29, 54, 24, 19, 55, 25],
   1450    [11, 45, 15, 46, 46, 16],
   1451 
   1452    // 34
   1453    [13, 145, 115, 6, 146, 116],
   1454    [14, 74, 46, 23, 75, 47],
   1455    [44, 54, 24, 7, 55, 25],
   1456    [59, 46, 16, 1, 47, 17],
   1457 
   1458    // 35
   1459    [12, 151, 121, 7, 152, 122],
   1460    [12, 75, 47, 26, 76, 48],
   1461    [39, 54, 24, 14, 55, 25],
   1462    [22, 45, 15, 41, 46, 16],
   1463 
   1464    // 36
   1465    [6, 151, 121, 14, 152, 122],
   1466    [6, 75, 47, 34, 76, 48],
   1467    [46, 54, 24, 10, 55, 25],
   1468    [2, 45, 15, 64, 46, 16],
   1469 
   1470    // 37
   1471    [17, 152, 122, 4, 153, 123],
   1472    [29, 74, 46, 14, 75, 47],
   1473    [49, 54, 24, 10, 55, 25],
   1474    [24, 45, 15, 46, 46, 16],
   1475 
   1476    // 38
   1477    [4, 152, 122, 18, 153, 123],
   1478    [13, 74, 46, 32, 75, 47],
   1479    [48, 54, 24, 14, 55, 25],
   1480    [42, 45, 15, 32, 46, 16],
   1481 
   1482    // 39
   1483    [20, 147, 117, 4, 148, 118],
   1484    [40, 75, 47, 7, 76, 48],
   1485    [43, 54, 24, 22, 55, 25],
   1486    [10, 45, 15, 67, 46, 16],
   1487 
   1488    // 40
   1489    [19, 148, 118, 6, 149, 119],
   1490    [18, 75, 47, 31, 76, 48],
   1491    [34, 54, 24, 34, 55, 25],
   1492    [20, 45, 15, 61, 46, 16]
   1493  ];
   1494 
   1495  const qrRSBlock = function(totalCount, dataCount) {
   1496    const _this = {};
   1497    _this.totalCount = totalCount;
   1498    _this.dataCount = dataCount;
   1499    return _this;
   1500  };
   1501 
   1502  const _this = {};
   1503 
   1504  const getRsBlockTable = function(typeNumber, errorCorrectionLevel) {
   1505 
   1506    switch(errorCorrectionLevel) {
   1507    case QRErrorCorrectionLevel.L :
   1508      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
   1509    case QRErrorCorrectionLevel.M :
   1510      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
   1511    case QRErrorCorrectionLevel.Q :
   1512      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
   1513    case QRErrorCorrectionLevel.H :
   1514      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
   1515    default :
   1516      return undefined;
   1517    }
   1518  };
   1519 
   1520  _this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {
   1521 
   1522    const rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);
   1523 
   1524    if (typeof rsBlock == 'undefined') {
   1525      throw 'bad rs block @ typeNumber:' + typeNumber +
   1526          '/errorCorrectionLevel:' + errorCorrectionLevel;
   1527    }
   1528 
   1529    const length = rsBlock.length / 3;
   1530 
   1531    const list = [];
   1532 
   1533    for (let i = 0; i < length; i += 1) {
   1534 
   1535      const count = rsBlock[i * 3 + 0];
   1536      const totalCount = rsBlock[i * 3 + 1];
   1537      const dataCount = rsBlock[i * 3 + 2];
   1538 
   1539      for (let j = 0; j < count; j += 1) {
   1540        list.push(qrRSBlock(totalCount, dataCount) );
   1541      }
   1542    }
   1543 
   1544    return list;
   1545  };
   1546 
   1547  return _this;
   1548 }();
   1549 
   1550 //---------------------------------------------------------------------
   1551 // qrBitBuffer
   1552 //---------------------------------------------------------------------
   1553 
   1554 const qrBitBuffer = function() {
   1555 
   1556  const _buffer = [];
   1557  let _length = 0;
   1558 
   1559  const _this = {};
   1560 
   1561  _this.getBuffer = function() {
   1562    return _buffer;
   1563  };
   1564 
   1565  _this.getAt = function(index) {
   1566    const bufIndex = Math.floor(index / 8);
   1567    return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
   1568  };
   1569 
   1570  _this.put = function(num, length) {
   1571    for (let i = 0; i < length; i += 1) {
   1572      _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
   1573    }
   1574  };
   1575 
   1576  _this.getLengthInBits = function() {
   1577    return _length;
   1578  };
   1579 
   1580  _this.putBit = function(bit) {
   1581 
   1582    const bufIndex = Math.floor(_length / 8);
   1583    if (_buffer.length <= bufIndex) {
   1584      _buffer.push(0);
   1585    }
   1586 
   1587    if (bit) {
   1588      _buffer[bufIndex] |= (0x80 >>> (_length % 8) );
   1589    }
   1590 
   1591    _length += 1;
   1592  };
   1593 
   1594  return _this;
   1595 };
   1596 
   1597 //---------------------------------------------------------------------
   1598 // qrNumber
   1599 //---------------------------------------------------------------------
   1600 
   1601 const qrNumber = function(data) {
   1602 
   1603  const _mode = QRMode.MODE_NUMBER;
   1604  const _data = data;
   1605 
   1606  const _this = {};
   1607 
   1608  _this.getMode = function() {
   1609    return _mode;
   1610  };
   1611 
   1612  _this.getLength = function(buffer) {
   1613    return _data.length;
   1614  };
   1615 
   1616  _this.write = function(buffer) {
   1617 
   1618    const data = _data;
   1619 
   1620    let i = 0;
   1621 
   1622    while (i + 2 < data.length) {
   1623      buffer.put(strToNum(data.substring(i, i + 3) ), 10);
   1624      i += 3;
   1625    }
   1626 
   1627    if (i < data.length) {
   1628      if (data.length - i == 1) {
   1629        buffer.put(strToNum(data.substring(i, i + 1) ), 4);
   1630      } else if (data.length - i == 2) {
   1631        buffer.put(strToNum(data.substring(i, i + 2) ), 7);
   1632      }
   1633    }
   1634  };
   1635 
   1636  const strToNum = function(s) {
   1637    let num = 0;
   1638    for (let i = 0; i < s.length; i += 1) {
   1639      num = num * 10 + chatToNum(s.charAt(i) );
   1640    }
   1641    return num;
   1642  };
   1643 
   1644  const chatToNum = function(c) {
   1645    if ('0' <= c && c <= '9') {
   1646      return c.charCodeAt(0) - '0'.charCodeAt(0);
   1647    }
   1648    throw 'illegal char :' + c;
   1649  };
   1650 
   1651  return _this;
   1652 };
   1653 
   1654 //---------------------------------------------------------------------
   1655 // qrAlphaNum
   1656 //---------------------------------------------------------------------
   1657 
   1658 const qrAlphaNum = function(data) {
   1659 
   1660  const _mode = QRMode.MODE_ALPHA_NUM;
   1661  const _data = data;
   1662 
   1663  const _this = {};
   1664 
   1665  _this.getMode = function() {
   1666    return _mode;
   1667  };
   1668 
   1669  _this.getLength = function(buffer) {
   1670    return _data.length;
   1671  };
   1672 
   1673  _this.write = function(buffer) {
   1674 
   1675    const s = _data;
   1676 
   1677    let i = 0;
   1678 
   1679    while (i + 1 < s.length) {
   1680      buffer.put(
   1681        getCode(s.charAt(i) ) * 45 +
   1682        getCode(s.charAt(i + 1) ), 11);
   1683      i += 2;
   1684    }
   1685 
   1686    if (i < s.length) {
   1687      buffer.put(getCode(s.charAt(i) ), 6);
   1688    }
   1689  };
   1690 
   1691  const getCode = function(c) {
   1692 
   1693    if ('0' <= c && c <= '9') {
   1694      return c.charCodeAt(0) - '0'.charCodeAt(0);
   1695    } else if ('A' <= c && c <= 'Z') {
   1696      return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;
   1697    } else {
   1698      switch (c) {
   1699      case '\u0020' : return 36;
   1700      case '$' : return 37;
   1701      case '%' : return 38;
   1702      case '*' : return 39;
   1703      case '+' : return 40;
   1704      case '-' : return 41;
   1705      case '.' : return 42;
   1706      case '/' : return 43;
   1707      case ':' : return 44;
   1708      default :
   1709        throw 'illegal char :' + c;
   1710      }
   1711    }
   1712  };
   1713 
   1714  return _this;
   1715 };
   1716 
   1717 //---------------------------------------------------------------------
   1718 // qr8BitByte
   1719 //---------------------------------------------------------------------
   1720 
   1721 const qr8BitByte = function(data) {
   1722 
   1723  const _mode = QRMode.MODE_8BIT_BYTE;
   1724  const _data = data;
   1725  const _bytes = qrcode.stringToBytes(data);
   1726 
   1727  const _this = {};
   1728 
   1729  _this.getMode = function() {
   1730    return _mode;
   1731  };
   1732 
   1733  _this.getLength = function(buffer) {
   1734    return _bytes.length;
   1735  };
   1736 
   1737  _this.write = function(buffer) {
   1738    for (let i = 0; i < _bytes.length; i += 1) {
   1739      buffer.put(_bytes[i], 8);
   1740    }
   1741  };
   1742 
   1743  return _this;
   1744 };
   1745 
   1746 //---------------------------------------------------------------------
   1747 // qrKanji
   1748 //---------------------------------------------------------------------
   1749 
   1750 const qrKanji = function(data) {
   1751 
   1752  const _mode = QRMode.MODE_KANJI;
   1753  const _data = data;
   1754 
   1755  const stringToBytes = qrcode.stringToBytes;
   1756  !function(c, code) {
   1757    // self test for sjis support.
   1758    const test = stringToBytes(c);
   1759    if (test.length != 2 || ( (test[0] << 8) | test[1]) != code) {
   1760      throw 'sjis not supported.';
   1761    }
   1762  }('\u53cb', 0x9746);
   1763 
   1764  const _bytes = stringToBytes(data);
   1765 
   1766  const _this = {};
   1767 
   1768  _this.getMode = function() {
   1769    return _mode;
   1770  };
   1771 
   1772  _this.getLength = function(buffer) {
   1773    return ~~(_bytes.length / 2);
   1774  };
   1775 
   1776  _this.write = function(buffer) {
   1777 
   1778    const data = _bytes;
   1779 
   1780    let i = 0;
   1781 
   1782    while (i + 1 < data.length) {
   1783 
   1784      let c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
   1785 
   1786      if (0x8140 <= c && c <= 0x9FFC) {
   1787        c -= 0x8140;
   1788      } else if (0xE040 <= c && c <= 0xEBBF) {
   1789        c -= 0xC140;
   1790      } else {
   1791        throw 'illegal char at ' + (i + 1) + '/' + c;
   1792      }
   1793 
   1794      c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);
   1795 
   1796      buffer.put(c, 13);
   1797 
   1798      i += 2;
   1799    }
   1800 
   1801    if (i < data.length) {
   1802      throw 'illegal char at ' + (i + 1);
   1803    }
   1804  };
   1805 
   1806  return _this;
   1807 };
   1808 
   1809 //=====================================================================
   1810 // GIF Support etc.
   1811 //
   1812 
   1813 //---------------------------------------------------------------------
   1814 // byteArrayOutputStream
   1815 //---------------------------------------------------------------------
   1816 
   1817 const byteArrayOutputStream = function() {
   1818 
   1819  const _bytes = [];
   1820 
   1821  const _this = {};
   1822 
   1823  _this.writeByte = function(b) {
   1824    _bytes.push(b & 0xff);
   1825  };
   1826 
   1827  _this.writeShort = function(i) {
   1828    _this.writeByte(i);
   1829    _this.writeByte(i >>> 8);
   1830  };
   1831 
   1832  _this.writeBytes = function(b, off, len) {
   1833    off = off || 0;
   1834    len = len || b.length;
   1835    for (let i = 0; i < len; i += 1) {
   1836      _this.writeByte(b[i + off]);
   1837    }
   1838  };
   1839 
   1840  _this.writeString = function(s) {
   1841    for (let i = 0; i < s.length; i += 1) {
   1842      _this.writeByte(s.charCodeAt(i) );
   1843    }
   1844  };
   1845 
   1846  _this.toByteArray = function() {
   1847    return _bytes;
   1848  };
   1849 
   1850  _this.toString = function() {
   1851    let s = '';
   1852    s += '[';
   1853    for (let i = 0; i < _bytes.length; i += 1) {
   1854      if (i > 0) {
   1855        s += ',';
   1856      }
   1857      s += _bytes[i];
   1858    }
   1859    s += ']';
   1860    return s;
   1861  };
   1862 
   1863  return _this;
   1864 };
   1865 
   1866 //---------------------------------------------------------------------
   1867 // base64EncodeOutputStream
   1868 //---------------------------------------------------------------------
   1869 
   1870 const base64EncodeOutputStream = function() {
   1871 
   1872  let _buffer = 0;
   1873  let _buflen = 0;
   1874  let _length = 0;
   1875  let _base64 = '';
   1876 
   1877  const _this = {};
   1878 
   1879  const writeEncoded = function(b) {
   1880    _base64 += String.fromCharCode(encode(b & 0x3f) );
   1881  };
   1882 
   1883  const encode = function(n) {
   1884    if (n < 0) {
   1885      throw 'n:' + n;
   1886    } else if (n < 26) {
   1887      return 0x41 + n;
   1888    } else if (n < 52) {
   1889      return 0x61 + (n - 26);
   1890    } else if (n < 62) {
   1891      return 0x30 + (n - 52);
   1892    } else if (n == 62) {
   1893      return 0x2b;
   1894    } else if (n == 63) {
   1895      return 0x2f;
   1896    } else {
   1897      throw 'n:' + n;
   1898    }
   1899  };
   1900 
   1901  _this.writeByte = function(n) {
   1902 
   1903    _buffer = (_buffer << 8) | (n & 0xff);
   1904    _buflen += 8;
   1905    _length += 1;
   1906 
   1907    while (_buflen >= 6) {
   1908      writeEncoded(_buffer >>> (_buflen - 6) );
   1909      _buflen -= 6;
   1910    }
   1911  };
   1912 
   1913  _this.flush = function() {
   1914 
   1915    if (_buflen > 0) {
   1916      writeEncoded(_buffer << (6 - _buflen) );
   1917      _buffer = 0;
   1918      _buflen = 0;
   1919    }
   1920 
   1921    if (_length % 3 != 0) {
   1922      // padding
   1923      const padlen = 3 - _length % 3;
   1924      for (let i = 0; i < padlen; i += 1) {
   1925        _base64 += '=';
   1926      }
   1927    }
   1928  };
   1929 
   1930  _this.toString = function() {
   1931    return _base64;
   1932  };
   1933 
   1934  return _this;
   1935 };
   1936 
   1937 //---------------------------------------------------------------------
   1938 // base64DecodeInputStream
   1939 //---------------------------------------------------------------------
   1940 
   1941 const base64DecodeInputStream = function(str) {
   1942 
   1943  const _str = str;
   1944  let _pos = 0;
   1945  let _buffer = 0;
   1946  let _buflen = 0;
   1947 
   1948  const _this = {};
   1949 
   1950  _this.read = function() {
   1951 
   1952    while (_buflen < 8) {
   1953 
   1954      if (_pos >= _str.length) {
   1955        if (_buflen == 0) {
   1956          return -1;
   1957        }
   1958        throw 'unexpected end of file./' + _buflen;
   1959      }
   1960 
   1961      const c = _str.charAt(_pos);
   1962      _pos += 1;
   1963 
   1964      if (c == '=') {
   1965        _buflen = 0;
   1966        return -1;
   1967      } else if (c.match(/^\s$/) ) {
   1968        // ignore if whitespace.
   1969        continue;
   1970      }
   1971 
   1972      _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
   1973      _buflen += 6;
   1974    }
   1975 
   1976    const n = (_buffer >>> (_buflen - 8) ) & 0xff;
   1977    _buflen -= 8;
   1978    return n;
   1979  };
   1980 
   1981  const decode = function(c) {
   1982    if (0x41 <= c && c <= 0x5a) {
   1983      return c - 0x41;
   1984    } else if (0x61 <= c && c <= 0x7a) {
   1985      return c - 0x61 + 26;
   1986    } else if (0x30 <= c && c <= 0x39) {
   1987      return c - 0x30 + 52;
   1988    } else if (c == 0x2b) {
   1989      return 62;
   1990    } else if (c == 0x2f) {
   1991      return 63;
   1992    } else {
   1993      throw 'c:' + c;
   1994    }
   1995  };
   1996 
   1997  return _this;
   1998 };
   1999 
   2000 //---------------------------------------------------------------------
   2001 // gifImage (B/W)
   2002 //---------------------------------------------------------------------
   2003 
   2004 const gifImage = function(width, height) {
   2005 
   2006  const _width = width;
   2007  const _height = height;
   2008  const _data = new Array(width * height);
   2009 
   2010  const _this = {};
   2011 
   2012  _this.setPixel = function(x, y, pixel) {
   2013    _data[y * _width + x] = pixel;
   2014  };
   2015 
   2016  _this.write = function(out) {
   2017 
   2018    //---------------------------------
   2019    // GIF Signature
   2020 
   2021    out.writeString('GIF87a');
   2022 
   2023    //---------------------------------
   2024    // Screen Descriptor
   2025 
   2026    out.writeShort(_width);
   2027    out.writeShort(_height);
   2028 
   2029    out.writeByte(0x80); // 2bit
   2030    out.writeByte(0);
   2031    out.writeByte(0);
   2032 
   2033    //---------------------------------
   2034    // Global Color Map
   2035 
   2036    // black
   2037    out.writeByte(0x00);
   2038    out.writeByte(0x00);
   2039    out.writeByte(0x00);
   2040 
   2041    // white
   2042    out.writeByte(0xff);
   2043    out.writeByte(0xff);
   2044    out.writeByte(0xff);
   2045 
   2046    //---------------------------------
   2047    // Image Descriptor
   2048 
   2049    out.writeString(',');
   2050    out.writeShort(0);
   2051    out.writeShort(0);
   2052    out.writeShort(_width);
   2053    out.writeShort(_height);
   2054    out.writeByte(0);
   2055 
   2056    //---------------------------------
   2057    // Local Color Map
   2058 
   2059    //---------------------------------
   2060    // Raster Data
   2061 
   2062    const lzwMinCodeSize = 2;
   2063    const raster = getLZWRaster(lzwMinCodeSize);
   2064 
   2065    out.writeByte(lzwMinCodeSize);
   2066 
   2067    let offset = 0;
   2068 
   2069    while (raster.length - offset > 255) {
   2070      out.writeByte(255);
   2071      out.writeBytes(raster, offset, 255);
   2072      offset += 255;
   2073    }
   2074 
   2075    out.writeByte(raster.length - offset);
   2076    out.writeBytes(raster, offset, raster.length - offset);
   2077    out.writeByte(0x00);
   2078 
   2079    //---------------------------------
   2080    // GIF Terminator
   2081    out.writeString(';');
   2082  };
   2083 
   2084  const bitOutputStream = function(out) {
   2085 
   2086    const _out = out;
   2087    let _bitLength = 0;
   2088    let _bitBuffer = 0;
   2089 
   2090    const _this = {};
   2091 
   2092    _this.write = function(data, length) {
   2093 
   2094      if ( (data >>> length) != 0) {
   2095        throw 'length over';
   2096      }
   2097 
   2098      while (_bitLength + length >= 8) {
   2099        _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
   2100        length -= (8 - _bitLength);
   2101        data >>>= (8 - _bitLength);
   2102        _bitBuffer = 0;
   2103        _bitLength = 0;
   2104      }
   2105 
   2106      _bitBuffer = (data << _bitLength) | _bitBuffer;
   2107      _bitLength = _bitLength + length;
   2108    };
   2109 
   2110    _this.flush = function() {
   2111      if (_bitLength > 0) {
   2112        _out.writeByte(_bitBuffer);
   2113      }
   2114    };
   2115 
   2116    return _this;
   2117  };
   2118 
   2119  const getLZWRaster = function(lzwMinCodeSize) {
   2120 
   2121    const clearCode = 1 << lzwMinCodeSize;
   2122    const endCode = (1 << lzwMinCodeSize) + 1;
   2123    let bitLength = lzwMinCodeSize + 1;
   2124 
   2125    // Setup LZWTable
   2126    const table = lzwTable();
   2127 
   2128    for (let i = 0; i < clearCode; i += 1) {
   2129      table.add(String.fromCharCode(i) );
   2130    }
   2131    table.add(String.fromCharCode(clearCode) );
   2132    table.add(String.fromCharCode(endCode) );
   2133 
   2134    const byteOut = byteArrayOutputStream();
   2135    const bitOut = bitOutputStream(byteOut);
   2136 
   2137    // clear code
   2138    bitOut.write(clearCode, bitLength);
   2139 
   2140    let dataIndex = 0;
   2141 
   2142    let s = String.fromCharCode(_data[dataIndex]);
   2143    dataIndex += 1;
   2144 
   2145    while (dataIndex < _data.length) {
   2146 
   2147      const c = String.fromCharCode(_data[dataIndex]);
   2148      dataIndex += 1;
   2149 
   2150      if (table.contains(s + c) ) {
   2151 
   2152        s = s + c;
   2153 
   2154      } else {
   2155 
   2156        bitOut.write(table.indexOf(s), bitLength);
   2157 
   2158        if (table.size() < 0xfff) {
   2159 
   2160          if (table.size() == (1 << bitLength) ) {
   2161            bitLength += 1;
   2162          }
   2163 
   2164          table.add(s + c);
   2165        }
   2166 
   2167        s = c;
   2168      }
   2169    }
   2170 
   2171    bitOut.write(table.indexOf(s), bitLength);
   2172 
   2173    // end code
   2174    bitOut.write(endCode, bitLength);
   2175 
   2176    bitOut.flush();
   2177 
   2178    return byteOut.toByteArray();
   2179  };
   2180 
   2181  const lzwTable = function() {
   2182 
   2183    const _map = {};
   2184    let _size = 0;
   2185 
   2186    const _this = {};
   2187 
   2188    _this.add = function(key) {
   2189      if (_this.contains(key) ) {
   2190        throw 'dup key:' + key;
   2191      }
   2192      _map[key] = _size;
   2193      _size += 1;
   2194    };
   2195 
   2196    _this.size = function() {
   2197      return _size;
   2198    };
   2199 
   2200    _this.indexOf = function(key) {
   2201      return _map[key];
   2202    };
   2203 
   2204    _this.contains = function(key) {
   2205      return typeof _map[key] != 'undefined';
   2206    };
   2207 
   2208    return _this;
   2209  };
   2210 
   2211  return _this;
   2212 };
   2213 
   2214 const createDataURL = function(width, height, getPixel) {
   2215  const gif = gifImage(width, height);
   2216  for (let y = 0; y < height; y += 1) {
   2217    for (let x = 0; x < width; x += 1) {
   2218      gif.setPixel(x, y, getPixel(x, y) );
   2219    }
   2220  }
   2221 
   2222  const b = byteArrayOutputStream();
   2223  gif.write(b);
   2224 
   2225  const base64 = base64EncodeOutputStream();
   2226  const bytes = b.toByteArray();
   2227  for (let i = 0; i < bytes.length; i += 1) {
   2228    base64.writeByte(bytes[i]);
   2229  }
   2230  base64.flush();
   2231 
   2232  return 'data:image/gif;base64,' + base64;
   2233 };
   2234 
   2235 export default qrcode;
   2236 
   2237 export const stringToBytes = qrcode.stringToBytes;