UNPKG

@duetds/date-picker

Version:

Duet Date Picker is an open source version of Duet Design System’s accessible date picker.

1,924 lines (1,558 loc) 465 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.png = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ (function (Buffer){ 'use strict'; var interlaceUtils = require('./interlace'); 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(); } } exports.dataToBitMap = function(data, bitmapInfo) { var width = bitmapInfo.width; var height = bitmapInfo.height; var depth = bitmapInfo.depth; var bpp = bitmapInfo.bpp; var interlace = 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) { images = interlaceUtils.getImagePasses(width, height); getPxPos = interlaceUtils.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; }; }).call(this,require("buffer").Buffer) },{"./interlace":11,"buffer":32}],2:[function(require,module,exports){ (function (Buffer){ 'use strict'; var constants = require('./constants'); module.exports = 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(data, inIndex); 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; }; }).call(this,require("buffer").Buffer) },{"./constants":4,"buffer":32}],3:[function(require,module,exports){ (function (process,Buffer){ 'use strict'; var util = require('util'); var Stream = require('stream'); 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); } }; }).call(this,require('_process'),require("buffer").Buffer) },{"_process":51,"buffer":32,"stream":64,"util":69}],4:[function(require,module,exports){ 'use strict'; module.exports = { 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 }; },{}],5:[function(require,module,exports){ 'use strict'; 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; }; },{}],6:[function(require,module,exports){ (function (Buffer){ 'use strict'; var paethPredictor = require('./paeth-predictor'); 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 }; module.exports = 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; }; }).call(this,require("buffer").Buffer) },{"./paeth-predictor":15,"buffer":32}],7:[function(require,module,exports){ (function (Buffer){ 'use strict'; var util = require('util'); var ChunkStream = require('./chunkstream'); var Filter = require('./filter-parse'); var FilterAsync = module.exports = function(bitmapInfo) { ChunkStream.call(this); var buffers = []; var that = this; this._filter = new Filter(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); }).call(this,require("buffer").Buffer) },{"./chunkstream":3,"./filter-parse":9,"buffer":32,"util":69}],8:[function(require,module,exports){ (function (Buffer){ 'use strict'; var SyncReader = require('./sync-reader'); var Filter = require('./filter-parse'); exports.process = function(inBuffer, bitmapInfo) { var outBuffers = []; var reader = new SyncReader(inBuffer); var filter = new Filter(bitmapInfo, { read: reader.read.bind(reader), write: function(bufferPart) { outBuffers.push(bufferPart); }, complete: function() { } }); filter.start(); reader.process(); return Buffer.concat(outBuffers); }; }).call(this,require("buffer").Buffer) },{"./filter-parse":9,"./sync-reader":22,"buffer":32}],9:[function(require,module,exports){ (function (Buffer){ 'use strict'; var interlaceUtils = require('./interlace'); var paethPredictor = require('./paeth-predictor'); 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 = 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) { var passes = interlaceUtils.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(); } }; }).call(this,require("buffer").Buffer) },{"./interlace":11,"./paeth-predictor":15,"buffer":32}],10:[function(require,module,exports){ (function (Buffer){ 'use strict'; 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; } } } module.exports = 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; }; }).call(this,require("buffer").Buffer) },{"buffer":32}],11:[function(require,module,exports){ 'use strict'; // 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] } ]; exports.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; }; exports.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); }; }; },{}],12:[function(require,module,exports){ (function (Buffer){ 'use strict'; var util = require('util'); var Stream = require('stream'); var constants = require('./constants'); var Packer = require('./packer'); 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); }; }).call(this,require("buffer").Buffer) },{"./constants":4,"./packer":14,"buffer":32,"stream":64,"util":69}],13:[function(require,module,exports){ (function (Buffer){ 'use strict'; var hasSyncZlib = true; var zlib = require('zlib'); if (!zlib.deflateSync) { hasSyncZlib = false; } var constants = require('./constants'); var Packer = require('./packer'); module.exports = function(metaData, opt) { 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 options = opt || {}; var packer = new Packer(options); var chunks = []; // Signature chunks.push(new Buffer(constants.PNG_SIGNATURE)); // Header chunks.push(packer.packIHDR(metaData.width, metaData.height)); if (metaData.gamma) { chunks.push(packer.packGAMA(metaData.gamma)); } var filteredData = packer.filterData(metaData.data, metaData.width, metaData.height); // compress it var compressedData = zlib.deflateSync(filteredData, packer.getDeflateOptions()); filteredData = null; if (!compressedData || !compressedData.length) { throw new Error('bad png - invalid compressed data response'); } chunks.push(packer.packIDAT(compressedData)); // End chunks.push(packer.packIEND()); return Buffer.concat(chunks); }; }).call(this,require("buffer").Buffer) },{"./constants":4,"./packer":14,"buffer":32,"zlib":30}],14:[function(require,module,exports){ (function (Buffer){ 'use strict'; var constants = require('./constants'); var CrcStream = require('./crc'); var bitPacker = require('./bitpacker'); var filter = require('./filter-pack'); var zlib = require('zlib'); 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 = filter(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(CrcStream.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); }; }).call(this,require("buffer").Buffer) },{"./bitpacker":2,"./constants":4,"./crc":5,"./filter-pack":6,"buffer":32,"zlib":30}],15:[function(require,module,exports){ 'use strict'; module.exports = 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; }; },{}],16:[function(require,module,exports){ 'use strict'; var util = require('util'); var zlib = require('zlib'); var ChunkStream = require('./chunkstream'); var FilterAsync = require('./filter-parse-async'); var Parser = require('./parser'); var bitmapper = require('./bitmapper'); var formatNormaliser = require('./format-normaliser'); 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 FilterAsync(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); }; },{"./bitmapper":1,"./chunkstream":3,"./filter-parse-async":7,"./format-normaliser":10,"./parser":18,"util":69,"zlib":30}],17:[function(require,module,exports){ (function (Buffer){ 'use strict'; var hasSyncZlib = true; var zlib = require('zlib'); var inflateSync = require('./sync-inflate'); if (!zlib.deflateSync) { hasSyncZlib = false; } var SyncReader = require('./sync-reader'); var FilterSync = require('./filter-parse-sync'); var Parser = require('./parser'); var bitmapper = require('./bitmapper'); var formatNormaliser = require('./format-normaliser'); module.exports = 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 = new Parser(options, { read: reader.read.bind(reader), error: handleError, metadata: handleMetaData, gamma: handleGamma, palette: handlePalette, transColor: handleTransColor, inflateData: handleInflateData, simpleTransparency: handleSimpleTransparency }); parser.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 = inflateSync(inflateData, { chunkSize: imageSize, maxLength: imageSize }); } inflateData = null; if (!inflatedData || !inflatedData.length) { throw new Error('bad png - invalid inflate data response'); } var unfilteredData = FilterSync.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; }; }).call(this,require("buffer").Buffer) },{"./bitmapper":1,"./filter-parse-sync":8,"./format-normaliser":10,"./parser":18,"./sync-inflate":21,"./sync-reader":22,"buffer":32,"zlib":30}],18:[function(require,module,exports){ (function (Buffer){ 'use strict'; var constants = require('./constants'); var CrcCalculator = require('./crc'); 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 CrcCalculator(); 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