poc to support colortype 2

This commit is contained in:
michuNEEO 2015-09-13 14:31:22 +02:00
parent 75d2927e75
commit 83d60edeaf
7 changed files with 51 additions and 47 deletions

0
lib/chunkstream.js Executable file → Normal file
View file

0
lib/constants.js Executable file → Normal file
View file

0
lib/crc.js Executable file → Normal file
View file

View file

@ -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;
};
};

19
lib/packer.js Executable file → Normal file
View file

@ -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

View file

@ -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;
};

2
lib/png.js Executable file → Normal file
View file

@ -160,4 +160,4 @@ PNG.adjustGamma = function(src) {
PNG.prototype.adjustGamma = function() {
PNG.adjustGamma(this);
};
};