From 83d60edeafe02757ec2f13ef0ea285116af162b0 Mon Sep 17 00:00:00 2001 From: michuNEEO Date: Sun, 13 Sep 2015 14:31:22 +0200 Subject: [PATCH] poc to support colortype 2 --- lib/chunkstream.js | 0 lib/constants.js | 0 lib/crc.js | 0 lib/filter-pack.js | 45 ++++++++++++++++++++---------------------- lib/packer.js | 19 ++++++++++++------ lib/paeth-predictor.js | 32 +++++++++++++++--------------- lib/png.js | 2 +- 7 files changed, 51 insertions(+), 47 deletions(-) mode change 100755 => 100644 lib/chunkstream.js mode change 100755 => 100644 lib/constants.js mode change 100755 => 100644 lib/crc.js mode change 100755 => 100644 lib/packer.js mode change 100755 => 100644 lib/png.js diff --git a/lib/chunkstream.js b/lib/chunkstream.js old mode 100755 new mode 100644 diff --git a/lib/constants.js b/lib/constants.js old mode 100755 new mode 100644 diff --git a/lib/crc.js b/lib/crc.js old mode 100755 new mode 100644 diff --git a/lib/filter-pack.js b/lib/filter-pack.js index 8899ceb..dd2f368 100644 --- a/lib/filter-pack.js +++ b/lib/filter-pack.js @@ -3,7 +3,6 @@ var paethPredictor = require('./paeth-predictor'); function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) { - pxData.copy(rawData, rawPos, pxPos, pxPos + byteWidth); } @@ -18,23 +17,23 @@ function filterSumNone(pxData, pxPos, byteWidth) { return sum; } -function filterSub(pxData, pxPos, byteWidth, rawData, rawPos) { +function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, BPP) { for (var x = 0; x < byteWidth; x++) { - var left = x >= 4 ? pxData[pxPos + x - 4] : 0; + var left = x >= BPP ? pxData[pxPos + x - BPP] : 0; var val = pxData[pxPos + x] - left; rawData[rawPos + x] = val; } } -function filterSumSub(pxData, pxPos, byteWidth) { +function filterSumSub(pxData, pxPos, byteWidth, BPP) { var sum = 0; for (var x = 0; x < byteWidth; x++) { - var left = x >= 4 ? pxData[pxPos + x - 4] : 0; + var left = x >= BPP ? pxData[pxPos + x - BPP] : 0; var val = pxData[pxPos + x] - left; sum += Math.abs(val); @@ -43,7 +42,7 @@ function filterSumSub(pxData, pxPos, byteWidth) { return sum; } -function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) { +function filterUp(pxData, pxPos, byteWidth, rawData, rawPos, BPP) { for (var x = 0; x < byteWidth; x++) { @@ -54,7 +53,7 @@ function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) { } } -function filterSumUp(pxData, pxPos, byteWidth) { +function filterSumUp(pxData, pxPos, byteWidth, BPP) { var sum = 0; var length = pxPos + byteWidth; @@ -69,11 +68,11 @@ function filterSumUp(pxData, pxPos, byteWidth) { return sum; } -function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos) { +function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, BPP) { for (var x = 0; x < byteWidth; x++) { - var left = x >= 4 ? pxData[pxPos + x - 4] : 0; + 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); @@ -81,12 +80,12 @@ function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos) { } } -function filterSumAvg(pxData, pxPos, byteWidth) { +function filterSumAvg(pxData, pxPos, byteWidth, BPP) { var sum = 0; for (var x = 0; x < byteWidth; x++) { - var left = x >= 4 ? pxData[pxPos + x - 4] : 0; + 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); @@ -96,27 +95,26 @@ function filterSumAvg(pxData, pxPos, byteWidth) { return sum; } -function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos) { +function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, BPP) { for (var x = 0; x < byteWidth; x++) { - var left = x >= 4 ? pxData[pxPos + x - 4] : 0; + var left = x >= BPP ? pxData[pxPos + x - BPP] : 0; var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; - var upleft = pxPos > 0 && x >= 4 ? pxData[pxPos + x - (byteWidth + 4)] : 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) { - +function filterSumPaeth(pxData, pxPos, byteWidth, BPP) { var sum = 0; for (var x = 0; x < byteWidth; x++) { - var left = x >= 4 ? pxData[pxPos + x - 4] : 0; + var left = x >= BPP ? pxData[pxPos + x - BPP] : 0; var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; - var upleft = pxPos > 0 && x >= 4 ? pxData[pxPos + x - (byteWidth + 4)] : 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); @@ -141,7 +139,7 @@ var filterSums = { 4: filterSumPaeth }; -module.exports = function(pxData, width, height, options) { +module.exports = function(pxData, width, height, options, bpp) { var filterTypes; if (!('filterType' in options) || options.filterType === -1) { @@ -154,7 +152,7 @@ module.exports = function(pxData, width, height, options) { throw new Error('unrecognised filter types'); } - var byteWidth = width << 2; + var byteWidth = width * bpp; var rawPos = 0; var pxPos = 0; var rawData = new Buffer((byteWidth + 1) * height); @@ -167,8 +165,7 @@ module.exports = function(pxData, width, height, options) { var min = Infinity; for (var i = 0; i < filterTypes.length; i++) { - var sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth); - + var sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp); if (sum < min) { sel = filterTypes[i]; min = sum; @@ -178,9 +175,9 @@ module.exports = function(pxData, width, height, options) { rawData[rawPos] = sel; rawPos++; - filters[sel](pxData, pxPos, byteWidth, rawData, rawPos); + filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp); rawPos += byteWidth; pxPos += byteWidth; } return rawData; -}; \ No newline at end of file +}; diff --git a/lib/packer.js b/lib/packer.js old mode 100755 new mode 100644 index ac2ccc6..abc0091 --- a/lib/packer.js +++ b/lib/packer.js @@ -8,6 +8,8 @@ var filter = require('./filter-pack'); var CrcStream = require('./crc'); var constants = require('./constants'); +var COLOR_TYPE_TRUECOLOR = 2; +var COLOR_TYPE_TRUECOLOR_WITH_ALPHA = 6; var Packer = module.exports = function(options) { Stream.call(this); @@ -18,6 +20,8 @@ var Packer = module.exports = function(options) { options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9; options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3; options.deflateFactory = options.deflateFactory || zlib.createDeflate; + options.bitDepth = options.bitDepth || 8; + options.colorType = (typeof options.colorType=="number") ? options.colorType : COLOR_TYPE_TRUECOLOR_WITH_ALPHA; this.readable = true; }; @@ -25,17 +29,20 @@ util.inherits(Packer, Stream); Packer.prototype.pack = function(data, width, height, gamma) { - // Signature this.emit('data', new Buffer(constants.PNG_SIGNATURE)); - this.emit('data', this._packIHDR(width, height)); + this.emit('data', this._packIHDR(width, height, this._options.bitDepth, this._options.colorType)); if (gamma) { this.emit('data', this._packGAMA(gamma)); } // filter pixel data - var filteredData = filter(data, width, height, this._options); + var bpp = 4; + if (this._options.colorType === COLOR_TYPE_TRUECOLOR) { + bpp = 3; + } + var filteredData = filter(data, width, height, this._options, bpp); // compress it var deflate = this._options.deflateFactory({ @@ -79,13 +86,13 @@ Packer.prototype._packGAMA = function(gamma) { return this._packChunk(constants.TYPE_gAMA, buf); }; -Packer.prototype._packIHDR = function(width, height) { +Packer.prototype._packIHDR = function(width, height, bitDepth, colorType) { var buf = new Buffer(13); buf.writeUInt32BE(width, 0); buf.writeUInt32BE(height, 4); - buf[8] = 8; - buf[9] = 6; // colorType + buf[8] = bitDepth; // Bit depth + buf[9] = colorType; // colorType buf[10] = 0; // compression buf[11] = 0; // filter buf[12] = 0; // interlace diff --git a/lib/paeth-predictor.js b/lib/paeth-predictor.js index 97c3adf..74d254e 100644 --- a/lib/paeth-predictor.js +++ b/lib/paeth-predictor.js @@ -1,17 +1,17 @@ -'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; +'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; }; \ No newline at end of file diff --git a/lib/png.js b/lib/png.js old mode 100755 new mode 100644 index 1c8627f..c60778e --- a/lib/png.js +++ b/lib/png.js @@ -160,4 +160,4 @@ PNG.adjustGamma = function(src) { PNG.prototype.adjustGamma = function() { PNG.adjustGamma(this); -}; \ No newline at end of file +};