Better scanline filter selection

This commit is contained in:
Kuba Niegowski 2012-08-21 09:50:38 +02:00
parent 207c02d323
commit eedc329b9a
5 changed files with 29 additions and 23 deletions

View file

@ -15,10 +15,8 @@ var fs = require('fs'),
PNG = require('pngjs').PNG; PNG = require('pngjs').PNG;
var png = new PNG({ var png = new PNG({
filterType: 4 filterType: 4
}), });
src = fs.createReadStream(process.argv[2]),
dst = fs.createWriteStream(process.argv[3]);
png.on('parsed', function() { png.on('parsed', function() {
@ -36,21 +34,27 @@ png.on('parsed', function() {
} }
} }
png.pipe(fs.createWriteStream('out.png'));
png.pack(); png.pack();
}); });
src.pipe(png).pipe(dst); fs.createReadStream('in.png').pipe(png);
``` ```
For more examples see `examples` folder. For more examples see `examples` folder.
Documentation Documentation
================ ================
Currently only true color mode with 8-bit color depth (per color) with alpha As input any color type is accepted (grayscale, rgb, palette, grayscale with alpha, rgb with alpha) but 8 bit per sample (channel) is the only supported bit depth. Interlaced mode is not supported.
is supported. PNG cannot parse and create images with palette of colors.
Interlaced mode is not supported either.
## PNG Supported ancillary chunks
------------------
- `gAMA` - gamma,
- `tRNS` - transparency (but only for paletted image)
## Class: PNG
`PNG` is readable and writeable `Stream`. `PNG` is readable and writeable `Stream`.
### Options ### Options
@ -80,9 +84,15 @@ two arguments `(err, data)`.
### Property: data ### Property: data
Buffer of image pixel data. Every pixel consists 4 bytes: R, G, B, A (opacity). Buffer of image pixel data. Every pixel consists 4 bytes: R, G, B, A (opacity).
### Property: gamma
Changelog Changelog
============ ============
### 0.2.0-alpha - 21 Aug 2012
- Input added palette, grayscale, no alpha support
- Better scanline filter selection
### 0.1.0-alpha - 19 Aug 2012 ### 0.1.0-alpha - 19 Aug 2012
- First version - First version

View file

@ -22,8 +22,7 @@ fs.readdir(__dirname + '/img/', function(err, files) {
for (var i = 0; i < 3; i++) { for (var i = 0; i < 3; i++) {
var sample = this.data[idx + i] / 255; var sample = this.data[idx + i] / 255;
sample = Math.pow(sample, 1 / this.gamma); sample = Math.pow(sample, 1 / 2.2 / this.gamma);
sample = Math.pow(sample, 1 / 2.2);
this.data[idx + i] = Math.round(sample * 255); this.data[idx + i] = Math.round(sample * 255);
} }
} }

View file

@ -17,13 +17,10 @@ png.on('parsed', function() {
for (var x = 0; x < png.width; x++) { for (var x = 0; x < png.width; x++) {
var idx = (png.width * y + x) << 2; var idx = (png.width * y + x) << 2;
// invert color if (Math.abs(png.data[idx] - png.data[idx+1]) <= 1
png.data[idx] = 255 - png.data[idx]; && Math.abs(png.data[idx+1] - png.data[idx+2]) <= 1)
png.data[idx+1] = 255 - png.data[idx+1]; png.data[idx] = png.data[idx+1] = png.data[idx+2];
png.data[idx+2] = 255 - png.data[idx+2];
// and reduce opacity
png.data[idx+3] = png.data[idx+3] >> 1;
} }
} }

View file

@ -200,7 +200,7 @@ Filter.prototype._filterNone = function(pxData, y, width, height, rawData) {
if (!rawData) { if (!rawData) {
for (var x = 0; x < pxRowLength; x++) for (var x = 0; x < pxRowLength; x++)
sum += pxData[y * pxRowLength + x]; sum += Math.abs(pxData[y * pxRowLength + x]);
} else { } else {
rawData[y * rawRowLength] = 0; rawData[y * rawRowLength] = 0;
@ -224,7 +224,7 @@ Filter.prototype._filterSub = function(pxData, y, width, height, rawData) {
var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0, var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0,
val = pxData[y * pxRowLength + x] - left; val = pxData[y * pxRowLength + x] - left;
if (!rawData) sum += val; if (!rawData) sum += Math.abs(val);
else rawData[y * rawRowLength + 1 + x] = val; else rawData[y * rawRowLength + 1 + x] = val;
} }
return sum; return sum;
@ -244,7 +244,7 @@ Filter.prototype._filterUp = function(pxData, y, width, height, rawData) {
var up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0, var up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
val = pxData[y * pxRowLength + x] - up; val = pxData[y * pxRowLength + x] - up;
if (!rawData) sum += val; if (!rawData) sum += Math.abs(val);
else rawData[y * rawRowLength + 1 + x] = val; else rawData[y * rawRowLength + 1 + x] = val;
} }
return sum; return sum;
@ -265,7 +265,7 @@ Filter.prototype._filterAvg = function(pxData, y, width, height, rawData) {
up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0, up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
val = pxData[y * pxRowLength + x] - ((left + up) >> 1); val = pxData[y * pxRowLength + x] - ((left + up) >> 1);
if (!rawData) sum += val; if (!rawData) sum += Math.abs(val);
else rawData[y * rawRowLength + 1 + x] = val; else rawData[y * rawRowLength + 1 + x] = val;
} }
return sum; return sum;
@ -287,7 +287,7 @@ Filter.prototype._filterPaeth = function(pxData, y, width, height, rawData) {
upLeft = x >= 4 && y > 0 ? pxData[(y - 1) * pxRowLength + x - 4] : 0, upLeft = x >= 4 && y > 0 ? pxData[(y - 1) * pxRowLength + x - 4] : 0,
val = pxData[y * pxRowLength + x] - PaethPredictor(left, up, upLeft); val = pxData[y * pxRowLength + x] - PaethPredictor(left, up, upLeft);
if (!rawData) sum += val; if (!rawData) sum += Math.abs(val);
else rawData[y * rawRowLength + 1 + x] = val; else rawData[y * rawRowLength + 1 + x] = val;
} }
return sum; return sum;

View file

@ -1,6 +1,6 @@
{ {
"name": "pngjs", "name": "pngjs",
"version": "0.1.0-alpha", "version": "0.2.0-alpha",
"description": "Simple PNG encoder/decoder", "description": "Simple PNG encoder/decoder",
"author": "Kuba Niegowski", "author": "Kuba Niegowski",
"contributors": [], "contributors": [],