diff --git a/.eslintrc b/.eslintrc index 31c8e16..8560625 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,7 +1,7 @@ { "ecmaFeatures": {}, "rules": { - "no-alert": 1, + "no-alert": 2, "no-array-constructor": 1, "no-bitwise": 0, "no-caller": 2, @@ -23,7 +23,7 @@ "no-empty": 2, "no-empty-character-class": 2, "no-empty-label": 1, - "no-eq-null": 1, + "no-eq-null": 0, "no-eval": 2, "no-ex-assign": 2, "no-extend-native": 0, @@ -36,7 +36,7 @@ "no-func-assign": 2, "no-implicit-coercion": 0, "no-implied-eval": 1, - "no-inline-comments": 1, + "no-inline-comments": 0, "no-inner-declarations": [2, "functions"], "no-invalid-regexp": 2, "no-invalid-this": 1, diff --git a/lib/bitmapper.js b/lib/bitmapper.js index 0c45f0d..a6f3c11 100644 --- a/lib/bitmapper.js +++ b/lib/bitmapper.js @@ -1,5 +1,34 @@ +'use strict'; + var interlaceUtils = require('./interlace'); +var pixelBppMap = { + 1: { // L + 0: 0, + 1: 0, + 2: 0, + 3: 0xff + }, + 2: { // LA + 0: 0, + 1: 0, + 2: 0, + 3: 1 + }, + 3: { // RGB + 0: 0, + 1: 1, + 2: 2, + 3: 0xff + }, + 4: { // RGBA + 0: 0, + 1: 1, + 2: 2, + 3: 3 + } +}; + function bitRetriever(data, depth) { var leftOver = []; @@ -14,7 +43,6 @@ function bitRetriever(data, depth) { switch(depth) { default: throw new Error("unrecognised depth"); - break; case 16: byte2 = data[i]; i++; @@ -74,8 +102,7 @@ exports.dataToBitMap = function(data, width, height, bpp, depth, interlace) { if (depth <= 8) { pxData = new Buffer(width * height * 4); } else { - // TODO: could be more effecient and use a buffer but change how we write to use 16 bit write methods with index * 2 - pxData = new Array(width * height * 4); + pxData = new Uint16Array(width * height * 4); } var maxBit = Math.pow(2, depth) - 1; var rawPos = 0; @@ -136,30 +163,3 @@ exports.dataToBitMap = function(data, width, height, bpp, depth, interlace) { return pxData; }; - -var pixelBppMap = { - 1: { // L - 0: 0, - 1: 0, - 2: 0, - 3: 0xff - }, - 2: { // LA - 0: 0, - 1: 0, - 2: 0, - 3: 1 - }, - 3: { // RGB - 0: 0, - 1: 1, - 2: 2, - 3: 0xff - }, - 4: { // RGBA - 0: 0, - 1: 1, - 2: 2, - 3: 3 - } -}; \ No newline at end of file diff --git a/lib/chunkstream.js b/lib/chunkstream.js index e57c1e7..feff3e4 100755 --- a/lib/chunkstream.js +++ b/lib/chunkstream.js @@ -138,22 +138,22 @@ ChunkStream.prototype._process = function() { this._reads.shift(); // == read // first we need to peek into first buffer - var buf = this._buffers[0]; + var smallerBuf = this._buffers[0]; // ok there is more data than we need - if (buf.length > read.length) { + if (smallerBuf.length > read.length) { this._buffered -= read.length; - this._buffers[0] = buf.slice(read.length); + this._buffers[0] = smallerBuf.slice(read.length); - read.func.call(this, buf.slice(0, 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 -= buf.length; - this._buffers.shift(); // == buf + this._buffered -= smallerBuf.length; + this._buffers.shift(); // == smallerBuf - read.func.call(this, buf); + read.func.call(this, smallerBuf); } } else if (this._buffered >= read.length) { diff --git a/lib/crc.js b/lib/crc.js index ef47f77..712a2ac 100755 --- a/lib/crc.js +++ b/lib/crc.js @@ -20,6 +20,22 @@ 'use strict'; +var crcTable = []; + +(function() { + for (var i = 0; i < 256; i++) { + var c = i; + for (var j = 0; j < 8; j++) { + if (c & 1) { + c = 0xedb88320 ^ (c >>> 1); + } else { + c = c >>> 1; + } + } + crcTable[i] = c; + } +}()); + var CrcCalculator = module.exports = function() { this._crc = -1; }; @@ -45,19 +61,3 @@ CrcCalculator.crc32 = function(buf) { } return crc ^ -1; }; - - - -var crcTable = []; - -for (var i = 0; i < 256; i++) { - var c = i; - for (var j = 0; j < 8; j++) { - if (c & 1) { - c = 0xedb88320 ^ (c >>> 1); - } else { - c = c >>> 1; - } - } - crcTable[i] = c; -} diff --git a/lib/filter-async.js b/lib/filter-async.js index 36d5438..1b713e1 100644 --- a/lib/filter-async.js +++ b/lib/filter-async.js @@ -32,7 +32,7 @@ var FilterAsync = module.exports = function(width, height, Bpp, depth, interlace var that = this; this._filter = new Filter(width, height, Bpp, depth, interlace, options, { read: this.read.bind(this), - complete: function(width, height) { + complete: function() { that.emit('complete', Buffer.concat(buffers), width, height) }, write: function(buffer) { diff --git a/lib/filter-sync.js b/lib/filter-sync.js index 4fe9880..c261a06 100644 --- a/lib/filter-sync.js +++ b/lib/filter-sync.js @@ -24,14 +24,14 @@ var SyncReader = require('./sync-reader'), Filter = require('./filter'); -exports.process = function(buffer, width, height, Bpp, depth, interlace, options) { +exports.process = function(inBuffer, width, height, Bpp, depth, interlace, options) { - var buffers = []; - var reader = new SyncReader(buffer); + var outBuffers = []; + var reader = new SyncReader(inBuffer); var filter = new Filter(width, height, Bpp, depth, interlace, options, { read: reader.read.bind(reader), - write: function(buffer) { - buffers.push(buffer); + write: function(bufferPart) { + outBuffers.push(bufferPart); }, complete: function(){} }); @@ -39,5 +39,5 @@ exports.process = function(buffer, width, height, Bpp, depth, interlace, options filter.start(); reader.process(); - return Buffer.concat(buffers); + return Buffer.concat(outBuffers); }; \ No newline at end of file diff --git a/lib/filter.js b/lib/filter.js index eb39c7a..0d45398 100755 --- a/lib/filter.js +++ b/lib/filter.js @@ -30,6 +30,23 @@ function getByteWidth(width, bpp, depth) { return byteWidth; } +function PaethPredictor(left, above, upLeft) { + + var p = left + above - upLeft, + pLeft = Math.abs(p - left), + pAbove = Math.abs(p - above), + pUpLeft = Math.abs(p - upLeft); + + if (pLeft <= pAbove && pLeft <= pUpLeft) { + return left; + } + if (pAbove <= pUpLeft) { + return above; + } + return upLeft; +} + + var Filter = module.exports = function(width, height, Bpp, depth, interlace, options, dependencies) { this._width = width; @@ -97,26 +114,26 @@ Filter.prototype._reverseFilterLine = function(rawData) { line[x] = rawByte; break; case 1: - var left = x > xBiggerThan ? line[x - xComparison] : 0; - line[x] = rawByte + left; + var f1_left = x > xBiggerThan ? line[x - xComparison] : 0; + line[x] = rawByte + f1_left; break; case 2: - var up = this._lastLine ? this._lastLine[x] : 0; - line[x] = rawByte + up; + var f2_up = this._lastLine ? this._lastLine[x] : 0; + line[x] = rawByte + f2_up; break; case 3: - var up = this._lastLine ? this._lastLine[x] : 0; - var left = x > xBiggerThan ? line[x - xComparison] : 0; - var add = Math.floor((left + up) / 2); - line[x] = rawByte + add; + var f3_up = this._lastLine ? this._lastLine[x] : 0; + var f3_left = x > xBiggerThan ? line[x - xComparison] : 0; + var f3_add = Math.floor((f3_left + f3_up) / 2); + line[x] = rawByte + f3_add; break; case 4: - var up = this._lastLine ? this._lastLine[x] : 0; - var left = x > xBiggerThan ? line[x - xComparison] : 0; - var upLeft = x > xBiggerThan && this._lastLine + var f4_up = this._lastLine ? this._lastLine[x] : 0; + var f4_left = x > xBiggerThan ? line[x - xComparison] : 0; + var f4_upLeft = x > xBiggerThan && this._lastLine ? this._lastLine[x - xComparison] : 0; - var add = PaethPredictor(left, up, upLeft); - line[x] = rawByte + add; + var f4_add = PaethPredictor(f4_left, f4_up, f4_upLeft); + line[x] = rawByte + f4_add; break; } @@ -268,17 +285,3 @@ Filter.prototype._filterPaeth = function(pxData, y, rawData) { } return sum; }; - - - -var PaethPredictor = function(left, above, upLeft) { - - var p = left + above - upLeft, - pLeft = Math.abs(p - left), - pAbove = Math.abs(p - above), - pUpLeft = Math.abs(p - upLeft); - - if (pLeft <= pAbove && pLeft <= pUpLeft) return left; - else if (pAbove <= pUpLeft) return above; - else return upLeft; -}; diff --git a/lib/interlace.js b/lib/interlace.js index bf867e7..65c2957 100644 --- a/lib/interlace.js +++ b/lib/interlace.js @@ -1,45 +1,4 @@ -exports.getImagePasses = function(width, height) { - var images = []; - var xLeftOver = width % 8; - var yLeftOver = height % 8; - var xRepeats = (width - xLeftOver) / 8; - var yRepeats = (width - 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, height) { - 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); - }; -}; +'use strict'; // Adam 7 // 0 1 2 3 4 5 6 7 @@ -82,4 +41,47 @@ var imagePasses = [ x: [0, 1, 2, 3, 4, 5, 6, 7], y: [1, 3, 5, 7] } -]; \ No newline at end of file +]; + +exports.getImagePasses = function(width, height) { + var images = []; + var xLeftOver = width % 8; + var yLeftOver = height % 8; + var xRepeats = (width - xLeftOver) / 8; + var yRepeats = (width - 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); + }; +}; \ No newline at end of file diff --git a/lib/packer.js b/lib/packer.js index f4313b1..4803db1 100755 --- a/lib/packer.js +++ b/lib/packer.js @@ -52,7 +52,7 @@ Packer.prototype.pack = function(data, width, height) { // filter pixel data //TODO {} var filter = new Filter(width, height, 4, 8, false, this._options, {}); - var data = filter.filter(data); + var filteredData = filter.filter(data); // compress it var deflate = zlib.createDeflate({ @@ -62,8 +62,8 @@ Packer.prototype.pack = function(data, width, height) { }); deflate.on('error', this.emit.bind(this, 'error')); - deflate.on('data', function(data) { - this.emit('data', this._packIDAT(data)); + deflate.on('data', function(compressedData) { + this.emit('data', this._packIDAT(compressedData)); }.bind(this)); deflate.on('end', function() { @@ -71,7 +71,7 @@ Packer.prototype.pack = function(data, width, height) { this.emit('end'); }.bind(this)); - deflate.end(data); + deflate.end(filteredData); }; Packer.prototype._packChunk = function(type, data) { diff --git a/lib/parser-async.js b/lib/parser-async.js index b5a9ef2..8ca1bc8 100644 --- a/lib/parser-async.js +++ b/lib/parser-async.js @@ -91,7 +91,7 @@ ParserAsync.prototype._createData = function(width, height, bpp, depth, interlac ); }; -ParserAsync.prototype._finished = function(data) { +ParserAsync.prototype._finished = function() { if (this.errord) { return; } diff --git a/lib/parser-base.js b/lib/parser-base.js deleted file mode 100644 index 51debf1..0000000 --- a/lib/parser-base.js +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright (c) 2012 Kuba Niegowski -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -'use strict'; - - -var util = require('util'), - zlib = require('zlib'), - CrcStream = require('./crc'), - ChunkStream = require('./chunkstream'), - constants = require('./constants'), - Filter = require('./filter'); - - -var Parser = module.exports = function(options, dependencies) { - - this._options = options; - options.checkCRC = options.checkCRC !== false; - - this._hasIHDR = false; - this._hasIEND = false; - - this._inflate = null; - this._filter = null; - this._crc = null; - - // 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.writable = true; - - //this.on('error', this._handleError.bind(this)); - //this._handleSignature(); - this.read = dependencies.read; - this.error = dependencies.error; -}; -util.inherits(Parser, ChunkStream); - - -Parser.prototype._handleError = function() { - - this.writable = false; - - this.destroy(); - - if (this._inflate) - this._inflate.destroy(); -}; - -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), - name = ''; - for (var i = 4; i < 8; i++) - name += String.fromCharCode(data[i]); - - // console.log('chunk ', name, length); - - // chunk flags - var ancillary = !!(data[4] & 0x20), // or critical - priv = !!(data[5] & 0x20), // or public - safeToCopy = !!(data[7] & 0x20); // or unsafe - - if (!this._hasIHDR && type != constants.TYPE_IHDR) { - this.error(new Error('Expected IHDR on beggining')); - return; - } - -// this._crc = new CrcStream(); -// this._crc.write(new Buffer(name)); - - if (this._chunks[type]) { - return this._chunks[type](length); - - } else if (!ancillary) { - this.error(new Error('Unsupported critical chunk type ' + name)); - return; - } else { - 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), - calcCrc = this._crc.crc32(); - - // check CRC - if (this._options.checkCRC && calcCrc != fileCrc) { - this.error(new Error('Crc error')); - return; - } - - if (this._hasIEND) { - this.destroySoon(); - - } else { - // todo allow _parseSignature to loop chinks? - 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), - height = data.readUInt32BE(4), - depth = data[8], - colorType = data[9], // bits: 1 palette, 2 color, 4 alpha - compr = data[10], - filter = data[11], - interlace = data[12]; - - // console.log(' width', width, 'height', height, - // 'depth', depth, 'colorType', colorType, - // 'compr', compr, 'filter', filter, 'interlace', interlace - // ); - - if (depth != 8) { - this.error(new Error('Unsupported bit depth ' + depth)); - return; - } - if (!(colorType in colorTypeToBppMap)) { - 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) { - this.error(new Error('Unsupported interlace method')); - return; - } - - this._colorType = colorType; - - this._data = new Buffer(width * height * 4); - this._filter = new Filter( - width, height, - colorTypeToBppMap[this._colorType], - this._data, - this._options - ); - - this._hasIHDR = true; - - this.metadata({ - width: width, - height: height, - palette: !!(colorType & constants.COLOR_PALETTE), - color: !!(colorType & constants.COLOR_COLOR), - alpha: !!(colorType & constants.COLOR_ALPHA), - data: this._data - }); - - 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.readUInt8(i * 3), - data.readUInt8(i * 3 + 1), - data.readUInt8(i * 3 + 2 ), - 0xff - ]); - } - - this._handleChunkEnd(); -}; - -Parser.prototype._handleTRNS = function(length) { - this.read(length, this._parseTRNS.bind(this)); -}; -Parser.prototype._parseTRNS = function(data) { - - this._crc.write(data); - - // palette - if (this._colorType == 3) { - 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 < this._palette.length; i++) { - this._palette[i][3] = i < data.length ? data.readUInt8(i) : 0xff; - } - } - - // for colorType 0 (grayscale) and 2 (rgb) - // there might be one gray/color defined as transparent - - 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) / 100000); - - this._handleChunkEnd(); -}; - -Parser.prototype._handleIDAT = function(length) { - this.read(-length, this._parseIDAT.bind(this, length)); -}; -Parser.prototype._parseIDAT = function(length, data) { - - this._crc.write(data); - - if (this._colorType == 3 && this._palette.length == 0) - throw new Error('Expected palette not found'); - - if (!this._inflate) { - this._inflate = zlib.createInflate(); - - this._inflate.on('error', this.emit.bind(this, 'error')); - this._filter.on('complete', this._reverseFiltered.bind(this)); - - this._inflate.pipe(this._filter); - } - - this._inflate.write(data); - length -= data.length; - - if (length > 0) - this._handleIDAT(length); - else - this._handleChunkEnd(); -}; - - -Parser.prototype._handleIEND = function(length) { - this.read(length, this._parseIEND.bind(this)); -}; -Parser.prototype._parseIEND = function(data) { - - this._crc.write(data); - - // no more data to inflate - this._inflate.end(); - - this._hasIEND = true; - this._handleChunkEnd(); -}; - - -var colorTypeToBppMap = { - 0: 1, - 2: 3, - 3: 1, - 4: 2, - 6: 4 -}; - -Parser.prototype._reverseFiltered = function(data, width, height) { - - if (this._colorType == 3) { // paletted - - // use values from palette - var pxLineLength = width << 2; - - for (var y = 0; y < height; y++) { - var pxRowPos = y * pxLineLength; - - for (var x = 0; x < width; x++) { - var pxPos = pxRowPos + (x << 2), - color = this._palette[data[pxPos]]; - - for (var i = 0; i < 4; i++) - data[pxPos + i] = color[i]; - } - } - } - - this.emit('parsed', data); -}; diff --git a/lib/parser.js b/lib/parser.js index c8b5593..b7b9e0f 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -97,9 +97,9 @@ Parser.prototype._parseChunkBegin = function(data) { //console.log('chunk ', name, length); // chunk flags - var ancillary = !!(data[4] & 0x20), // or critical - priv = !!(data[5] & 0x20), // or public - safeToCopy = !!(data[7] & 0x20); // or unsafe + var ancillary = !!(data[4] & 0x20); // or critical +// priv = !!(data[5] & 0x20), // or public +// safeToCopy = !!(data[7] & 0x20); // or unsafe if (!this._hasIHDR && type != constants.TYPE_IHDR) { this.error(new Error('Expected IHDR on beggining')); @@ -111,16 +111,17 @@ Parser.prototype._parseChunkBegin = function(data) { if (this._chunks[type]) { return this._chunks[type](length); + } - } else if (!ancillary) { + if (!ancillary) { this.error(new Error('Unsupported critical chunk type ' + name)); return; - } else { - this.read(length + 4, this._skipChunk.bind(this)); } + + this.read(length + 4, this._skipChunk.bind(this)); }; -Parser.prototype._skipChunk = function(data) { +Parser.prototype._skipChunk = function(/*data*/) { this.read(8, this._parseChunkBegin.bind(this)); }; @@ -218,9 +219,9 @@ Parser.prototype._parsePLTE = function(data) { for (var i = 0; i < entries; i++) { this._palette.push([ - data.readUInt8(i * 3), - data.readUInt8(i * 3 + 1), - data.readUInt8(i * 3 + 2 ), + data[i * 3], + data[i * 3 + 1], + data[i * 3 + 2 ], 0xff ]); } @@ -246,7 +247,7 @@ Parser.prototype._parseTRNS = function(data) { return; } for (var i = 0; i < this._palette.length; i++) { - this._palette[i][3] = i < data.length ? data.readUInt8(i) : 0xff; + this._palette[i][3] = i < data.length ? data[i] : 0xff; } } @@ -311,35 +312,34 @@ Parser.prototype.reverseFiltered = function(indata, depth, width, height) { var outdata = indata; // only different for 16 bits + var pxLineLength = width << 2; + var x, y, i, pxPos, pxRowPos; + if (this._colorType == 3) { // paletted - //console.log("paletted"); + //TODO abstract loop? // use values from palette - var pxLineLength = width << 2; + for (y = 0; y < height; y++) { + pxRowPos = y * pxLineLength; - for (var y = 0; y < height; y++) { - var pxRowPos = y * pxLineLength; - - for (var x = 0; x < width; x++) { - var pxPos = pxRowPos + (x << 2), - color = this._palette[indata[pxPos]]; + for (x = 0; x < width; x++) { + pxPos = pxRowPos + (x << 2); + var color = this._palette[indata[pxPos]]; if (!color) { throw new Error("index " + indata[pxPos] + " not in palette"); } - for (var i = 0; i < 4; i++) + for (i = 0; i < 4; i++) indata[pxPos + i] = color[i]; } } } else { - var pxLineLength = width << 2; - if (this._transColor) { - for (var y = 0; y < height; y++) { - var pxRowPos = y * pxLineLength; + for (y = 0; y < height; y++) { + pxRowPos = y * pxLineLength; - for (var x = 0; x < width; x++) { - var pxPos = pxRowPos + (x << 2); + for (x = 0; x < width; x++) { + pxPos = pxRowPos + (x << 2); var makeTrans = false; //console.log(pxPos); if (this._transColor.length === 1) { @@ -350,7 +350,7 @@ Parser.prototype.reverseFiltered = function(indata, depth, width, height) { makeTrans = true; } if (makeTrans) { - for (var i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { indata[pxPos + i] = 0; } } @@ -365,12 +365,12 @@ Parser.prototype.reverseFiltered = function(indata, depth, width, height) { var maxOutSample = 255; var maxInSample = Math.pow(2, depth) - 1; - for (var y = 0; y < height; y++) { - var pxRowPos = y * pxLineLength; + for (y = 0; y < height; y++) { + pxRowPos = y * pxLineLength; - for (var x = 0; x < width; x++) { - var pxPos = pxRowPos + (x << 2); - for (var i = 0; i < 4; i++) + for (x = 0; x < width; x++) { + pxPos = pxRowPos + (x << 2); + for (i = 0; i < 4; i++) outdata[pxPos + i] = Math.floor((indata[pxPos + i] * maxOutSample) / maxInSample + 0.5); } } diff --git a/lib/png.js b/lib/png.js index 0fe8558..bb57a5b 100755 --- a/lib/png.js +++ b/lib/png.js @@ -39,7 +39,9 @@ var PNG = exports.PNG = function(options) { 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)}; + if(options.fill && this.data){ + this.data.fill(0); + } this.gamma = 0; this.readable = this.writable = true; @@ -81,10 +83,10 @@ PNG.prototype.parse = function(data, callback) { if (callback) { var onParsed = null, onError = null; - this.once('parsed', onParsed = function(data) { + this.once('parsed', onParsed = function(parsedData) { this.removeListener('error', onError); - this.data = data; + this.data = parsedData; callback(null, this); }.bind(this));