@stencil/core
Version:
A Compiler for Web Components and Progressive Web Apps
1,945 lines (1,562 loc) • 67.7 kB
JavaScript
'use strict';
var fs = require('fs');
var util = require('util');
var Stream = require('stream');
var zlib = require('zlib');
var require$$0 = require('assert');
var require$$1 = require('buffer');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
var Stream__default = /*#__PURE__*/_interopDefaultLegacy(Stream);
var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib);
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
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, basedir, module) {
return module = {
path: basedir,
exports: {},
require: function (path, base) {
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
}
}, fn(module, module.exports), module.exports;
}
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
}
var chunkstream = createCommonjsModule(function (module) {
var ChunkStream = module.exports = function() {
Stream__default['default'].call(this);
this._buffers = [];
this._buffered = 0;
this._reads = [];
this._paused = false;
this._encoding = 'utf8';
this.writable = true;
};
util__default['default'].inherits(ChunkStream, Stream__default['default']);
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__default['default'].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__default['default'].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__default['default'].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__default['default'].Z_MIN_CHUNK);
this._inflate = zlib__default['default'].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__default['default'].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.COLOR