text: 'use strict';
  
  function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
  
  var fs = _interopDefault(require('fs'));
  var util = _interopDefault(require('util'));
  var stream = _interopDefault(require('stream'));
  var zlib = _interopDefault(require('zlib'));
  var assert = _interopDefault(require('assert'));
  var buffer = _interopDefault(require('buffer'));
  
  var pixelmatch_1 = pixelmatch;
  
  function pixelmatch(img1, img2, output, width, height, options) {
  
      if (!options) options = {};
  
      var threshold = options.threshold === undefined ? 0.1 : options.threshold;
  
      // maximum acceptable square distance between two colors;
      // 35215 is the maximum possible value for the YIQ difference metric
      var maxDelta = 35215 * threshold * threshold,
          diff = 0;
  
      // compare each pixel of one image against the other one
      for (var y = 0; y < height; y++) {
          for (var x = 0; x < width; x++) {
  
              var pos = (y * width + x) * 4;
  
              // squared YUV distance between colors at this pixel position
              var delta = colorDelta(img1, img2, pos, pos);
  
              // the color difference is above the threshold
              if (delta > maxDelta) {
                  // check it's a real rendering difference or just anti-aliasing
                  if (!options.includeAA && (antialiased(img1, x, y, width, height, img2) ||
                                     antialiased(img2, x, y, width, height, img1))) {
                      // one of the pixels is anti-aliasing; draw as yellow and do not count as difference
                      if (output) drawPixel(output, pos, 255, 255, 0);
  
                  } else {
                      // found substantial difference not caused by anti-aliasing; draw it as red
                      if (output) drawPixel(output, pos, 255, 0, 0);
                      diff++;
                  }
  
              } else if (output) {
                  // pixels are similar; draw background as grayscale image blended with white
                  var val = blend(grayPixel(img1, pos), 0.1);
                  drawPixel(output, pos, val, val, val);
              }
          }
      }
  
      // return the number of different pixels
      return diff;
  }
  
  // check if a pixel is likely a part of anti-aliasing;
  // based on "Anti-aliased Pixel and Intensity Slope Detector" paper by V. Vysniauskas, 2009
  
  function antialiased(img, x1, y1, width, height, img2) {
      var x0 = Math.max(x1 - 1, 0),
          y0 = Math.max(y1 - 1, 0),
          x2 = Math.min(x1 + 1, width - 1),
          y2 = Math.min(y1 + 1, height - 1),
          pos = (y1 * width + x1) * 4,
          zeroes = 0,
          positives = 0,
          negatives = 0,
          min = 0,
          max = 0,
          minX, minY, maxX, maxY;
  
      // go through 8 adjacent pixels
      for (var x = x0; x <= x2; x++) {
          for (var y = y0; y <= y2; y++) {
              if (x === x1 && y === y1) continue;
  
              // brightness delta between the center pixel and adjacent one
              var delta = colorDelta(img, img, pos, (y * width + x) * 4, true);
  
              // count the number of equal, darker and brighter adjacent pixels
              if (delta === 0) zeroes++;
              else if (delta < 0) negatives++;
              else if (delta > 0) positives++;
  
              // if found more than 2 equal siblings, it's definitely not anti-aliasing
              if (zeroes > 2) return false;
  
              if (!img2) continue;
  
              // remember the darkest pixel
              if (delta < min) {
                  min = delta;
                  minX = x;
                  minY = y;
              }
              // remember the brightest pixel
              if (delta > max) {
                  max = delta;
                  maxX = x;
                  maxY = y;
              }
          }
      }
  
      if (!img2) return true;
  
      // if there are no both darker and brighter pixels among siblings, it's not anti-aliasing
      if (negatives === 0 || positives === 0) return false;
  
      // if either the darkest or the brightest pixel has more than 2 equal siblings in both images
      // (definitely not anti-aliased), this pixel is anti-aliased
      return (!antialiased(img, minX, minY, width, height) && !antialiased(img2, minX, minY, width, height)) ||
             (!antialiased(img, maxX, maxY, width, height) && !antialiased(img2, maxX, maxY, width, height));
  }
  
  // calculate color difference according to the paper "Measuring perceived color difference
  // using YIQ NTSC transmission color space in mobile applications" by Y. Kotsarenko and F. Ramos
  
  function colorDelta(img1, img2, k, m, yOnly) {
      var a1 = img1[k + 3] / 255,
          a2 = img2[m + 3] / 255,
  
          r1 = blend(img1[k + 0], a1),
          g1 = blend(img1[k + 1], a1),
          b1 = blend(img1[k + 2], a1),
  
          r2 = blend(img2[m + 0], a2),
          g2 = blend(img2[m + 1], a2),
          b2 = blend(img2[m + 2], a2),
  
          y = rgb2y(r1, g1, b1) - rgb2y(r2, g2, b2);
  
      if (yOnly) return y; // brightness difference only
  
      var i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2),
          q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);
  
      return 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q;
  }
  
  function rgb2y(r, g, b) { return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; }
  function rgb2i(r, g, b) { return r * 0.59597799 - g * 0.27417610 - b * 0.32180189; }
  function rgb2q(r, g, b) { return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; }
  
  // blend semi-transparent color with white
  function blend(c, a) {
      return 255 + (c - 255) * a;
  }
  
  function drawPixel(output, pos, r, g, b) {
      output[pos + 0] = r;
      output[pos + 1] = g;
      output[pos + 2] = b;
      output[pos + 3] = 255;
  }
  
  function grayPixel(img, i) {
      var a = img[i + 3] / 255,
          r = blend(img[i + 0], a),
          g = blend(img[i + 1], a),
          b = blend(img[i + 2], a);
      return rgb2y(r, g, b);
  }
  
  function createCommonjsModule(fn, module) {
  	return module = { exports: {} }, fn(module, module.exports), module.exports;
  }
  
  var chunkstream = createCommonjsModule(function (module) {
  
  
  
  
  
  
  var ChunkStream = module.exports = function() {
    stream.call(this);
  
    this._buffers = [];
    this._buffered = 0;
  
    this._reads = [];
    this._paused = false;
  
    this._encoding = 'utf8';
    this.writable = true;
  };
  util.inherits(ChunkStream, stream);
  
  
  ChunkStream.prototype.read = function(length, callback) {
  
    this._reads.push({
      length: Math.abs(length), // if length < 0 then at most this length
      allowLess: length < 0,
      func: callback
    });
  
    process.nextTick(function() {
      this._process();
  
      // its paused and there is not enought data then ask for more
      if (this._paused && this._reads.length > 0) {
        this._paused = false;
  
        this.emit('drain');
      }
    }.bind(this));
  };
  
  ChunkStream.prototype.write = function(data, encoding) {
  
    if (!this.writable) {
      this.emit('error', new Error('Stream not writable'));
      return false;
    }
  
    var dataBuffer;
    if (Buffer.isBuffer(data)) {
      dataBuffer = data;
    }
    else {
      dataBuffer = new Buffer(data, encoding || this._encoding);
    }
  
    this._buffers.push(dataBuffer);
    this._buffered += dataBuffer.length;
  
    this._process();
  
    // ok if there are no more read requests
    if (this._reads && this._reads.length === 0) {
      this._paused = true;
    }
  
    return this.writable && !this._paused;
  };
  
  ChunkStream.prototype.end = function(data, encoding) {
  
    if (data) {
      this.write(data, encoding);
    }
  
    this.writable = false;
  
    // already destroyed
    if (!this._buffers) {
      return;
    }
  
    // enqueue or handle end
    if (this._buffers.length === 0) {
      this._end();
    }
    else {
      this._buffers.push(null);
      this._process();
    }
  };
  
  ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
  
  ChunkStream.prototype._end = function() {
  
    if (this._reads.length > 0) {
      this.emit('error',
        new Error('Unexpected end of input')
      );
    }
  
    this.destroy();
  };
  
  ChunkStream.prototype.destroy = function() {
  
    if (!this._buffers) {
      return;
    }
  
    this.writable = false;
    this._reads = null;
    this._buffers = null;
  
    this.emit('close');
  };
  
  ChunkStream.prototype._processReadAllowingLess = function(read) {
    // ok there is any data so that we can satisfy this request
    this._reads.shift(); // == read
  
    // first we need to peek into first buffer
    var smallerBuf = this._buffers[0];
  
    // ok there is more data than we need
    if (smallerBuf.length > read.length) {
  
      this._buffered -= read.length;
      this._buffers[0] = smallerBuf.slice(read.length);
  
      read.func.call(this, smallerBuf.slice(0, read.length));
  
    }
    else {
      // ok this is less than maximum length so use it all
      this._buffered -= smallerBuf.length;
      this._buffers.shift(); // == smallerBuf
  
      read.func.call(this, smallerBuf);
    }
  };
  
  ChunkStream.prototype._processRead = function(read) {
    this._reads.shift(); // == read
  
    var pos = 0;
    var count = 0;
    var data = new Buffer(read.length);
  
    // create buffer for all data
    while (pos < read.length) {
  
      var buf = this._buffers[count++];
      var len = Math.min(buf.length, read.length - pos);
  
      buf.copy(data, pos, 0, len);
      pos += len;
  
      // last buffer wasn't used all so just slice it and leave
      if (len !== buf.length) {
        this._buffers[--count] = buf.slice(len);
      }
    }
  
    // remove all used buffers
    if (count > 0) {
      this._buffers.splice(0, count);
    }
  
    this._buffered -= read.length;
  
    read.func.call(this, data);
  };
  
  ChunkStream.prototype._process = function() {
  
    try {
      // as long as there is any data and read requests
      while (this._buffered > 0 && this._reads && this._reads.length > 0) {
  
        var read = this._reads[0];
  
        // read any data (but no more than length)
        if (read.allowLess) {
          this._processReadAllowingLess(read);
  
        }
        else if (this._buffered >= read.length) {
          // ok we can meet some expectations
  
          this._processRead(read);
        }
        else {
          // not enought data to satisfy first request in queue
          // so we need to wait for more
          break;
        }
      }
  
      if (this._buffers && !this.writable) {
        this._end();
      }
    }
    catch (ex) {
      this.emit('error', ex);
    }
  };
  });
  
  // Adam 7
  //   0 1 2 3 4 5 6 7
  // 0 x 6 4 6 x 6 4 6
  // 1 7 7 7 7 7 7 7 7
  // 2 5 6 5 6 5 6 5 6
  // 3 7 7 7 7 7 7 7 7
  // 4 3 6 4 6 3 6 4 6
  // 5 7 7 7 7 7 7 7 7
  // 6 5 6 5 6 5 6 5 6
  // 7 7 7 7 7 7 7 7 7
  
  
  var imagePasses = [
    { // pass 1 - 1px
      x: [0],
      y: [0]
    },
    { // pass 2 - 1px
      x: [4],
      y: [0]
    },
    { // pass 3 - 2px
      x: [0, 4],
      y: [4]
    },
    { // pass 4 - 4px
      x: [2, 6],
      y: [0, 4]
    },
    { // pass 5 - 8px
      x: [0, 2, 4, 6],
      y: [2, 6]
    },
    { // pass 6 - 16px
      x: [1, 3, 5, 7],
      y: [0, 2, 4, 6]
    },
    { // pass 7 - 32px
      x: [0, 1, 2, 3, 4, 5, 6, 7],
      y: [1, 3, 5, 7]
    }
  ];
  
  var getImagePasses = function(width, height) {
    var images = [];
    var xLeftOver = width % 8;
    var yLeftOver = height % 8;
    var xRepeats = (width - xLeftOver) / 8;
    var yRepeats = (height - yLeftOver) / 8;
    for (var i = 0; i < imagePasses.length; i++) {
      var pass = imagePasses[i];
      var passWidth = xRepeats * pass.x.length;
      var passHeight = yRepeats * pass.y.length;
      for (var j = 0; j < pass.x.length; j++) {
        if (pass.x[j] < xLeftOver) {
          passWidth++;
        }
        else {
          break;
        }
      }
      for (j = 0; j < pass.y.length; j++) {
        if (pass.y[j] < yLeftOver) {
          passHeight++;
        }
        else {
          break;
        }
      }
      if (passWidth > 0 && passHeight > 0) {
        images.push({ width: passWidth, height: passHeight, index: i });
      }
    }
    return images;
  };
  
  var getInterlaceIterator = function(width) {
    return function(x, y, pass) {
      var outerXLeftOver = x % imagePasses[pass].x.length;
      var outerX = (((x - outerXLeftOver) / imagePasses[pass].x.length) * 8) + imagePasses[pass].x[outerXLeftOver];
      var outerYLeftOver = y % imagePasses[pass].y.length;
      var outerY = (((y - outerYLeftOver) / imagePasses[pass].y.length) * 8) + imagePasses[pass].y[outerYLeftOver];
      return (outerX * 4) + (outerY * width * 4);
    };
  };
  
  var interlace = {
  	getImagePasses: getImagePasses,
  	getInterlaceIterator: getInterlaceIterator
  };
  
  var paethPredictor = function paethPredictor(left, above, upLeft) {
  
    var paeth = left + above - upLeft;
    var pLeft = Math.abs(paeth - left);
    var pAbove = Math.abs(paeth - above);
    var pUpLeft = Math.abs(paeth - upLeft);
  
    if (pLeft <= pAbove && pLeft <= pUpLeft) {
      return left;
    }
    if (pAbove <= pUpLeft) {
      return above;
    }
    return upLeft;
  };
  
  var filterParse = createCommonjsModule(function (module) {
  
  
  
  
  function getByteWidth(width, bpp, depth) {
    var byteWidth = width * bpp;
    if (depth !== 8) {
      byteWidth = Math.ceil(byteWidth / (8 / depth));
    }
    return byteWidth;
  }
  
  var Filter = module.exports = function(bitmapInfo, dependencies) {
  
    var width = bitmapInfo.width;
    var height = bitmapInfo.height;
    var interlace$1 = bitmapInfo.interlace;
    var bpp = bitmapInfo.bpp;
    var depth = bitmapInfo.depth;
  
    this.read = dependencies.read;
    this.write = dependencies.write;
    this.complete = dependencies.complete;
  
    this._imageIndex = 0;
    this._images = [];
    if (interlace$1) {
      var passes = interlace.getImagePasses(width, height);
      for (var i = 0; i < passes.length; i++) {
        this._images.push({
          byteWidth: getByteWidth(passes[i].width, bpp, depth),
          height: passes[i].height,
          lineIndex: 0
        });
      }
    }
    else {
      this._images.push({
        byteWidth: getByteWidth(width, bpp, depth),
        height: height,
        lineIndex: 0
      });
    }
  
    // when filtering the line we look at the pixel to the left
    // the spec also says it is done on a byte level regardless of the number of pixels
    // so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back
    // a pixel rather than just a different byte part. However if we are sub byte, we ignore.
    if (depth === 8) {
      this._xComparison = bpp;
    }
    else if (depth === 16) {
      this._xComparison = bpp * 2;
    }
    else {
      this._xComparison = 1;
    }
  };
  
  Filter.prototype.start = function() {
    this.read(this._images[this._imageIndex].byteWidth + 1, this._reverseFilterLine.bind(this));
  };
  
  Filter.prototype._unFilterType1 = function(rawData, unfilteredLine, byteWidth) {
  
    var xComparison = this._xComparison;
    var xBiggerThan = xComparison - 1;
  
    for (var x = 0; x < byteWidth; x++) {
      var rawByte = rawData[1 + x];
      var f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
      unfilteredLine[x] = rawByte + f1Left;
    }
  };
  
  Filter.prototype._unFilterType2 = function(rawData, unfilteredLine, byteWidth) {
  
    var lastLine = this._lastLine;
  
    for (var x = 0; x < byteWidth; x++) {
      var rawByte = rawData[1 + x];
      var f2Up = lastLine ? lastLine[x] : 0;
      unfilteredLine[x] = rawByte + f2Up;
    }
  };
  
  Filter.prototype._unFilterType3 = function(rawData, unfilteredLine, byteWidth) {
  
    var xComparison = this._xComparison;
    var xBiggerThan = xComparison - 1;
    var lastLine = this._lastLine;
  
    for (var x = 0; x < byteWidth; x++) {
      var rawByte = rawData[1 + x];
      var f3Up = lastLine ? lastLine[x] : 0;
      var f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
      var f3Add = Math.floor((f3Left + f3Up) / 2);
      unfilteredLine[x] = rawByte + f3Add;
    }
  };
  
  Filter.prototype._unFilterType4 = function(rawData, unfilteredLine, byteWidth) {
  
    var xComparison = this._xComparison;
    var xBiggerThan = xComparison - 1;
    var lastLine = this._lastLine;
  
    for (var x = 0; x < byteWidth; x++) {
      var rawByte = rawData[1 + x];
      var f4Up = lastLine ? lastLine[x] : 0;
      var f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
      var f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
      var f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
      unfilteredLine[x] = rawByte + f4Add;
    }
  };
  
  Filter.prototype._reverseFilterLine = function(rawData) {
  
    var filter = rawData[0];
    var unfilteredLine;
    var currentImage = this._images[this._imageIndex];
    var byteWidth = currentImage.byteWidth;
  
    if (filter === 0) {
      unfilteredLine = rawData.slice(1, byteWidth + 1);
    }
    else {
  
      unfilteredLine = new Buffer(byteWidth);
  
      switch (filter) {
        case 1:
          this._unFilterType1(rawData, unfilteredLine, byteWidth);
          break;
        case 2:
          this._unFilterType2(rawData, unfilteredLine, byteWidth);
          break;
        case 3:
          this._unFilterType3(rawData, unfilteredLine, byteWidth);
          break;
        case 4:
          this._unFilterType4(rawData, unfilteredLine, byteWidth);
          break;
        default:
          throw new Error('Unrecognised filter type - ' + filter);
      }
    }
  
    this.write(unfilteredLine);
  
    currentImage.lineIndex++;
    if (currentImage.lineIndex >= currentImage.height) {
      this._lastLine = null;
      this._imageIndex++;
      currentImage = this._images[this._imageIndex];
    }
    else {
      this._lastLine = unfilteredLine;
    }
  
    if (currentImage) {
      // read, using the byte width that may be from the new current image
      this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
    }
    else {
      this._lastLine = null;
      this.complete();
    }
  };
  });
  
  var filterParseAsync = createCommonjsModule(function (module) {
  
  
  
  
  
  
  var FilterAsync = module.exports = function(bitmapInfo) {
    chunkstream.call(this);
  
    var buffers = [];
    var that = this;
    this._filter = new filterParse(bitmapInfo, {
      read: this.read.bind(this),
      write: function(buffer) {
        buffers.push(buffer);
      },
      complete: function() {
        that.emit('complete', Buffer.concat(buffers));
      }
    });
  
    this._filter.start();
  };
  util.inherits(FilterAsync, chunkstream);
  });
  
  var constants = {
  
    PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
  
    TYPE_IHDR: 0x49484452,
    TYPE_IEND: 0x49454e44,
    TYPE_IDAT: 0x49444154,
    TYPE_PLTE: 0x504c5445,
    TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase
    TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase
  
    // color-type bits
    COLORTYPE_GRAYSCALE: 0,
    COLORTYPE_PALETTE: 1,
    COLORTYPE_COLOR: 2,
    COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha
  
    // color-type combinations
    COLORTYPE_PALETTE_COLOR: 3,
    COLORTYPE_COLOR_ALPHA: 6,
  
    COLORTYPE_TO_BPP_MAP: {
      0: 1,
      2: 3,
      3: 1,
      4: 2,
      6: 4
    },
  
    GAMMA_DIVISION: 100000
  };
  
  var crc = createCommonjsModule(function (module) {
  
  var crcTable = [];
  
  (function() {
    for (var i = 0; i < 256; i++) {
      var currentCrc = i;
      for (var j = 0; j < 8; j++) {
        if (currentCrc & 1) {
          currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
        }
        else {
          currentCrc = currentCrc >>> 1;
        }
      }
      crcTable[i] = currentCrc;
    }
  }());
  
  var CrcCalculator = module.exports = function() {
    this._crc = -1;
  };
  
  CrcCalculator.prototype.write = function(data) {
  
    for (var i = 0; i < data.length; i++) {
      this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
    }
    return true;
  };
  
  CrcCalculator.prototype.crc32 = function() {
    return this._crc ^ -1;
  };
  
  
  CrcCalculator.crc32 = function(buf) {
  
    var crc = -1;
    for (var i = 0; i < buf.length; i++) {
      crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
    }
    return crc ^ -1;
  };
  });
  
  var parser = createCommonjsModule(function (module) {
  
  
  
  
  
  var Parser = module.exports = function(options, dependencies) {
  
    this._options = options;
    options.checkCRC = options.checkCRC !== false;
  
    this._hasIHDR = false;
    this._hasIEND = false;
    this._emittedHeadersFinished = false;
  
    // input flags/metadata
    this._palette = [];
    this._colorType = 0;
  
    this._chunks = {};
    this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this);
    this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this);
    this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this);
    this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this);
    this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this);
    this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this);
  
    this.read = dependencies.read;
    this.error = dependencies.error;
    this.metadata = dependencies.metadata;
    this.gamma = dependencies.gamma;
    this.transColor = dependencies.transColor;
    this.palette = dependencies.palette;
    this.parsed = dependencies.parsed;
    this.inflateData = dependencies.inflateData;
    this.finished = dependencies.finished;
    this.simpleTransparency = dependencies.simpleTransparency;
    this.headersFinished = dependencies.headersFinished || function() {};
  };
  
  Parser.prototype.start = function() {
    this.read(constants.PNG_SIGNATURE.length,
      this._parseSignature.bind(this)
    );
  };
  
  Parser.prototype._parseSignature = function(data) {
  
    var signature = constants.PNG_SIGNATURE;
  
    for (var i = 0; i < signature.length; i++) {
      if (data[i] !== signature[i]) {
        this.error(new Error('Invalid file signature'));
        return;
      }
    }
    this.read(8, this._parseChunkBegin.bind(this));
  };
  
  Parser.prototype._parseChunkBegin = function(data) {
  
    // chunk content length
    var length = data.readUInt32BE(0);
  
    // chunk type
    var type = data.readUInt32BE(4);
    var name = '';
    for (var i = 4; i < 8; i++) {
      name += String.fromCharCode(data[i]);
    }
  
    //console.log('chunk ', name, length);
  
    // chunk flags
    var ancillary = Boolean(data[4] & 0x20); // or critical
    //    priv = Boolean(data[5] & 0x20), // or public
    //    safeToCopy = Boolean(data[7] & 0x20); // or unsafe
  
    if (!this._hasIHDR && type !== constants.TYPE_IHDR) {
      this.error(new Error('Expected IHDR on beggining'));
      return;
    }
  
    this._crc = new crc();
    this._crc.write(new Buffer(name));
  
    if (this._chunks[type]) {
      return this._chunks[type](length);
    }
  
    if (!ancillary) {
      this.error(new Error('Unsupported critical chunk type ' + name));
      return;
    }
  
    this.read(length + 4, this._skipChunk.bind(this));
  };
  
  Parser.prototype._skipChunk = function(/*data*/) {
    this.read(8, this._parseChunkBegin.bind(this));
  };
  
  Parser.prototype._handleChunkEnd = function() {
    this.read(4, this._parseChunkEnd.bind(this));
  };
  
  Parser.prototype._parseChunkEnd = function(data) {
  
    var fileCrc = data.readInt32BE(0);
    var calcCrc = this._crc.crc32();
  
    // check CRC
    if (this._options.checkCRC && calcCrc !== fileCrc) {
      this.error(new Error('Crc error - ' + fileCrc + ' - ' + calcCrc));
      return;
    }
  
    if (!this._hasIEND) {
      this.read(8, this._parseChunkBegin.bind(this));
    }
  };
  
  Parser.prototype._handleIHDR = function(length) {
    this.read(length, this._parseIHDR.bind(this));
  };
  Parser.prototype._parseIHDR = function(data) {
  
    this._crc.write(data);
  
    var width = data.readUInt32BE(0);
    var height = data.readUInt32BE(4);
    var depth = data[8];
    var colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha
    var compr = data[10];
    var filter = data[11];
    var interlace = data[12];
  
    // console.log('    width', width, 'height', height,
    //     'depth', depth, 'colorType', colorType,
    //     'compr', compr, 'filter', filter, 'interlace', interlace
    // );
  
    if (depth !== 8 && depth !== 4 && depth !== 2 && depth !== 1 && depth !== 16) {
      this.error(new Error('Unsupported bit depth ' + depth));
      return;
    }
    if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) {
      this.error(new Error('Unsupported color type'));
      return;
    }
    if (compr !== 0) {
      this.error(new Error('Unsupported compression method'));
      return;
    }
    if (filter !== 0) {
      this.error(new Error('Unsupported filter method'));
      return;
    }
    if (interlace !== 0 && interlace !== 1) {
      this.error(new Error('Unsupported interlace method'));
      return;
    }
  
    this._colorType = colorType;
  
    var bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType];
  
    this._hasIHDR = true;
  
    this.metadata({
      width: width,
      height: height,
      depth: depth,
      interlace: Boolean(interlace),
      palette: Boolean(colorType & constants.COLORTYPE_PALETTE),
      color: Boolean(colorType & constants.COLORTYPE_COLOR),
      alpha: Boolean(colorType & constants.COLORTYPE_ALPHA),
      bpp: bpp,
      colorType: colorType
    });
  
    this._handleChunkEnd();
  };
  
  
  Parser.prototype._handlePLTE = function(length) {
    this.read(length, this._parsePLTE.bind(this));
  };
  Parser.prototype._parsePLTE = function(data) {
  
    this._crc.write(data);
  
    var entries = Math.floor(data.length / 3);
    // console.log('Palette:', entries);
  
    for (var i = 0; i < entries; i++) {
      this._palette.push([
        data[i * 3],
        data[i * 3 + 1],
        data[i * 3 + 2],
        0xff
      ]);
    }
  
    this.palette(this._palette);
  
    this._handleChunkEnd();
  };
  
  Parser.prototype._handleTRNS = function(length) {
    this.simpleTransparency();
    this.read(length, this._parseTRNS.bind(this));
  };
  Parser.prototype._parseTRNS = function(data) {
  
    this._crc.write(data);
  
    // palette
    if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) {
      if (this._palette.length === 0) {
        this.error(new Error('Transparency chunk must be after palette'));
        return;
      }
      if (data.length > this._palette.length) {
        this.error(new Error('More transparent colors than palette size'));
        return;
      }
      for (var i = 0; i < data.length; i++) {
        this._palette[i][3] = data[i];
      }
      this.palette(this._palette);
    }
  
    // for colorType 0 (grayscale) and 2 (rgb)
    // there might be one gray/color defined as transparent
    if (this._colorType === constants.COLORTYPE_GRAYSCALE) {
      // grey, 2 bytes
      this.transColor([data.readUInt16BE(0)]);
    }
    if (this._colorType === constants.COLORTYPE_COLOR) {
      this.transColor([data.readUInt16BE(0), data.readUInt16BE(2), data.readUInt16BE(4)]);
    }
  
    this._handleChunkEnd();
  };
  
  Parser.prototype._handleGAMA = function(length) {
    this.read(length, this._parseGAMA.bind(this));
  };
  Parser.prototype._parseGAMA = function(data) {
  
    this._crc.write(data);
    this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION);
  
    this._handleChunkEnd();
  };
  
  Parser.prototype._handleIDAT = function(length) {
    if (!this._emittedHeadersFinished) {
      this._emittedHeadersFinished = true;
      this.headersFinished();
    }
    this.read(-length, this._parseIDAT.bind(this, length));
  };
  Parser.prototype._parseIDAT = function(length, data) {
  
    this._crc.write(data);
  
    if (this._colorType === constants.COLORTYPE_PALETTE_COLOR && this._palette.length === 0) {
      throw new Error('Expected palette not found');
    }
  
    this.inflateData(data);
    var leftOverLength = length - data.length;
  
    if (leftOverLength > 0) {
      this._handleIDAT(leftOverLength);
    }
    else {
      this._handleChunkEnd();
    }
  };
  
  Parser.prototype._handleIEND = function(length) {
    this.read(length, this._parseIEND.bind(this));
  };
  Parser.prototype._parseIEND = function(data) {
  
    this._crc.write(data);
  
    this._hasIEND = true;
    this._handleChunkEnd();
  
    if (this.finished) {
      this.finished();
    }
  };
  });
  
  var pixelBppMapper = [
    // 0 - dummy entry
    function() {},
  
    // 1 - L
    // 0: 0, 1: 0, 2: 0, 3: 0xff
    function(pxData, data, pxPos, rawPos) {
      if (rawPos === data.length) {
        throw new Error('Ran out of data');
      }
  
      var pixel = data[rawPos];
      pxData[pxPos] = pixel;
      pxData[pxPos + 1] = pixel;
      pxData[pxPos + 2] = pixel;
      pxData[pxPos + 3] = 0xff;
    },
  
    // 2 - LA
    // 0: 0, 1: 0, 2: 0, 3: 1
    function(pxData, data, pxPos, rawPos) {
      if (rawPos + 1 >= data.length) {
        throw new Error('Ran out of data');
      }
  
      var pixel = data[rawPos];
      pxData[pxPos] = pixel;
      pxData[pxPos + 1] = pixel;
      pxData[pxPos + 2] = pixel;
      pxData[pxPos + 3] = data[rawPos + 1];
    },
  
    // 3 - RGB
    // 0: 0, 1: 1, 2: 2, 3: 0xff
    function(pxData, data, pxPos, rawPos) {
      if (rawPos + 2 >= data.length) {
        throw new Error('Ran out of data');
      }
  
      pxData[pxPos] = data[rawPos];
      pxData[pxPos + 1] = data[rawPos + 1];
      pxData[pxPos + 2] = data[rawPos + 2];
      pxData[pxPos + 3] = 0xff;
    },
  
    // 4 - RGBA
    // 0: 0, 1: 1, 2: 2, 3: 3
    function(pxData, data, pxPos, rawPos) {
      if (rawPos + 3 >= data.length) {
        throw new Error('Ran out of data');
      }
  
      pxData[pxPos] = data[rawPos];
      pxData[pxPos + 1] = data[rawPos + 1];
      pxData[pxPos + 2] = data[rawPos + 2];
      pxData[pxPos + 3] = data[rawPos + 3];
    }
  ];
  
  var pixelBppCustomMapper = [
    // 0 - dummy entry
    function() {},
  
    // 1 - L
    // 0: 0, 1: 0, 2: 0, 3: 0xff
    function(pxData, pixelData, pxPos, maxBit) {
      var pixel = pixelData[0];
      pxData[pxPos] = pixel;
      pxData[pxPos + 1] = pixel;
      pxData[pxPos + 2] = pixel;
      pxData[pxPos + 3] = maxBit;
    },
  
    // 2 - LA
    // 0: 0, 1: 0, 2: 0, 3: 1
    function(pxData, pixelData, pxPos) {
      var pixel = pixelData[0];
      pxData[pxPos] = pixel;
      pxData[pxPos + 1] = pixel;
      pxData[pxPos + 2] = pixel;
      pxData[pxPos + 3] = pixelData[1];
    },
  
    // 3 - RGB
    // 0: 0, 1: 1, 2: 2, 3: 0xff
    function(pxData, pixelData, pxPos, maxBit) {
      pxData[pxPos] = pixelData[0];
      pxData[pxPos + 1] = pixelData[1];
      pxData[pxPos + 2] = pixelData[2];
      pxData[pxPos + 3] = maxBit;
    },
  
    // 4 - RGBA
    // 0: 0, 1: 1, 2: 2, 3: 3
    function(pxData, pixelData, pxPos) {
      pxData[pxPos] = pixelData[0];
      pxData[pxPos + 1] = pixelData[1];
      pxData[pxPos + 2] = pixelData[2];
      pxData[pxPos + 3] = pixelData[3];
    }
  ];
  
  function bitRetriever(data, depth) {
  
    var leftOver = [];
    var i = 0;
  
    function split() {
      if (i === data.length) {
        throw new Error('Ran out of data');
      }
      var byte = data[i];
      i++;
      var byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
      switch (depth) {
        default:
          throw new Error('unrecognised depth');
        case 16:
          byte2 = data[i];
          i++;
          leftOver.push(((byte << 8) + byte2));
          break;
        case 4:
          byte2 = byte & 0x0f;
          byte1 = byte >> 4;
          leftOver.push(byte1, byte2);
          break;
        case 2:
          byte4 = byte & 3;
          byte3 = byte >> 2 & 3;
          byte2 = byte >> 4 & 3;
          byte1 = byte >> 6 & 3;
          leftOver.push(byte1, byte2, byte3, byte4);
          break;
        case 1:
          byte8 = byte & 1;
          byte7 = byte >> 1 & 1;
          byte6 = byte >> 2 & 1;
          byte5 = byte >> 3 & 1;
          byte4 = byte >> 4 & 1;
          byte3 = byte >> 5 & 1;
          byte2 = byte >> 6 & 1;
          byte1 = byte >> 7 & 1;
          leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
          break;
      }
    }
  
    return {
      get: function(count) {
        while (leftOver.length < count) {
          split();
        }
        var returner = leftOver.slice(0, count);
        leftOver = leftOver.slice(count);
        return returner;
      },
      resetAfterLine: function() {
        leftOver.length = 0;
      },
      end: function() {
        if (i !== data.length) {
          throw new Error('extra data found');
        }
      }
    };
  }
  
  function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { // eslint-disable-line max-params
    var imageWidth = image.width;
    var imageHeight = image.height;
    var imagePass = image.index;
    for (var y = 0; y < imageHeight; y++) {
      for (var x = 0; x < imageWidth; x++) {
        var pxPos = getPxPos(x, y, imagePass);
        pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
        rawPos += bpp; //eslint-disable-line no-param-reassign
      }
    }
    return rawPos;
  }
  
  function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) { // eslint-disable-line max-params
    var imageWidth = image.width;
    var imageHeight = image.height;
    var imagePass = image.index;
    for (var y = 0; y < imageHeight; y++) {
      for (var x = 0; x < imageWidth; x++) {
        var pixelData = bits.get(bpp);
        var pxPos = getPxPos(x, y, imagePass);
        pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
      }
      bits.resetAfterLine();
    }
  }
  
  var dataToBitMap = function(data, bitmapInfo) {
  
    var width = bitmapInfo.width;
    var height = bitmapInfo.height;
    var depth = bitmapInfo.depth;
    var bpp = bitmapInfo.bpp;
    var interlace$1 = bitmapInfo.interlace;
  
    if (depth !== 8) {
      var bits = bitRetriever(data, depth);
    }
    var pxData;
    if (depth <= 8) {
      pxData = new Buffer(width * height * 4);
    }
    else {
      pxData = new Uint16Array(width * height * 4);
    }
    var maxBit = Math.pow(2, depth) - 1;
    var rawPos = 0;
    var images;
    var getPxPos;
  
    if (interlace$1) {
      images = interlace.getImagePasses(width, height);
      getPxPos = interlace.getInterlaceIterator(width, height);
    }
    else {
      var nonInterlacedPxPos = 0;
      getPxPos = function() {
        var returner = nonInterlacedPxPos;
        nonInterlacedPxPos += 4;
        return returner;
      };
      images = [{ width: width, height: height }];
    }
  
    for (var imageIndex = 0; imageIndex < images.length; imageIndex++) {
      if (depth === 8) {
        rawPos = mapImage8Bit(images[imageIndex], pxData, getPxPos, bpp, data, rawPos);
      }
      else {
        mapImageCustomBit(images[imageIndex], pxData, getPxPos, bpp, bits, maxBit);
      }
    }
    if (depth === 8) {
      if (rawPos !== data.length) {
        throw new Error('extra data found');
      }
    }
    else {
      bits.end();
    }
  
    return pxData;
  };
  
  var bitmapper = {
  	dataToBitMap: dataToBitMap
  };
  
  function dePalette(indata, outdata, width, height, palette) {
    var pxPos = 0;
    // use values from palette
    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        var color = palette[indata[pxPos]];
  
        if (!color) {
          throw new Error('index ' + indata[pxPos] + ' not in palette');
        }
  
        for (var i = 0; i < 4; i++) {
          outdata[pxPos + i] = color[i];
        }
        pxPos += 4;
      }
    }
  }
  
  function replaceTransparentColor(indata, outdata, width, height, transColor) {
    var pxPos = 0;
    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        var makeTrans = false;
  
        if (transColor.length === 1) {
          if (transColor[0] === indata[pxPos]) {
            makeTrans = true;
          }
        }
        else if (transColor[0] === indata[pxPos] && transColor[1] === indata[pxPos + 1] && transColor[2] === indata[pxPos + 2]) {
          makeTrans = true;
        }
        if (makeTrans) {
          for (var i = 0; i < 4; i++) {
            outdata[pxPos + i] = 0;
          }
        }
        pxPos += 4;
      }
    }
  }
  
  function scaleDepth(indata, outdata, width, height, depth) {
    var maxOutSample = 255;
    var maxInSample = Math.pow(2, depth) - 1;
    var pxPos = 0;
  
    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        for (var i = 0; i < 4; i++) {
          outdata[pxPos + i] = Math.floor((indata[pxPos + i] * maxOutSample) / maxInSample + 0.5);
        }
        pxPos += 4;
      }
    }
  }
  
  var formatNormaliser = function(indata, imageData) {
  
    var depth = imageData.depth;
    var width = imageData.width;
    var height = imageData.height;
    var colorType = imageData.colorType;
    var transColor = imageData.transColor;
    var palette = imageData.palette;
  
    var outdata = indata; // only different for 16 bits
  
    if (colorType === 3) { // paletted
      dePalette(indata, outdata, width, height, palette);
    }
    else {
      if (transColor) {
        replaceTransparentColor(indata, outdata, width, height, transColor);
      }
      // if it needs scaling
      if (depth !== 8) {
        // if we need to change the buffer size
        if (depth === 16) {
          outdata = new Buffer(width * height * 4);
        }
        scaleDepth(indata, outdata, width, height, depth);
      }
    }
    return outdata;
  };
  
  var parserAsync = createCommonjsModule(function (module) {
  
  
  
  
  
  
  
  
  
  var ParserAsync = module.exports = function(options) {
    chunkstream.call(this);
  
    this._parser = new parser(options, {
      read: this.read.bind(this),
      error: this._handleError.bind(this),
      metadata: this._handleMetaData.bind(this),
      gamma: this.emit.bind(this, 'gamma'),
      palette: this._handlePalette.bind(this),
      transColor: this._handleTransColor.bind(this),
      finished: this._finished.bind(this),
      inflateData: this._inflateData.bind(this),
      simpleTransparency: this._simpleTransparency.bind(this),
      headersFinished: this._headersFinished.bind(this)
    });
    this._options = options;
    this.writable = true;
  
    this._parser.start();
  };
  util.inherits(ParserAsync, chunkstream);
  
  
  ParserAsync.prototype._handleError = function(err) {
  
    this.emit('error', err);
  
    this.writable = false;
  
    this.destroy();
  
    if (this._inflate && this._inflate.destroy) {
      this._inflate.destroy();
    }
  
    if (this._filter) {
      this._filter.destroy();
      // For backward compatibility with Node 7 and below.
      // Suppress errors due to _inflate calling write() even after
      // it's destroy()'ed.
      this._filter.on('error', function() {});
    }
  
    this.errord = true;
  };
  
  ParserAsync.prototype._inflateData = function(data) {
    if (!this._inflate) {
      if (this._bitmapInfo.interlace) {
        this._inflate = zlib.createInflate();
  
        this._inflate.on('error', this.emit.bind(this, 'error'));
        this._filter.on('complete', this._complete.bind(this));
  
        this._inflate.pipe(this._filter);
      }
      else {
        var rowSize = ((this._bitmapInfo.width * this._bitmapInfo.bpp * this._bitmapInfo.depth + 7) >> 3) + 1;
        var imageSize = rowSize * this._bitmapInfo.height;
        var chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK);
  
        this._inflate = zlib.createInflate({ chunkSize: chunkSize });
        var leftToInflate = imageSize;
  
        var emitError = this.emit.bind(this, 'error');
        this._inflate.on('error', function(err) {
          if (!leftToInflate) {
            return;
          }
  
          emitError(err);
        });
        this._filter.on('complete', this._complete.bind(this));
  
        var filterWrite = this._filter.write.bind(this._filter);
        this._inflate.on('data', function(chunk) {
          if (!leftToInflate) {
            return;
          }
  
          if (chunk.length > leftToInflate) {
            chunk = chunk.slice(0, leftToInflate);
          }
  
          leftToInflate -= chunk.length;
  
          filterWrite(chunk);
        });
  
        this._inflate.on('end', this._filter.end.bind(this._filter));
      }
    }
    this._inflate.write(data);
  };
  
  ParserAsync.prototype._handleMetaData = function(metaData) {
    this._metaData = metaData;
    this._bitmapInfo = Object.create(metaData);
  
    this._filter = new filterParseAsync(this._bitmapInfo);
  };
  
  ParserAsync.prototype._handleTransColor = function(transColor) {
    this._bitmapInfo.transColor = transColor;
  };
  
  ParserAsync.prototype._handlePalette = function(palette) {
    this._bitmapInfo.palette = palette;
  };
  
  ParserAsync.prototype._simpleTransparency = function() {
    this._metaData.alpha = true;
  };
  
  ParserAsync.prototype._headersFinished = function() {
    // Up until this point, we don't know if we have a tRNS chunk (alpha)
    // so we can't emit metadata any earlier
    this.emit('metadata', this._metaData);
  };
  
  ParserAsync.prototype._finished = function() {
    if (this.errord) {
      return;
    }
  
    if (!this._inflate) {
      this.emit('error', 'No Inflate block');
    }
    else {
      // no more data to inflate
      this._inflate.end();
    }
    this.destroySoon();
  };
  
  ParserAsync.prototype._complete = function(filteredData) {
  
    if (this.errord) {
      return;
    }
  
    try {
      var bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
  
      var normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo);
      bitmapData = null;
    }
    catch (ex) {
      this._handleError(ex);
      return;
    }
  
    this.emit('parsed', normalisedBitmapData);
  };
  });
  
  var bitpacker = function(dataIn, width, height, options) {
    var outHasAlpha = [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(options.colorType) !== -1;
    if (options.colorType === options.inputColorType) {
      var bigEndian = (function() {
        var buffer = new ArrayBuffer(2);
        new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
        // Int16Array uses the platform's endianness.
        return new Int16Array(buffer)[0] !== 256;
      })();
      // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
      if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
        return dataIn;
      }
    }
  
    // map to a UInt16 array if data is 16bit, fix endianness below
    var data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
  
    var maxValue = 255;
    var inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
    if (inBpp === 4 && !options.inputHasAlpha) {
      inBpp = 3;
    }
    var outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
    if (options.bitDepth === 16) {
      maxValue = 65535;
      outBpp *= 2;
    }
    var outData = new Buffer(width * height * outBpp);
  
    var inIndex = 0;
    var outIndex = 0;
  
    var bgColor = options.bgColor || {};
    if (bgColor.red === undefined) {
      bgColor.red = maxValue;
    }
    if (bgColor.green === undefined) {
      bgColor.green = maxValue;
    }
    if (bgColor.blue === undefined) {
      bgColor.blue = maxValue;
    }
  
    function getRGBA() {
      var red;
      var green;
      var blue;
      var alpha = maxValue;
      switch (options.inputColorType) {
        case constants.COLORTYPE_COLOR_ALPHA:
          alpha = data[inIndex + 3];
          red = data[inIndex];
          green = data[inIndex + 1];
          blue = data[inIndex + 2];
          break;
        case constants.COLORTYPE_COLOR:
          red = data[inIndex];
          green = data[inIndex + 1];
          blue = data[inIndex + 2];
          break;
        case constants.COLORTYPE_ALPHA:
          alpha = data[inIndex + 1];
          red = data[inIndex];
          green = red;
          blue = red;
          break;
        case constants.COLORTYPE_GRAYSCALE:
          red = data[inIndex];
          green = red;
          blue = red;
          break;
        default:
          throw new Error('input color type:' + options.inputColorType + ' is not supported at present');
      }
  
      if (options.inputHasAlpha) {
        if (!outHasAlpha) {
          alpha /= maxValue;
          red = Math.min(Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0), maxValue);
          green = Math.min(Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0), maxValue);
          blue = Math.min(Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0), maxValue);
        }
      }
      return { red: red, green: green, blue: blue, alpha: alpha };
    }
  
    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        var rgba = getRGBA();
  
        switch (options.colorType) {
          case constants.COLORTYPE_COLOR_ALPHA:
          case constants.COLORTYPE_COLOR:
            if (options.bitDepth === 8) {
              outData[outIndex] = rgba.red;
              outData[outIndex + 1] = rgba.green;
              outData[outIndex + 2] = rgba.blue;
              if (outHasAlpha) {
                outData[outIndex + 3] = rgba.alpha;
              }
            }
            else {
              outData.writeUInt16BE(rgba.red, outIndex);
              outData.writeUInt16BE(rgba.green, outIndex + 2);
              outData.writeUInt16BE(rgba.blue, outIndex + 4);
              if (outHasAlpha) {
                outData.writeUInt16BE(rgba.alpha, outIndex + 6);
              }
            }
            break;
          case constants.COLORTYPE_ALPHA:
          case constants.COLORTYPE_GRAYSCALE:
            // Convert to grayscale and alpha
            var grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
            if (options.bitDepth === 8) {
              outData[outIndex] = grayscale;
              if (outHasAlpha) {
                outData[outIndex + 1] = rgba.alpha;
              }
            }
            else {
              outData.writeUInt16BE(grayscale, outIndex);
              if (outHasAlpha) {
                outData.writeUInt16BE(rgba.alpha, outIndex + 2);
              }
            }
            break;
          default:
            throw new Error('unrecognised color Type ' + options.colorType);
        }
  
        inIndex += inBpp;
        outIndex += outBpp;
      }
    }
  
    return outData;
  };
  
  function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
  
    for (var x = 0; x < byteWidth; x++) {
      rawData[rawPos + x] = pxData[pxPos + x];
    }
  }
  
  function filterSumNone(pxData, pxPos, byteWidth) {
  
    var sum = 0;
    var length = pxPos + byteWidth;
  
    for (var i = pxPos; i < length; i++) {
      sum += Math.abs(pxData[i]);
    }
    return sum;
  }
  
  function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
  
    for (var x = 0; x < byteWidth; x++) {
  
      var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
      var val = pxData[pxPos + x] - left;
  
      rawData[rawPos + x] = val;
    }
  }
  
  function filterSumSub(pxData, pxPos, byteWidth, bpp) {
  
    var sum = 0;
    for (var x = 0; x < byteWidth; x++) {
  
      var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
      var val = pxData[pxPos + x] - left;
  
      sum += Math.abs(val);
    }
  
    return sum;
  }
  
  function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
  
    for (var x = 0; x < byteWidth; x++) {
  
      var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
      var val = pxData[pxPos + x] - up;
  
      rawData[rawPos + x] = val;
    }
  }
  
  function filterSumUp(pxData, pxPos, byteWidth) {
  
    var sum = 0;
    var length = pxPos + byteWidth;
    for (var x = pxPos; x < length; x++) {
  
      var up = pxPos > 0 ? pxData[x - byteWidth] : 0;
      var val = pxData[x] - up;
  
      sum += Math.abs(val);
    }
  
    return sum;
  }
  
  function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
  
    for (var x = 0; x < byteWidth; x++) {
  
      var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
      var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
      var val = pxData[pxPos + x] - ((left + up) >> 1);
  
      rawData[rawPos + x] = val;
    }
  }
  
  function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
  
    var sum = 0;
    for (var x = 0; x < byteWidth; x++) {
  
      var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
      var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
      var val = pxData[pxPos + x] - ((left + up) >> 1);
  
      sum += Math.abs(val);
    }
  
    return sum;
  }
  
  function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
  
    for (var x = 0; x < byteWidth; x++) {
  
      var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
      var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
      var upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
      var val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
  
      rawData[rawPos + x] = val;
    }
  }
  
  function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
    var sum = 0;
    for (var x = 0; x < byteWidth; x++) {
  
      var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
      var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
      var upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
      var val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
  
      sum += Math.abs(val);
    }
  
    return sum;
  }
  
  var filters = {
    0: filterNone,
    1: filterSub,
    2: filterUp,
    3: filterAvg,
    4: filterPaeth
  };
  
  var filterSums = {
    0: filterSumNone,
    1: filterSumSub,
    2: filterSumUp,
    3: filterSumAvg,
    4: filterSumPaeth
  };
  
  var filterPack = function(pxData, width, height, options, bpp) {
  
    var filterTypes;
    if (!('filterType' in options) || options.filterType === -1) {
      filterTypes = [0, 1, 2, 3, 4];
    }
    else if (typeof options.filterType === 'number') {
      filterTypes = [options.filterType];
    }
    else {
      throw new Error('unrecognised filter types');
    }
  
    if (options.bitDepth === 16) {
      bpp *= 2;
    }
    var byteWidth = width * bpp;
    var rawPos = 0;
    var pxPos = 0;
    var rawData = new Buffer((byteWidth + 1) * height);
  
    var sel = filterTypes[0];
  
    for (var y = 0; y < height; y++) {
  
      if (filterTypes.length > 1) {
        // find best filter for this line (with lowest sum of values)
        var min = Infinity;
  
        for (var i = 0; i < filterTypes.length; i++) {
          var sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp);
          if (sum < min) {
            sel = filterTypes[i];
            min = sum;
          }
        }
      }
  
      rawData[rawPos] = sel;
      rawPos++;
      filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp);
      rawPos += byteWidth;
      pxPos += byteWidth;
    }
    return rawData;
  };
  
  var packer = createCommonjsModule(function (module) {
  
  
  
  
  
  
  
  var Packer = module.exports = function(options) {
    this._options = options;
  
    options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
    options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9;
    options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3;
    options.inputHasAlpha = options.inputHasAlpha != null ? options.inputHasAlpha : true;
    options.deflateFactory = options.deflateFactory || zlib.createDeflate;
    options.bitDepth = options.bitDepth || 8;
    // This is outputColorType
    options.colorType = (typeof options.colorType === 'number') ? options.colorType : constants.COLORTYPE_COLOR_ALPHA;
    options.inputColorType = (typeof options.inputColorType === 'number') ? options.inputColorType : constants.COLORTYPE_COLOR_ALPHA;
  
    if ([
      constants.COLORTYPE_GRAYSCALE,
      constants.COLORTYPE_COLOR,
      constants.COLORTYPE_COLOR_ALPHA,
      constants.COLORTYPE_ALPHA
    ].indexOf(options.colorType) === -1) {
      throw new Error('option color type:' + options.colorType + ' is not supported at present');
    }
    if ([
      constants.COLORTYPE_GRAYSCALE,
      constants.COLORTYPE_COLOR,
      constants.COLORTYPE_COLOR_ALPHA,
      constants.COLORTYPE_ALPHA
    ].indexOf(options.inputColorType) === -1) {
      throw new Error('option input color type:' + options.inputColorType + ' is not supported at present');
    }
    if (options.bitDepth !== 8 && options.bitDepth !== 16) {
      throw new Error('option bit depth:' + options.bitDepth + ' is not supported at present');
    }
  };
  
  Packer.prototype.getDeflateOptions = function() {
    return {
      chunkSize: this._options.deflateChunkSize,
      level: this._options.deflateLevel,
      strategy: this._options.deflateStrategy
    };
  };
  
  Packer.prototype.createDeflate = function() {
    return this._options.deflateFactory(this.getDeflateOptions());
  };
  
  Packer.prototype.filterData = function(data, width, height) {
    // convert to correct format for filtering (e.g. right bpp and bit depth)
    var packedData = bitpacker(data, width, height, this._options);
  
    // filter pixel data
    var bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
    var filteredData = filterPack(packedData, width, height, this._options, bpp);
    return filteredData;
  };
  
  Packer.prototype._packChunk = function(type, data) {
  
    var len = (data ? data.length : 0);
    var buf = new Buffer(len + 12);
  
    buf.writeUInt32BE(len, 0);
    buf.writeUInt32BE(type, 4);
  
    if (data) {
      data.copy(buf, 8);
    }
  
    buf.writeInt32BE(crc.crc32(buf.slice(4, buf.length - 4)), buf.length - 4);
    return buf;
  };
  
  Packer.prototype.packGAMA = function(gamma) {
    var buf = new Buffer(4);
    buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
    return this._packChunk(constants.TYPE_gAMA, buf);
  };
  
  Packer.prototype.packIHDR = function(width, height) {
  
    var buf = new Buffer(13);
    buf.writeUInt32BE(width, 0);
    buf.writeUInt32BE(height, 4);
    buf[8] = this._options.bitDepth; // Bit depth
    buf[9] = this._options.colorType; // colorType
    buf[10] = 0; // compression
    buf[11] = 0; // filter
    buf[12] = 0; // interlace
  
    return this._packChunk(constants.TYPE_IHDR, buf);
  };
  
  Packer.prototype.packIDAT = function(data) {
    return this._packChunk(constants.TYPE_IDAT, data);
  };
  
  Packer.prototype.packIEND = function() {
    return this._packChunk(constants.TYPE_IEND, null);
  };
  });
  
  var packerAsync = createCommonjsModule(function (module) {
  
  
  
  
  
  
  var PackerAsync = module.exports = function(opt) {
    stream.call(this);
  
    var options = opt || {};
  
    this._packer = new packer(options);
    this._deflate = this._packer.createDeflate();
  
    this.readable = true;
  };
  util.inherits(PackerAsync, stream);
  
  
  PackerAsync.prototype.pack = function(data, width, height, gamma) {
    // Signature
    this.emit('data', new Buffer(constants.PNG_SIGNATURE));
    this.emit('data', this._packer.packIHDR(width, height));
  
    if (gamma) {
      this.emit('data', this._packer.packGAMA(gamma));
    }
  
    var filteredData = this._packer.filterData(data, width, height);
  
    // compress it
    this._deflate.on('error', this.emit.bind(this, 'error'));
  
    this._deflate.on('data', function(compressedData) {
      this.emit('data', this._packer.packIDAT(compressedData));
    }.bind(this));
  
    this._deflate.on('end', function() {
      this.emit('data', this._packer.packIEND());
      this.emit('end');
    }.bind(this));
  
    this._deflate.end(filteredData);
  };
  });
  
  var syncInflate = createCommonjsModule(function (module, exports) {
  
  var assert$1 = assert.ok;
  
  
  
  var kMaxLength = buffer.kMaxLength;
  
  function Inflate(opts) {
    if (!(this instanceof Inflate)) {
      return new Inflate(opts);
    }
  
    if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) {
      opts.chunkSize = zlib.Z_MIN_CHUNK;
    }
  
    zlib.Inflate.call(this, opts);
  
    // Node 8 --> 9 compatibility check
    this._offset = this._offset === undefined ? this._outOffset : this._offset;
    this._buffer = this._buffer || this._outBuffer;
  
    if (opts && opts.maxLength != null) {
      this._maxLength = opts.maxLength;
    }
  }
  
  function createInflate(opts) {
    return new Inflate(opts);
  }
  
  function _close(engine, callback) {
    if (callback) {
      process.nextTick(callback);
    }
  
    // Caller may invoke .close after a zlib error (which will null _handle).
    if (!engine._handle) {
      return;
    }
  
    engine._handle.close();
    engine._handle = null;
  }
  
  Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
    if (typeof asyncCb === 'function') {
      return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
    }
  
    var self = this;
  
    var availInBefore = chunk && chunk.length;
    var availOutBefore = this._chunkSize - this._offset;
    var leftToInflate = this._maxLength;
    var inOff = 0;
  
    var buffers = [];
    var nread = 0;
  
    var error;
    this.on('error', function(err) {
      error = err;
    });
  
    function handleChunk(availInAfter, availOutAfter) {
      if (self._hadError) {
        return;
      }
  
      var have = availOutBefore - availOutAfter;
      assert$1(have >= 0, 'have should not go down');
  
      if (have > 0) {
        var out = self._buffer.slice(self._offset, self._offset + have);
        self._offset += have;
  
        if (out.length > leftToInflate) {
          out = out.slice(0, leftToInflate);
        }
  
        buffers.push(out);
        nread += out.length;
        leftToInflate -= out.length;
  
        if (leftToInflate === 0) {
          return false;
        }
      }
  
      if (availOutAfter === 0 || self._offset >= self._chunkSize) {
        availOutBefore = self._chunkSize;
        self._offset = 0;
        self._buffer = Buffer.allocUnsafe(self._chunkSize);
      }
  
      if (availOutAfter === 0) {
        inOff += (availInBefore - availInAfter);
        availInBefore = availInAfter;
  
        return true;
      }
  
      return false;
    }
  
    assert$1(this._handle, 'zlib binding closed');
    do {
      var res = this._handle.writeSync(flushFlag,
        chunk, // in
        inOff, // in_off
        availInBefore, // in_len
        this._buffer, // out
        this._offset, //out_off
        availOutBefore); // out_len
      // Node 8 --> 9 compatibility check
      res = res || this._writeState;
    } while (!this._hadError && handleChunk(res[0], res[1]));
  
    if (this._hadError) {
      throw error;
    }
  
    if (nread >= kMaxLength) {
      _close(this);
      throw new RangeError('Cannot create final Buffer. It would be larger than 0x' + kMaxLength.toString(16) + ' bytes');
    }
  
    var buf = Buffer.concat(buffers, nread);
    _close(this);
  
    return buf;
  };
  
  util.inherits(Inflate, zlib.Inflate);
  
  function zlibBufferSync(engine, buffer) {
    if (typeof buffer === 'string') {
      buffer = Buffer.from(buffer);
    }
    if (!(buffer instanceof Buffer)) {
      throw new TypeError('Not a string or buffer');
    }
  
    var flushFlag = engine._finishFlushFlag;
    if (flushFlag == null) {
      flushFlag = zlib.Z_FINISH;
    }
  
    return engine._processChunk(buffer, flushFlag);
  }
  
  function inflateSync(buffer, opts) {
    return zlibBufferSync(new Inflate(opts), buffer);
  }
  
  module.exports = exports = inflateSync;
  exports.Inflate = Inflate;
  exports.createInflate = createInflate;
  exports.inflateSync = inflateSync;
  });
  var syncInflate_1 = syncInflate.Inflate;
  var syncInflate_2 = syncInflate.createInflate;
  var syncInflate_3 = syncInflate.inflateSync;
  
  var syncReader = createCommonjsModule(function (module) {
  
  var SyncReader = module.exports = function(buffer) {
  
    this._buffer = buffer;
    this._reads = [];
  };
  
  SyncReader.prototype.read = function(length, callback) {
  
    this._reads.push({
      length: Math.abs(length), // if length < 0 then at most this length
      allowLess: length < 0,
      func: callback
    });
  };
  
  SyncReader.prototype.process = function() {
  
    // as long as there is any data and read requests
    while (this._reads.length > 0 && this._buffer.length) {
  
      var read = this._reads[0];
  
      if (this._buffer.length && (this._buffer.length >= read.length || read.allowLess)) {
  
        // ok there is any data so that we can satisfy this request
        this._reads.shift(); // == read
  
        var buf = this._buffer;
  
        this._buffer = buf.slice(read.length);
  
        read.func.call(this, buf.slice(0, read.length));
  
      }
      else {
        break;
      }
  
    }
  
    if (this._reads.length > 0) {
      return new Error('There are some read requests waitng on finished stream');
    }
  
    if (this._buffer.length > 0) {
      return new Error('unrecognised content at end of stream');
    }
  
  };
  });
  
  var process_1 = function(inBuffer, bitmapInfo) {
  
    var outBuffers = [];
    var reader = new syncReader(inBuffer);
    var filter = new filterParse(bitmapInfo, {
      read: reader.read.bind(reader),
      write: function(bufferPart) {
        outBuffers.push(bufferPart);
      },
      complete: function() {
      }
    });
  
    filter.start();
    reader.process();
  
    return Buffer.concat(outBuffers);
  };
  
  var filterParseSync = {
  	process: process_1
  };
  
  var hasSyncZlib = true;
  
  
  if (!zlib.deflateSync) {
    hasSyncZlib = false;
  }
  
  
  
  
  
  
  
  var parserSync = function(buffer, options) {
  
    if (!hasSyncZlib) {
      throw new Error('To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0');
    }
  
    var err;
    function handleError(_err_) {
      err = _err_;
    }
  
    var metaData;
    function handleMetaData(_metaData_) {
      metaData = _metaData_;
    }
  
    function handleTransColor(transColor) {
      metaData.transColor = transColor;
    }
  
    function handlePalette(palette) {
      metaData.palette = palette;
    }
  
    function handleSimpleTransparency() {
      metaData.alpha = true;
    }
  
    var gamma;
    function handleGamma(_gamma_) {
      gamma = _gamma_;
    }
  
    var inflateDataList = [];
    function handleInflateData(inflatedData) {
      inflateDataList.push(inflatedData);
    }
  
    var reader = new syncReader(buffer);
  
    var parser$1 = new parser(options, {
      read: reader.read.bind(reader),
      error: handleError,
      metadata: handleMetaData,
      gamma: handleGamma,
      palette: handlePalette,
      transColor: handleTransColor,
      inflateData: handleInflateData,
      simpleTransparency: handleSimpleTransparency
    });
  
    parser$1.start();
    reader.process();
  
    if (err) {
      throw err;
    }
  
    //join together the inflate datas
    var inflateData = Buffer.concat(inflateDataList);
    inflateDataList.length = 0;
  
    var inflatedData;
    if (metaData.interlace) {
      inflatedData = zlib.inflateSync(inflateData);
    }
    else {
      var rowSize = ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1;
      var imageSize = rowSize * metaData.height;
      inflatedData = syncInflate(inflateData, { chunkSize: imageSize, maxLength: imageSize });
    }
    inflateData = null;
  
    if (!inflatedData || !inflatedData.length) {
      throw new Error('bad png - invalid inflate data response');
    }
  
    var unfilteredData = filterParseSync.process(inflatedData, metaData);
    inflateData = null;
  
    var bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData);
    unfilteredData = null;
  
    var normalisedBitmapData = formatNormaliser(bitmapData, metaData);
  
    metaData.data = normalisedBitmapData;
    metaData.gamma = gamma || 0;
  
    return metaData;
  };
  
  var hasSyncZlib$1 = true;
  
  if (!zlib.deflateSync) {
    hasSyncZlib$1 = false;
  }
  
  
  
  var packerSync = function(metaData, opt) {
  
    if (!hasSyncZlib$1) {
      throw new Error('To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0');
    }
  
    var options = opt || {};
  
    var packer$1 = new packer(options);
  
    var chunks = [];
  
    // Signature
    chunks.push(new Buffer(constants.PNG_SIGNATURE));
  
    // Header
    chunks.push(packer$1.packIHDR(metaData.width, metaData.height));
  
    if (metaData.gamma) {
      chunks.push(packer$1.packGAMA(metaData.gamma));
    }
  
    var filteredData = packer$1.filterData(metaData.data, metaData.width, metaData.height);
  
    // compress it
    var compressedData = zlib.deflateSync(filteredData, packer$1.getDeflateOptions());
    filteredData = null;
  
    if (!compressedData || !compressedData.length) {
      throw new Error('bad png - invalid compressed data response');
    }
    chunks.push(packer$1.packIDAT(compressedData));
  
    // End
    chunks.push(packer$1.packIEND());
  
    return Buffer.concat(chunks);
  };
  
  var read = function(buffer, options) {
  
    return parserSync(buffer, options || {});
  };
  
  var write = function(png, options) {
  
    return packerSync(png, options);
  };
  
  var pngSync = {
  	read: read,
  	write: write
  };
  
  var png = createCommonjsModule(function (module, exports) {
  
  
  
  
  
  
  
  
  var PNG = exports.PNG = function(options) {
    stream.call(this);
  
    options = options || {}; // eslint-disable-line no-param-reassign
  
    // coerce pixel dimensions to integers (also coerces undefined -> 0):
    this.width = options.width | 0;
    this.height = options.height | 0;
  
    this.data = this.width > 0 && this.height > 0 ?
      new Buffer(4 * this.width * this.height) : null;
  
    if (options.fill && this.data) {
      this.data.fill(0);
    }
  
    this.gamma = 0;
    this.readable = this.writable = true;
  
    this._parser = new parserAsync(options);
  
    this._parser.on('error', this.emit.bind(this, 'error'));
    this._parser.on('close', this._handleClose.bind(this));
    this._parser.on('metadata', this._metadata.bind(this));
    this._parser.on('gamma', this._gamma.bind(this));
    this._parser.on('parsed', function(data) {
      this.data = data;
      this.emit('parsed', data);
    }.bind(this));
  
    this._packer = new packerAsync(options);
    this._packer.on('data', this.emit.bind(this, 'data'));
    this._packer.on('end', this.emit.bind(this, 'end'));
    this._parser.on('close', this._handleClose.bind(this));
    this._packer.on('error', this.emit.bind(this, 'error'));
  
  };
  util.inherits(PNG, stream);
  
  PNG.sync = pngSync;
  
  PNG.prototype.pack = function() {
  
    if (!this.data || !this.data.length) {
      this.emit('error', 'No data provided');
      return this;
    }
  
    process.nextTick(function() {
      this._packer.pack(this.data, this.width, this.height, this.gamma);
    }.bind(this));
  
    return this;
  };
  
  
  PNG.prototype.parse = function(data, callback) {
  
    if (callback) {
      var onParsed, onError;
  
      onParsed = function(parsedData) {
        this.removeListener('error', onError);
  
        this.data = parsedData;
        callback(null, this);
      }.bind(this);
  
      onError = function(err) {
        this.removeListener('parsed', onParsed);
  
        callback(err, null);
      }.bind(this);
  
      this.once('parsed', onParsed);
      this.once('error', onError);
    }
  
    this.end(data);
    return this;
  };
  
  PNG.prototype.write = function(data) {
    this._parser.write(data);
    return true;
  };
  
  PNG.prototype.end = function(data) {
    this._parser.end(data);
  };
  
  PNG.prototype._metadata = function(metadata) {
    this.width = metadata.width;
    this.height = metadata.height;
  
    this.emit('metadata', metadata);
  };
  
  PNG.prototype._gamma = function(gamma) {
    this.gamma = gamma;
  };
  
  PNG.prototype._handleClose = function() {
    if (!this._parser.writable && !this._packer.readable) {
      this.emit('close');
    }
  };
  
  
  PNG.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params
    // coerce pixel dimensions to integers (also coerces undefined -> 0):
    /* eslint-disable no-param-reassign */
    srcX |= 0;
    srcY |= 0;
    width |= 0;
    height |= 0;
    deltaX |= 0;
    deltaY |= 0;
    /* eslint-enable no-param-reassign */
  
    if (srcX > src.width || srcY > src.height || srcX + width > src.width || srcY + height > src.height) {
      throw new Error('bitblt reading outside image');
    }
  
    if (deltaX > dst.width || deltaY > dst.height || deltaX + width > dst.width || deltaY + height > dst.height) {
      throw new Error('bitblt writing outside image');
    }
  
    for (var y = 0; y < height; y++) {
      src.data.copy(dst.data,
        ((deltaY + y) * dst.width + deltaX) << 2,
        ((srcY + y) * src.width + srcX) << 2,
        ((srcY + y) * src.width + srcX + width) << 2
      );
    }
  };
  
  
  PNG.prototype.bitblt = function(dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params
  
    PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
    return this;
  };
  
  PNG.adjustGamma = function(src) {
    if (src.gamma) {
      for (var y = 0; y < src.height; y++) {
        for (var x = 0; x < src.width; x++) {
          var idx = (src.width * y + x) << 2;
  
          for (var i = 0; i < 3; i++) {
            var sample = src.data[idx + i] / 255;
            sample = Math.pow(sample, 1 / 2.2 / src.gamma);
            src.data[idx + i] = Math.round(sample * 255);
          }
        }
      }
      src.gamma = 0;
    }
  };
  
  PNG.prototype.adjustGamma = function() {
    PNG.adjustGamma(this);
  };
  });
  var png_1 = png.PNG;
  
  function getMismatchedPixels(pixelMatchInput) {
      const imgA = fs
          .createReadStream(pixelMatchInput.imageAPath)
          .pipe(new png_1())
          .on('parsed', doneReading);
      const imgB = fs
          .createReadStream(pixelMatchInput.imageBPath)
          .pipe(new png_1())
          .on('parsed', doneReading);
      let filesRead = 0;
      function doneReading() {
          if (++filesRead < 2)
              return;
          const mismatchedPixels = pixelmatch_1(imgA.data, imgB.data, null, pixelMatchInput.width, pixelMatchInput.height, {
              threshold: pixelMatchInput.pixelmatchThreshold,
              includeAA: false,
          });
          process.send(mismatchedPixels);
      }
  }
  process.on('message', getMismatchedPixels);
  