mirror of
https://github.com/danbulant/pngjs
synced 2026-06-19 22:41:58 +00:00
Pull out format normaliser. Fix #18
This commit is contained in:
parent
8cf14b9ca2
commit
71a371d6cd
7 changed files with 131 additions and 93 deletions
|
|
@ -129,7 +129,7 @@
|
|||
"generator-star-spacing": 0,
|
||||
"guard-for-in": 1,
|
||||
"handle-callback-err": 2,
|
||||
"id-length": [2, {"min": 3, "max": 20, "exceptions":["x", "y", "i", "j", "ex", "up"]}],
|
||||
"id-length": [2, {"min": 3, "max": 25, "exceptions":["x", "y", "i", "j", "ex", "up"]}],
|
||||
"indent": [1, 2, {"SwitchCase": 1}],
|
||||
"init-declarations": 0,
|
||||
"key-spacing": [1, { "beforeColon": false, "afterColon": true }],
|
||||
|
|
|
|||
89
lib/format-normaliser.js
Normal file
89
lib/format-normaliser.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
'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;
|
||||
};
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
|
||||
var util = require('util');
|
||||
var zlib = require('zlib');
|
||||
var ChunkStream = require('./chunkstream');
|
||||
var FilterAsync = require('./filter-async');
|
||||
var Parser = require('./parser');
|
||||
var bitmapper = require('./bitmapper');
|
||||
|
||||
var formatNormaliser = require('./format-normaliser');
|
||||
|
||||
var ParserAsync = module.exports = function(options) {
|
||||
ChunkStream.call(this);
|
||||
|
|
@ -98,7 +97,14 @@ ParserAsync.prototype._complete = function(filteredData, width, height) {
|
|||
this._depth,
|
||||
this._interlace);
|
||||
|
||||
bitmapData = this._parser.reverseFiltered(bitmapData, this._depth, width, height);
|
||||
// todo not bitmap data any more
|
||||
bitmapData = formatNormaliser(bitmapData, {
|
||||
depth: this._depth, // TODO always store in this format
|
||||
width: width,
|
||||
height: height,
|
||||
colorType: this._parser._colorType,
|
||||
palette: this._parser._palette,
|
||||
transColor: this._parser._transColor });
|
||||
}
|
||||
catch (ex) {
|
||||
this._handleError(ex);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ var SyncReader = require('./sync-reader');
|
|||
var FilterSync = require('./filter-sync');
|
||||
var Parser = require('./parser');
|
||||
var bitmapper = require('./bitmapper');
|
||||
var formatNormaliser = require('./format-normaliser');
|
||||
|
||||
|
||||
var ParserSync = module.exports = function(buffer, options) {
|
||||
|
|
@ -33,6 +34,10 @@ var ParserSync = module.exports = function(buffer, options) {
|
|||
|
||||
var data = zlib.inflateSync(inflateData);
|
||||
|
||||
if (!data || !data.length) {
|
||||
throw new Error('bad png - invalid inflate data response');
|
||||
}
|
||||
|
||||
data = FilterSync.process(
|
||||
data,
|
||||
this._width, this._height,
|
||||
|
|
@ -41,13 +46,19 @@ var ParserSync = module.exports = function(buffer, options) {
|
|||
this._interlace,
|
||||
this._options
|
||||
);
|
||||
|
||||
// todo do not store _data
|
||||
this._data = bitmapper.dataToBitMap(data, this._width, this._height,
|
||||
this._bpp,
|
||||
this._depth,
|
||||
this._interlace);
|
||||
// todo yuck
|
||||
this.data = this._parser.reverseFiltered(this._data, this._depth, this._width, this._height);
|
||||
|
||||
this.data = formatNormaliser(this._data, {
|
||||
depth: this._depth, // TODO always store in this format
|
||||
width: this._width,
|
||||
height: this._height,
|
||||
colorType: this._parser._colorType,
|
||||
palette: this._parser._palette,
|
||||
transColor: this._parser._transColor });
|
||||
};
|
||||
|
||||
ParserSync.prototype._handleError = function(err) {
|
||||
|
|
@ -73,5 +84,5 @@ ParserSync.prototype._createData = function(width, height, bpp, depth, interlace
|
|||
this._height = height;
|
||||
this._depth = depth;
|
||||
this._interlace = interlace;
|
||||
return this._data;
|
||||
return this._data; // todo do not return
|
||||
};
|
||||
|
|
|
|||
|
|
@ -276,7 +276,6 @@ Parser.prototype._parseIDAT = function(length, data) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
Parser.prototype._handleIEND = function(length) {
|
||||
this.read(length, this._parseIEND.bind(this));
|
||||
};
|
||||
|
|
@ -289,79 +288,3 @@ Parser.prototype._parseIEND = function(data) {
|
|||
|
||||
this.finished();
|
||||
};
|
||||
|
||||
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
|
||||
//TODO abstract loop?
|
||||
// use values from palette
|
||||
for (y = 0; y < height; y++) {
|
||||
pxRowPos = y * pxLineLength;
|
||||
|
||||
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 (i = 0; i < 4; i++) {
|
||||
indata[pxPos + i] = color[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this._transColor) {
|
||||
for (y = 0; y < height; y++) {
|
||||
pxRowPos = y * pxLineLength;
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
pxPos = pxRowPos + (x << 2);
|
||||
var makeTrans = false;
|
||||
//console.log(pxPos);
|
||||
if (this._transColor.length === 1) {
|
||||
if (this._transColor[0] === indata[pxPos]) {
|
||||
makeTrans = true;
|
||||
}
|
||||
}
|
||||
else if (this._transColor[0] === indata[pxPos] && this._transColor[1] === indata[pxPos + 1] && this._transColor[2] === indata[pxPos + 2]) {
|
||||
makeTrans = true;
|
||||
}
|
||||
if (makeTrans) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
indata[pxPos + i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (depth !== 8) {
|
||||
if (depth === 16) {
|
||||
outdata = new Buffer(width * height * 4);
|
||||
}
|
||||
//console.log("adjusting");
|
||||
var maxOutSample = 255;
|
||||
var maxInSample = Math.pow(2, depth) - 1;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
pxRowPos = y * pxLineLength;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return outdata;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@ PNG.sync = PNGSync;
|
|||
|
||||
PNG.prototype.pack = function() {
|
||||
|
||||
if (!this.data || !this.data.length) {
|
||||
this.emit('error', 'No data provided');
|
||||
return this;
|
||||
}
|
||||
|
||||
process.nextTick(function() {
|
||||
this._packer.pack(this.data, this.width, this.height);
|
||||
}.bind(this));
|
||||
|
|
|
|||
|
|
@ -15,9 +15,15 @@ module.exports = function(done) {
|
|||
|
||||
var completed = 0;
|
||||
var expected = files.length * 2;
|
||||
function complete() {
|
||||
var anyFailures = false;
|
||||
function complete(isSuccessful) {
|
||||
completed++;
|
||||
anyFailures = anyFailures || !isSuccessful;
|
||||
if (expected === completed) {
|
||||
if (anyFailures) {
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
|
@ -41,13 +47,13 @@ module.exports = function(done) {
|
|||
console.log(e.stack);
|
||||
}
|
||||
syncError = true;
|
||||
complete();
|
||||
complete(expectedError);
|
||||
}
|
||||
|
||||
if (!syncError) {
|
||||
if (expectedError) {
|
||||
console.log("Sync: Error expected, parsed fine ..", file);
|
||||
complete();
|
||||
complete(false);
|
||||
} else {
|
||||
|
||||
var outpng = new PNG();
|
||||
|
|
@ -58,7 +64,7 @@ module.exports = function(done) {
|
|||
outpng.pack()
|
||||
.pipe(fs.createWriteStream(__dirname + '/outsync/' + file)
|
||||
.on("finish", function () {
|
||||
complete();
|
||||
complete(true);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +75,7 @@ module.exports = function(done) {
|
|||
if (!expectedError) {
|
||||
console.log("Async: Unexpected error parsing.." + file, err);
|
||||
}
|
||||
complete();
|
||||
complete(expectedError);
|
||||
})
|
||||
.on('parsed', function () {
|
||||
|
||||
|
|
@ -82,11 +88,9 @@ module.exports = function(done) {
|
|||
.pipe(
|
||||
fs.createWriteStream(__dirname + '/out/' + file)
|
||||
.on("finish", function() {
|
||||
complete();
|
||||
complete(true);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue