mirror of
https://github.com/danbulant/pngjs
synced 2026-06-13 19:42:34 +00:00
Support for synchronous reading of PNG's
This commit is contained in:
parent
b5328d3574
commit
807ffcd66f
15 changed files with 787 additions and 444 deletions
24
lib/crc.js
24
lib/crc.js
|
|
@ -20,21 +20,11 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var util = require('util'),
|
||||
Stream = require('stream');
|
||||
|
||||
|
||||
var CrcStream = module.exports = function() {
|
||||
Stream.call(this);
|
||||
|
||||
var CrcCalculator = module.exports = function() {
|
||||
this._crc = -1;
|
||||
|
||||
this.writable = true;
|
||||
};
|
||||
util.inherits(CrcStream, Stream);
|
||||
|
||||
|
||||
CrcStream.prototype.write = function(data) {
|
||||
CrcCalculator.prototype.write = function(data) {
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
|
||||
|
|
@ -42,18 +32,12 @@ CrcStream.prototype.write = function(data) {
|
|||
return true;
|
||||
};
|
||||
|
||||
CrcStream.prototype.end = function(data) {
|
||||
if (data) this.write(data);
|
||||
|
||||
this.emit('crc', this.crc32());
|
||||
};
|
||||
|
||||
CrcStream.prototype.crc32 = function() {
|
||||
CrcCalculator.prototype.crc32 = function() {
|
||||
return this._crc ^ -1;
|
||||
};
|
||||
|
||||
|
||||
CrcStream.crc32 = function(buf) {
|
||||
CrcCalculator.crc32 = function(buf) {
|
||||
|
||||
var crc = -1;
|
||||
for (var i = 0; i < buf.length; i++) {
|
||||
|
|
|
|||
38
lib/filter-async.js
Normal file
38
lib/filter-async.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// 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'),
|
||||
ChunkStream = require('./chunkstream'),
|
||||
Filter = require('./filter');
|
||||
|
||||
|
||||
var FilterAsync = module.exports = function(width, height, Bpp, data, options) {
|
||||
ChunkStream.call(this);
|
||||
|
||||
this._filter = new Filter(width, height, Bpp, data, options, {
|
||||
read: this.read.bind(this),
|
||||
complete: this.emit.bind(this, 'complete')
|
||||
});
|
||||
|
||||
this._filter.start();
|
||||
};
|
||||
util.inherits(FilterAsync, ChunkStream);
|
||||
37
lib/filter-sync.js
Normal file
37
lib/filter-sync.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// 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 SyncReader = require('./sync-reader'),
|
||||
Filter = require('./filter');
|
||||
|
||||
|
||||
exports.process = function(buffer, width, height, Bpp, outData, options) {
|
||||
|
||||
var reader = new SyncReader(buffer);
|
||||
var filter = new Filter(width, height, Bpp, outData, options, {
|
||||
read: reader.read.bind(reader),
|
||||
complete: function(){}
|
||||
});
|
||||
|
||||
filter.start();
|
||||
reader.process();
|
||||
};
|
||||
|
|
@ -21,12 +21,10 @@
|
|||
'use strict';
|
||||
|
||||
var util = require('util'),
|
||||
zlib = require('zlib'),
|
||||
ChunkStream = require('./chunkstream');
|
||||
|
||||
|
||||
var Filter = module.exports = function(width, height, Bpp, data, options) {
|
||||
ChunkStream.call(this);
|
||||
var Filter = module.exports = function(width, height, Bpp, data, options, dependencies) {
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
|
@ -50,10 +48,13 @@ var Filter = module.exports = function(width, height, Bpp, data, options) {
|
|||
4: this._filterPaeth.bind(this)
|
||||
};
|
||||
|
||||
this.read(this._width * Bpp + 1, this._reverseFilterLine.bind(this));
|
||||
this.read = dependencies.read;
|
||||
this.complete = dependencies.complete;
|
||||
};
|
||||
util.inherits(Filter, ChunkStream);
|
||||
|
||||
Filter.prototype.start = function() {
|
||||
this.read(this._width * this._Bpp + 1, this._reverseFilterLine.bind(this));
|
||||
};
|
||||
|
||||
var pixelBppMap = {
|
||||
1: { // L
|
||||
|
|
@ -167,7 +168,7 @@ Filter.prototype._reverseFilterLine = function(rawData) {
|
|||
if (this._line < this._height)
|
||||
this.read(this._width * this._Bpp + 1, this._reverseFilterLine.bind(this));
|
||||
else
|
||||
this.emit('complete', this._data, this._width, this._height);
|
||||
this.complete(this._data, this._width, this._height);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ Packer.prototype.pack = function(data, width, height) {
|
|||
this.emit('data', this._packIHDR(width, height));
|
||||
|
||||
// filter pixel data
|
||||
var filter = new Filter(width, height, 4, data, this._options);
|
||||
var filter = new Filter(width, height, 4, data, this._options, {});
|
||||
var data = filter.filter();
|
||||
|
||||
// compress it
|
||||
|
|
|
|||
97
lib/parser-async.js
Normal file
97
lib/parser-async.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// 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'),
|
||||
ChunkStream = require('./chunkstream'),
|
||||
FilterAsync = require('./filter-async'),
|
||||
Parser = require('./parser');
|
||||
|
||||
|
||||
var ParserAsync = module.exports = function(options) {
|
||||
ChunkStream.call(this);
|
||||
|
||||
this._parser = new Parser(options, {
|
||||
read: this.read.bind(this),
|
||||
error: this.emit.bind(this, "error"),
|
||||
metadata: this.emit.bind(this, "metadata"),
|
||||
gamma: this.emit.bind(this, "gamma"),
|
||||
finished: this._finished.bind(this),
|
||||
inflateData: this._inflateData.bind(this),
|
||||
createData: this._createData.bind(this)
|
||||
});
|
||||
this._options = options;
|
||||
this.writable = true;
|
||||
|
||||
this.on('error', this._handleError.bind(this));
|
||||
this._parser.start();
|
||||
};
|
||||
util.inherits(ParserAsync, ChunkStream);
|
||||
|
||||
|
||||
ParserAsync.prototype._handleError = function() {
|
||||
|
||||
this.writable = false;
|
||||
|
||||
this.destroy();
|
||||
|
||||
if (this._inflate && this._inflate.destroy) {
|
||||
this._inflate.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
ParserAsync.prototype._inflateData = function(data) {
|
||||
if (!this._inflate) {
|
||||
this._inflate = zlib.createInflate();
|
||||
|
||||
this._inflate.on('error', this.emit.bind(this, 'error'));
|
||||
this._filter.on('complete', this._complete.bind(this));
|
||||
|
||||
this._inflate.pipe(this._filter);
|
||||
}
|
||||
this._inflate.write(data);
|
||||
};
|
||||
|
||||
ParserAsync.prototype._createData = function(width, height, bpp) {
|
||||
this._data = new Buffer(width * height * 4);
|
||||
this._filter = new FilterAsync(
|
||||
width, height,
|
||||
bpp,
|
||||
this._data,
|
||||
this._options
|
||||
);
|
||||
return this._data;
|
||||
};
|
||||
|
||||
ParserAsync.prototype._finished = function(data) {
|
||||
// no more data to inflate
|
||||
this._inflate.end();
|
||||
this.destroySoon();
|
||||
};
|
||||
|
||||
ParserAsync.prototype._complete = function(data, width, height) {
|
||||
|
||||
data = this._parser.reverseFiltered(data, width, height);
|
||||
|
||||
this.emit('parsed', data);
|
||||
};
|
||||
87
lib/parser-sync.js
Normal file
87
lib/parser-sync.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// 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 zlib = require('zlib'),
|
||||
SyncReader = require('./sync-reader'),
|
||||
FilterSync = require('./filter-sync'),
|
||||
Parser = require('./parser');
|
||||
|
||||
|
||||
var ParserSync = module.exports = function(buffer, options) {
|
||||
|
||||
var reader = new SyncReader(buffer);
|
||||
|
||||
this._inflateDataList = [];
|
||||
this._parser = new Parser(options, {
|
||||
read: reader.read.bind(reader),
|
||||
error: this._handleError.bind(this),
|
||||
metadata: this._metaData.bind(this),
|
||||
gamma: this._gamma.bind(this),
|
||||
finished: function() {},
|
||||
inflateData: this._inflateData.bind(this),
|
||||
createData: this._createData.bind(this)
|
||||
});
|
||||
this._options = options;
|
||||
|
||||
this._parser.start();
|
||||
reader.process();
|
||||
|
||||
//join together the inflate datas
|
||||
var inflateData = Buffer.concat(this._inflateDataList);
|
||||
|
||||
var data = zlib.inflateSync(inflateData);
|
||||
|
||||
FilterSync.process(
|
||||
data,
|
||||
this._width, this._height,
|
||||
this._bpp,
|
||||
this._data,
|
||||
this._options
|
||||
);
|
||||
|
||||
this.data = this._parser.reverseFiltered(this._data, this._width, this._height);
|
||||
};
|
||||
|
||||
ParserSync.prototype._handleError = function(err) {
|
||||
this.err = err;
|
||||
};
|
||||
|
||||
ParserSync.prototype._metaData = function(metaData) {
|
||||
this.metaData = metaData;
|
||||
};
|
||||
|
||||
ParserSync.prototype._gamma = function(gamma) {
|
||||
this.gamma = gamma;
|
||||
};
|
||||
|
||||
ParserSync.prototype._inflateData = function(data) {
|
||||
this._inflateDataList.push(data);
|
||||
};
|
||||
|
||||
ParserSync.prototype._createData = function(width, height, bpp) {
|
||||
this._data = new Buffer(width * height * 4);
|
||||
this._bpp = bpp;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
return this._data;
|
||||
};
|
||||
423
lib/parser.js
Executable file → Normal file
423
lib/parser.js
Executable file → Normal file
|
|
@ -21,339 +21,302 @@
|
|||
'use strict';
|
||||
|
||||
|
||||
var util = require('util'),
|
||||
zlib = require('zlib'),
|
||||
CrcStream = require('./crc'),
|
||||
ChunkStream = require('./chunkstream'),
|
||||
constants = require('./constants'),
|
||||
Filter = require('./filter');
|
||||
var constants = require('./constants'),
|
||||
CrcCalculator = require('./crc');
|
||||
|
||||
|
||||
var Parser = module.exports = function(options) {
|
||||
ChunkStream.call(this);
|
||||
var Parser = module.exports = function(options, dependencies) {
|
||||
|
||||
this._options = options;
|
||||
options.checkCRC = options.checkCRC !== false;
|
||||
this._options = options;
|
||||
options.checkCRC = options.checkCRC !== false;
|
||||
|
||||
this._hasIHDR = false;
|
||||
this._hasIEND = false;
|
||||
this._hasIHDR = false;
|
||||
this._hasIEND = false;
|
||||
|
||||
this._inflate = null;
|
||||
this._filter = null;
|
||||
this._crc = null;
|
||||
// input flags/metadata
|
||||
this._palette = [];
|
||||
this._colorType = 0;
|
||||
|
||||
// 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._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();
|
||||
};
|
||||
util.inherits(Parser, ChunkStream);
|
||||
|
||||
|
||||
Parser.prototype._handleError = function() {
|
||||
|
||||
this.writable = false;
|
||||
|
||||
this.destroy();
|
||||
|
||||
if (this._inflate)
|
||||
this._inflate.destroy();
|
||||
this.read = dependencies.read;
|
||||
this.error = dependencies.error;
|
||||
this.metadata = dependencies.metadata;
|
||||
this.gamma = dependencies.gamma;
|
||||
this.parsed = dependencies.parsed;
|
||||
this.createData = dependencies.createData;
|
||||
this.inflateData = dependencies.inflateData;
|
||||
this.finished = dependencies.finished;
|
||||
};
|
||||
|
||||
Parser.prototype._handleSignature = function() {
|
||||
this.read(constants.PNG_SIGNATURE.length,
|
||||
this._parseSignature.bind(this)
|
||||
);
|
||||
var colorTypeToBppMap = {
|
||||
0: 1,
|
||||
2: 3,
|
||||
3: 1,
|
||||
4: 2,
|
||||
6: 4
|
||||
};
|
||||
|
||||
Parser.prototype.start = function() {
|
||||
this.read(constants.PNG_SIGNATURE.length,
|
||||
this._parseSignature.bind(this)
|
||||
);
|
||||
};
|
||||
|
||||
Parser.prototype._parseSignature = function(data) {
|
||||
|
||||
var signature = constants.PNG_SIGNATURE;
|
||||
var signature = constants.PNG_SIGNATURE;
|
||||
|
||||
for (var i = 0; i < signature.length; i++) {
|
||||
if (data[i] != signature[i]) {
|
||||
this.emit('error', new Error('Invalid file signature'));
|
||||
return;
|
||||
}
|
||||
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));
|
||||
}
|
||||
this.read(8, this._parseChunkBegin.bind(this));
|
||||
};
|
||||
|
||||
Parser.prototype._parseChunkBegin = function(data) {
|
||||
|
||||
// chunk content length
|
||||
var length = data.readUInt32BE(0);
|
||||
// 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]);
|
||||
// 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);
|
||||
//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
|
||||
// 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.emit('error', new Error('Expected IHDR on beggining'));
|
||||
return;
|
||||
}
|
||||
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));
|
||||
this._crc = new CrcCalculator();
|
||||
this._crc.write(new Buffer(name));
|
||||
|
||||
if (this._chunks[type]) {
|
||||
return this._chunks[type](length);
|
||||
if (this._chunks[type]) {
|
||||
return this._chunks[type](length);
|
||||
|
||||
} else if (!ancillary) {
|
||||
this.emit('error', new Error('Unsupported critical chunk type ' + name));
|
||||
return;
|
||||
} else {
|
||||
this.read(length + 4, this._skipChunk.bind(this));
|
||||
}
|
||||
} 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));
|
||||
this.read(8, this._parseChunkBegin.bind(this));
|
||||
};
|
||||
|
||||
Parser.prototype._handleChunkEnd = function() {
|
||||
this.read(4, this._parseChunkEnd.bind(this));
|
||||
this.read(4, this._parseChunkEnd.bind(this));
|
||||
};
|
||||
|
||||
Parser.prototype._parseChunkEnd = function(data) {
|
||||
|
||||
var fileCrc = data.readInt32BE(0),
|
||||
calcCrc = this._crc.crc32();
|
||||
var fileCrc = data.readInt32BE(0),
|
||||
calcCrc = this._crc.crc32();
|
||||
|
||||
// check CRC
|
||||
if (this._options.checkCRC && calcCrc != fileCrc) {
|
||||
this.emit('error', new Error('Crc error'));
|
||||
return;
|
||||
}
|
||||
// check CRC
|
||||
if (this._options.checkCRC && calcCrc != fileCrc) {
|
||||
this.error(new Error('Crc error - ' + fileCrc + " - " + calcCrc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._hasIEND) {
|
||||
this.destroySoon();
|
||||
|
||||
} else {
|
||||
this.read(8, this._parseChunkBegin.bind(this));
|
||||
}
|
||||
if (!this._hasIEND) {
|
||||
this.read(8, this._parseChunkBegin.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Parser.prototype._handleIHDR = function(length) {
|
||||
this.read(length, this._parseIHDR.bind(this));
|
||||
this.read(length, this._parseIHDR.bind(this));
|
||||
};
|
||||
Parser.prototype._parseIHDR = function(data) {
|
||||
|
||||
this._crc.write(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];
|
||||
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
|
||||
// );
|
||||
// console.log(' width', width, 'height', height,
|
||||
// 'depth', depth, 'colorType', colorType,
|
||||
// 'compr', compr, 'filter', filter, 'interlace', interlace
|
||||
// );
|
||||
|
||||
if (depth != 8) {
|
||||
this.emit('error', new Error('Unsupported bit depth ' + depth));
|
||||
return;
|
||||
}
|
||||
if (!(colorType in colorTypeToBppMap)) {
|
||||
this.emit('error', new Error('Unsupported color type'));
|
||||
return;
|
||||
}
|
||||
if (compr != 0) {
|
||||
this.emit('error', new Error('Unsupported compression method'));
|
||||
return;
|
||||
}
|
||||
if (filter != 0) {
|
||||
this.emit('error', new Error('Unsupported filter method'));
|
||||
return;
|
||||
}
|
||||
if (interlace != 0) {
|
||||
this.emit('error', new Error('Unsupported interlace method'));
|
||||
return;
|
||||
}
|
||||
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._colorType = colorType;
|
||||
|
||||
this._data = new Buffer(width * height * 4);
|
||||
this._filter = new Filter(
|
||||
width, height,
|
||||
colorTypeToBppMap[this._colorType],
|
||||
this._data,
|
||||
this._options
|
||||
);
|
||||
this._data = this.createData(width, height, colorTypeToBppMap[this._colorType]);
|
||||
|
||||
this._hasIHDR = true;
|
||||
this._hasIHDR = true;
|
||||
|
||||
this.emit('metadata', {
|
||||
width: width,
|
||||
height: height,
|
||||
palette: !!(colorType & constants.COLOR_PALETTE),
|
||||
color: !!(colorType & constants.COLOR_COLOR),
|
||||
alpha: !!(colorType & constants.COLOR_ALPHA),
|
||||
data: this._data
|
||||
});
|
||||
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();
|
||||
this._handleChunkEnd();
|
||||
};
|
||||
|
||||
|
||||
Parser.prototype._handlePLTE = function(length) {
|
||||
this.read(length, this._parsePLTE.bind(this));
|
||||
this.read(length, this._parsePLTE.bind(this));
|
||||
};
|
||||
Parser.prototype._parsePLTE = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
this._crc.write(data);
|
||||
|
||||
var entries = Math.floor(data.length / 3);
|
||||
// console.log('Palette:', entries);
|
||||
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
|
||||
]);
|
||||
}
|
||||
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();
|
||||
this._handleChunkEnd();
|
||||
};
|
||||
|
||||
Parser.prototype._handleTRNS = function(length) {
|
||||
this.read(length, this._parseTRNS.bind(this));
|
||||
this.read(length, this._parseTRNS.bind(this));
|
||||
};
|
||||
Parser.prototype._parseTRNS = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
this._crc.write(data);
|
||||
|
||||
// palette
|
||||
if (this._colorType == 3) {
|
||||
if (this._palette.length == 0) {
|
||||
this.emit('error', new Error('Transparency chunk must be after palette'));
|
||||
return;
|
||||
}
|
||||
if (data.length > this._palette.length) {
|
||||
this.emit('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;
|
||||
}
|
||||
// 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
|
||||
// for colorType 0 (grayscale) and 2 (rgb)
|
||||
// there might be one gray/color defined as transparent
|
||||
|
||||
this._handleChunkEnd();
|
||||
this._handleChunkEnd();
|
||||
};
|
||||
|
||||
Parser.prototype._handleGAMA = function(length) {
|
||||
this.read(length, this._parseGAMA.bind(this));
|
||||
this.read(length, this._parseGAMA.bind(this));
|
||||
};
|
||||
Parser.prototype._parseGAMA = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
this.emit('gamma', data.readUInt32BE(0) / 100000);
|
||||
this._crc.write(data);
|
||||
this.gamma(data.readUInt32BE(0) / 100000);
|
||||
|
||||
this._handleChunkEnd();
|
||||
this._handleChunkEnd();
|
||||
};
|
||||
|
||||
Parser.prototype._handleIDAT = function(length) {
|
||||
this.read(-length, this._parseIDAT.bind(this, length));
|
||||
this.read(-length, this._parseIDAT.bind(this, length));
|
||||
};
|
||||
Parser.prototype._parseIDAT = function(length, data) {
|
||||
|
||||
this._crc.write(data);
|
||||
this._crc.write(data);
|
||||
|
||||
if (this._colorType == 3 && this._palette.length == 0)
|
||||
throw new Error('Expected palette not found');
|
||||
if (this._colorType == 3 && this._palette.length == 0)
|
||||
throw new Error('Expected palette not found');
|
||||
|
||||
if (!this._inflate) {
|
||||
this._inflate = zlib.createInflate();
|
||||
this.inflateData(data);
|
||||
length -= data.length;
|
||||
|
||||
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();
|
||||
if (length > 0)
|
||||
this._handleIDAT(length);
|
||||
else
|
||||
this._handleChunkEnd();
|
||||
};
|
||||
|
||||
|
||||
Parser.prototype._handleIEND = function(length) {
|
||||
this.read(length, this._parseIEND.bind(this));
|
||||
this.read(length, this._parseIEND.bind(this));
|
||||
};
|
||||
Parser.prototype._parseIEND = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
this._crc.write(data);
|
||||
|
||||
// no more data to inflate
|
||||
this._inflate.end();
|
||||
this._hasIEND = true;
|
||||
this._handleChunkEnd();
|
||||
|
||||
this._hasIEND = true;
|
||||
this._handleChunkEnd();
|
||||
this.finished();
|
||||
};
|
||||
|
||||
Parser.prototype.reverseFiltered = function(data, width, height) {
|
||||
|
||||
var colorTypeToBppMap = {
|
||||
0: 1,
|
||||
2: 3,
|
||||
3: 1,
|
||||
4: 2,
|
||||
6: 4
|
||||
};
|
||||
if (this._colorType == 3) { // paletted
|
||||
|
||||
Parser.prototype._reverseFiltered = function(data, width, height) {
|
||||
// use values from palette
|
||||
var pxLineLength = width << 2;
|
||||
|
||||
if (this._colorType == 3) { // paletted
|
||||
for (var y = 0; y < height; y++) {
|
||||
var pxRowPos = y * pxLineLength;
|
||||
|
||||
// use values from palette
|
||||
var pxLineLength = width << 2;
|
||||
for (var x = 0; x < width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
color = this._palette[data[pxPos]];
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 4; i++)
|
||||
data[pxPos + i] = color[i];
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('parsed', data);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
|
|
|
|||
42
lib/png-sync.js
Normal file
42
lib/png-sync.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// 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 Parser = require('./parser-sync');
|
||||
|
||||
|
||||
exports.read = function(buffer, options) {
|
||||
|
||||
options = options || {};
|
||||
var parser = new Parser(buffer, options);
|
||||
|
||||
if (parser.err) {
|
||||
throw parser.err;
|
||||
}
|
||||
|
||||
return {
|
||||
data: parser.data,
|
||||
width: parser._width,
|
||||
height: parser._height,
|
||||
gamma: parser.gamma || 0
|
||||
};
|
||||
};
|
||||
47
lib/png.js
47
lib/png.js
|
|
@ -23,8 +23,9 @@
|
|||
|
||||
var util = require('util'),
|
||||
Stream = require('stream'),
|
||||
Parser = require('./parser'),
|
||||
Packer = require('./packer');
|
||||
Parser = require('./parser-async'),
|
||||
Packer = require('./packer'),
|
||||
PNGSync = require('./png-sync');
|
||||
|
||||
|
||||
var PNG = exports.PNG = function(options) {
|
||||
|
|
@ -34,7 +35,7 @@ var PNG = exports.PNG = function(options) {
|
|||
|
||||
this.width = options.width || 0;
|
||||
this.height = options.height || 0;
|
||||
|
||||
|
||||
this.data = this.width > 0 && this.height > 0
|
||||
? new Buffer(4 * this.width * this.height) : null;
|
||||
|
||||
|
|
@ -63,6 +64,7 @@ var PNG = exports.PNG = function(options) {
|
|||
};
|
||||
util.inherits(PNG, Stream);
|
||||
|
||||
PNG.sync = PNGSync;
|
||||
|
||||
PNG.prototype.pack = function() {
|
||||
|
||||
|
|
@ -125,25 +127,46 @@ PNG.prototype._handleClose = function() {
|
|||
this.emit('close');
|
||||
};
|
||||
|
||||
|
||||
PNG.prototype.bitblt = function(dst, sx, sy, w, h, dx, dy) {
|
||||
|
||||
var src = this;
|
||||
PNG.bitblt = function(src, dst, sx, sy, w, h, dx, dy) {
|
||||
|
||||
if (sx > src.width || sy > src.height
|
||||
|| sx + w > src.width || sy + h > src.height)
|
||||
|| sx + w > src.width || sy + h > src.height)
|
||||
throw new Error('bitblt reading outside image');
|
||||
if (dx > dst.width || dy > dst.height
|
||||
|| dx + w > dst.width || dy + h > dst.height)
|
||||
|| dx + w > dst.width || dy + h > dst.height)
|
||||
throw new Error('bitblt writing outside image');
|
||||
|
||||
for (var y = 0; y < h; y++) {
|
||||
src.data.copy(dst.data,
|
||||
((dy + y) * dst.width + dx) << 2,
|
||||
((sy + y) * src.width + sx) << 2,
|
||||
((sy + y) * src.width + sx + w) << 2
|
||||
((dy + y) * dst.width + dx) << 2,
|
||||
((sy + y) * src.width + sx) << 2,
|
||||
((sy + y) * src.width + sx + w) << 2
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
PNG.prototype.bitblt = function(dst, sx, sy, w, h, dx, dy) {
|
||||
|
||||
PNG.bitblt(this, dst, sx, sy, w, h, dx, dy);
|
||||
return this;
|
||||
};
|
||||
|
||||
PNG.adjustGamma = function(src) {
|
||||
if (src.gamma) {
|
||||
for (var y = 0; y < src.height; y++) {
|
||||
for (var x = 0; x < src.width; x++) {
|
||||
var idx = (src.width * y + x) << 2;
|
||||
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var sample = src.data[idx + i] / 255;
|
||||
sample = Math.pow(sample, 1 / 2.2 / src.gamma);
|
||||
src.data[idx + i] = Math.round(sample * 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
src.gamma = 0;
|
||||
}
|
||||
};
|
||||
|
||||
PNG.prototype.adjustGamma = function() { PNG.adjustGamma(this); };
|
||||
70
lib/sync-reader.js
Normal file
70
lib/sync-reader.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// 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 SyncReader = module.exports = function (buffer) {
|
||||
|
||||
this._buffer = buffer;
|
||||
this._reads = [];
|
||||
};
|
||||
|
||||
SyncReader.prototype.read = function (length, callback) {
|
||||
|
||||
this._reads.push({
|
||||
length: Math.abs(length), // if length < 0 then at most this length
|
||||
allowLess: length < 0,
|
||||
func: callback
|
||||
});
|
||||
};
|
||||
|
||||
SyncReader.prototype.process = function () {
|
||||
|
||||
// as long as there is any data and read requests
|
||||
while (this._reads.length > 0 && this._buffer.length) {
|
||||
|
||||
var read = this._reads[0];
|
||||
|
||||
if (this._buffer.length && (this._buffer.length >= read.length || read.allowLess)) {
|
||||
|
||||
// ok there is any data so that we can satisfy this request
|
||||
this._reads.shift(); // == read
|
||||
|
||||
var buf = this._buffer;
|
||||
|
||||
this._buffer = buf.slice(read.length);
|
||||
|
||||
read.func.call(this, buf.slice(0, read.length));
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (this._reads.length > 0) {
|
||||
return new Error('There are some read requests waitng on finished stream');
|
||||
}
|
||||
|
||||
if (this._buffer.length > 0) {
|
||||
return new Error('unrecognised content at end of stream');
|
||||
}
|
||||
|
||||
};
|
||||
BIN
test/in/large.png
Normal file
BIN
test/in/large.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 MiB |
320
test/list.html
320
test/list.html
|
|
@ -11,175 +11,175 @@
|
|||
<body>
|
||||
|
||||
<h3>Filtering</h3>
|
||||
<img src="in/f99n0g04.png"> <img src="out/f99n0g04.png"> filter changing per scanline, grayscale, 4 bit <br />
|
||||
<img src="in/f04n2c08.png"> <img src="out/f04n2c08.png"> no filtering, colour, 8 bit <br />
|
||||
<img src="in/f04n0g08.png"> <img src="out/f04n0g08.png"> no filtering, grayscale, 8 bit<br />
|
||||
<img src="in/f03n2c08.png"> <img src="out/f03n2c08.png"> filter 3, colour, 8 bit <br />
|
||||
<img src="in/f03n0g08.png"> <img src="out/f03n0g08.png"> filter 3, grayscale, 8 bit<br />
|
||||
<img src="in/f02n2c08.png"> <img src="out/f02n2c08.png"> filter 2, colour, 8 bit <br />
|
||||
<img src="in/f02n0g08.png"> <img src="out/f02n0g08.png"> filter 2, grayscale, 8 bit<br />
|
||||
<img src="in/f01n2c08.png"> <img src="out/f01n2c08.png"> filter 1, colour, 8 bit <br />
|
||||
<img src="in/f01n0g08.png"> <img src="out/f01n0g08.png"> filter 1, grayscale, 8 bit<br />
|
||||
<img src="in/f00n2c08.png"> <img src="out/f00n2c08.png"> filter 0, colour, 8 bit <br />
|
||||
<img src="in/f00n0g08.png"> <img src="out/f00n0g08.png"> filter 0, grayscale, 8 bit<br />
|
||||
<img src="in/f99n0g04.png"> <img src="out/f99n0g04.png"> <img src="outsync/f99n0g04.png"> filter changing per scanline, grayscale, 4 bit <br />
|
||||
<img src="in/f04n2c08.png"> <img src="out/f04n2c08.png"> <img src="outsync/f04n2c08.png"> no filtering, colour, 8 bit <br />
|
||||
<img src="in/f04n0g08.png"> <img src="out/f04n0g08.png"> <img src="outsync/f04n0g08.png"> no filtering, grayscale, 8 bit<br />
|
||||
<img src="in/f03n2c08.png"> <img src="out/f03n2c08.png"> <img src="outsync/f03n2c08.png"> filter 3, colour, 8 bit <br />
|
||||
<img src="in/f03n0g08.png"> <img src="out/f03n0g08.png"> <img src="outsync/f03n0g08.png"> filter 3, grayscale, 8 bit<br />
|
||||
<img src="in/f02n2c08.png"> <img src="out/f02n2c08.png"> <img src="outsync/f02n2c08.png"> filter 2, colour, 8 bit <br />
|
||||
<img src="in/f02n0g08.png"> <img src="out/f02n0g08.png"> <img src="outsync/f02n0g08.png"> filter 2, grayscale, 8 bit<br />
|
||||
<img src="in/f01n2c08.png"> <img src="out/f01n2c08.png"> <img src="outsync/f01n2c08.png"> filter 1, colour, 8 bit <br />
|
||||
<img src="in/f01n0g08.png"> <img src="out/f01n0g08.png"> <img src="outsync/f01n0g08.png"> filter 1, grayscale, 8 bit<br />
|
||||
<img src="in/f00n2c08.png"> <img src="out/f00n2c08.png"> <img src="outsync/f00n2c08.png"> filter 0, colour, 8 bit <br />
|
||||
<img src="in/f00n0g08.png"> <img src="out/f00n0g08.png"> <img src="outsync/f00n0g08.png"> filter 0, grayscale, 8 bit<br />
|
||||
<h3>Ancilary chunks</h3>
|
||||
<img src="in/ctzn0g04.png"> <img src="out/ctzn0g04.png"> <br />
|
||||
<img src="in/ctjn0g04.png"> <img src="out/ctjn0g04.png"> <br />
|
||||
<img src="in/cthn0g04.png"> <img src="out/cthn0g04.png"> <br />
|
||||
<img src="in/ctgn0g04.png"> <img src="out/ctgn0g04.png"> <br />
|
||||
<img src="in/ctfn0g04.png"> <img src="out/ctfn0g04.png"> <br />
|
||||
<img src="in/cten0g04.png"> <img src="out/cten0g04.png"> <br />
|
||||
<img src="in/ct1n0g04.png"> <img src="out/ct1n0g04.png"> <br />
|
||||
<img src="in/ct0n0g04.png"> <img src="out/ct0n0g04.png"> <br />
|
||||
<img src="in/cs8n3p08.png"> <img src="out/cs8n3p08.png"> <br />
|
||||
<img src="in/cs8n2c08.png"> <img src="out/cs8n2c08.png"> <br />
|
||||
<img src="in/cs5n3p08.png"> <img src="out/cs5n3p08.png"> <br />
|
||||
<img src="in/cs5n2c08.png"> <img src="out/cs5n2c08.png"> <br />
|
||||
<img src="in/cs3n3p08.png"> <img src="out/cs3n3p08.png"> <br />
|
||||
<img src="in/cs3n2c16.png"> <img src="out/cs3n2c16.png"> <br />
|
||||
<img src="in/cm9n0g04.png"> <img src="out/cm9n0g04.png"> <br />
|
||||
<img src="in/cm7n0g04.png"> <img src="out/cm7n0g04.png"> <br />
|
||||
<img src="in/cm0n0g04.png"> <img src="out/cm0n0g04.png"> <br />
|
||||
<img src="in/ch2n3p08.png"> <img src="out/ch2n3p08.png"> <br />
|
||||
<img src="in/ch1n3p04.png"> <img src="out/ch1n3p04.png"> <br />
|
||||
<img src="in/cdun2c08.png"> <img src="out/cdun2c08.png"> <br />
|
||||
<img src="in/cdsn2c08.png"> <img src="out/cdsn2c08.png"> <br />
|
||||
<img src="in/cdhn2c08.png"> <img src="out/cdhn2c08.png"> <br />
|
||||
<img src="in/cdfn2c08.png"> <img src="out/cdfn2c08.png"> <br />
|
||||
<img src="in/ccwn3p08.png"> <img src="out/ccwn3p08.png"> <br />
|
||||
<img src="in/ccwn2c08.png"> <img src="out/ccwn2c08.png"> <br />
|
||||
<img src="in/ctzn0g04.png"> <img src="out/ctzn0g04.png"> <img src="outsync/ctzn0g04.png"> <br />
|
||||
<img src="in/ctjn0g04.png"> <img src="out/ctjn0g04.png"> <img src="outsync/ctjn0g04.png"> <br />
|
||||
<img src="in/cthn0g04.png"> <img src="out/cthn0g04.png"> <img src="outsync/cthn0g04.png"> <br />
|
||||
<img src="in/ctgn0g04.png"> <img src="out/ctgn0g04.png"> <img src="outsync/ctgn0g04.png"> <br />
|
||||
<img src="in/ctfn0g04.png"> <img src="out/ctfn0g04.png"> <img src="outsync/ctfn0g04.png"> <br />
|
||||
<img src="in/cten0g04.png"> <img src="out/cten0g04.png"> <img src="outsync/cten0g04.png"> <br />
|
||||
<img src="in/ct1n0g04.png"> <img src="out/ct1n0g04.png"> <img src="outsync/ct1n0g04.png"> <br />
|
||||
<img src="in/ct0n0g04.png"> <img src="out/ct0n0g04.png"> <img src="outsync/ct0n0g04.png"> <br />
|
||||
<img src="in/cs8n3p08.png"> <img src="out/cs8n3p08.png"> <img src="outsync/cs8n3p08.png"> <br />
|
||||
<img src="in/cs8n2c08.png"> <img src="out/cs8n2c08.png"> <img src="outsync/cs8n2c08.png"> <br />
|
||||
<img src="in/cs5n3p08.png"> <img src="out/cs5n3p08.png"> <img src="outsync/cs5n3p08.png"> <br />
|
||||
<img src="in/cs5n2c08.png"> <img src="out/cs5n2c08.png"> <img src="outsync/cs5n2c08.png"> <br />
|
||||
<img src="in/cs3n3p08.png"> <img src="out/cs3n3p08.png"> <img src="outsync/cs3n3p08.png"> <br />
|
||||
<img src="in/cs3n2c16.png"> <img src="out/cs3n2c16.png"> <img src="outsync/cs3n2c16.png"> <br />
|
||||
<img src="in/cm9n0g04.png"> <img src="out/cm9n0g04.png"> <img src="outsync/cm9n0g04.png"> <br />
|
||||
<img src="in/cm7n0g04.png"> <img src="out/cm7n0g04.png"> <img src="outsync/cm7n0g04.png"> <br />
|
||||
<img src="in/cm0n0g04.png"> <img src="out/cm0n0g04.png"> <img src="outsync/cm0n0g04.png"> <br />
|
||||
<img src="in/ch2n3p08.png"> <img src="out/ch2n3p08.png"> <img src="outsync/ch2n3p08.png"> <br />
|
||||
<img src="in/ch1n3p04.png"> <img src="out/ch1n3p04.png"> <img src="outsync/ch1n3p04.png"> <br />
|
||||
<img src="in/cdun2c08.png"> <img src="out/cdun2c08.png"> <img src="outsync/cdun2c08.png"> <br />
|
||||
<img src="in/cdsn2c08.png"> <img src="out/cdsn2c08.png"> <img src="outsync/cdsn2c08.png"> <br />
|
||||
<img src="in/cdhn2c08.png"> <img src="out/cdhn2c08.png"> <img src="outsync/cdhn2c08.png"> <br />
|
||||
<img src="in/cdfn2c08.png"> <img src="out/cdfn2c08.png"> <img src="outsync/cdfn2c08.png"> <br />
|
||||
<img src="in/ccwn3p08.png"> <img src="out/ccwn3p08.png"> <img src="outsync/ccwn3p08.png"> <br />
|
||||
<img src="in/ccwn2c08.png"> <img src="out/ccwn2c08.png"> <img src="outsync/ccwn2c08.png"> <br />
|
||||
|
||||
<h3>Basic</h3>
|
||||
<img src="in/basi0g08.png"> <img src="out/basi0g08.png"> <br />
|
||||
<img src="in/basi0g04.png"> <img src="out/basi0g04.png"> <br />
|
||||
<img src="in/basi0g02.png"> <img src="out/basi0g02.png"> <br />
|
||||
<img src="in/basi0g01.png"> <img src="out/basi0g01.png"> <br />
|
||||
<img src="in/bgyn6a16.png"> <img src="out/bgyn6a16.png"> <br />
|
||||
<img src="in/bgwn6a08.png"> <img src="out/bgwn6a08.png"> <br />
|
||||
<img src="in/bggn4a16.png"> <img src="out/bggn4a16.png"> <br />
|
||||
<img src="in/bgbn4a08.png"> <img src="out/bgbn4a08.png"> <br />
|
||||
<img src="in/bgan6a16.png"> <img src="out/bgan6a16.png"> <br />
|
||||
<img src="in/bgan6a08.png"> <img src="out/bgan6a08.png"> <br />
|
||||
<img src="in/bgai4a16.png"> <img src="out/bgai4a16.png"> <br />
|
||||
<img src="in/bgai4a08.png"> <img src="out/bgai4a08.png"> <br />
|
||||
<img src="in/basn6a16.png"> <img src="out/basn6a16.png"> <br />
|
||||
<img src="in/basn6a08.png"> <img src="out/basn6a08.png"> <br />
|
||||
<img src="in/basn4a16.png"> <img src="out/basn4a16.png"> <br />
|
||||
<img src="in/basn4a08.png"> <img src="out/basn4a08.png"> <br />
|
||||
<img src="in/basn3p08.png"> <img src="out/basn3p08.png"> <br />
|
||||
<img src="in/basn3p04.png"> <img src="out/basn3p04.png"> <br />
|
||||
<img src="in/basn3p02.png"> <img src="out/basn3p02.png"> <br />
|
||||
<img src="in/basn3p01.png"> <img src="out/basn3p01.png"> <br />
|
||||
<img src="in/basn2c16.png"> <img src="out/basn2c16.png"> <br />
|
||||
<img src="in/basn2c08.png"> <img src="out/basn2c08.png"> <br />
|
||||
<img src="in/basn0g16.png"> <img src="out/basn0g16.png"> <br />
|
||||
<img src="in/basn0g08.png"> <img src="out/basn0g08.png"> <br />
|
||||
<img src="in/basn0g04.png"> <img src="out/basn0g04.png"> <br />
|
||||
<img src="in/basn0g02.png"> <img src="out/basn0g02.png"> <br />
|
||||
<img src="in/basn0g01.png"> <img src="out/basn0g01.png"> <br />
|
||||
<img src="in/basi6a16.png"> <img src="out/basi6a16.png"> <br />
|
||||
<img src="in/basi6a08.png"> <img src="out/basi6a08.png"> <br />
|
||||
<img src="in/basi4a16.png"> <img src="out/basi4a16.png"> <br />
|
||||
<img src="in/basi4a08.png"> <img src="out/basi4a08.png"> <br />
|
||||
<img src="in/basi3p08.png"> <img src="out/basi3p08.png"> <br />
|
||||
<img src="in/basi3p04.png"> <img src="out/basi3p04.png"> <br />
|
||||
<img src="in/basi3p02.png"> <img src="out/basi3p02.png"> <br />
|
||||
<img src="in/basi3p01.png"> <img src="out/basi3p01.png"> <br />
|
||||
<img src="in/basi2c16.png"> <img src="out/basi2c16.png"> <br />
|
||||
<img src="in/basi2c08.png"> <img src="out/basi2c08.png"> <br />
|
||||
<img src="in/basi0g16.png"> <img src="out/basi0g16.png"> <br />
|
||||
<img src="in/basi0g08.png"> <img src="out/basi0g08.png"> <img src="outsync/basi0g08.png"> <br />
|
||||
<img src="in/basi0g04.png"> <img src="out/basi0g04.png"> <img src="outsync/basi0g04.png"> <br />
|
||||
<img src="in/basi0g02.png"> <img src="out/basi0g02.png"> <img src="outsync/basi0g02.png"> <br />
|
||||
<img src="in/basi0g01.png"> <img src="out/basi0g01.png"> <img src="outsync/basi0g01.png"> <br />
|
||||
<img src="in/bgyn6a16.png"> <img src="out/bgyn6a16.png"> <img src="outsync/bgyn6a16.png"> <br />
|
||||
<img src="in/bgwn6a08.png"> <img src="out/bgwn6a08.png"> <img src="outsync/bgwn6a08.png"> <br />
|
||||
<img src="in/bggn4a16.png"> <img src="out/bggn4a16.png"> <img src="outsync/bggn4a16.png"> <br />
|
||||
<img src="in/bgbn4a08.png"> <img src="out/bgbn4a08.png"> <img src="outsync/bgbn4a08.png"> <br />
|
||||
<img src="in/bgan6a16.png"> <img src="out/bgan6a16.png"> <img src="outsync/bgan6a16.png"> <br />
|
||||
<img src="in/bgan6a08.png"> <img src="out/bgan6a08.png"> <img src="outsync/bgan6a08.png"> <br />
|
||||
<img src="in/bgai4a16.png"> <img src="out/bgai4a16.png"> <img src="outsync/bgai4a16.png"> <br />
|
||||
<img src="in/bgai4a08.png"> <img src="out/bgai4a08.png"> <img src="outsync/bgai4a08.png"> <br />
|
||||
<img src="in/basn6a16.png"> <img src="out/basn6a16.png"> <img src="outsync/basn6a16.png"> <br />
|
||||
<img src="in/basn6a08.png"> <img src="out/basn6a08.png"> <img src="outsync/basn6a08.png"> <br />
|
||||
<img src="in/basn4a16.png"> <img src="out/basn4a16.png"> <img src="outsync/basn4a16.png"> <br />
|
||||
<img src="in/basn4a08.png"> <img src="out/basn4a08.png"> <img src="outsync/basn4a08.png"> <br />
|
||||
<img src="in/basn3p08.png"> <img src="out/basn3p08.png"> <img src="outsync/basn3p08.png"> <br />
|
||||
<img src="in/basn3p04.png"> <img src="out/basn3p04.png"> <img src="outsync/basn3p04.png"> <br />
|
||||
<img src="in/basn3p02.png"> <img src="out/basn3p02.png"> <img src="outsync/basn3p02.png"> <br />
|
||||
<img src="in/basn3p01.png"> <img src="out/basn3p01.png"> <img src="outsync/basn3p01.png"> <br />
|
||||
<img src="in/basn2c16.png"> <img src="out/basn2c16.png"> <img src="outsync/basn2c16.png"> <br />
|
||||
<img src="in/basn2c08.png"> <img src="out/basn2c08.png"> <img src="outsync/basn2c08.png"> <br />
|
||||
<img src="in/basn0g16.png"> <img src="out/basn0g16.png"> <img src="outsync/basn0g16.png"> <br />
|
||||
<img src="in/basn0g08.png"> <img src="out/basn0g08.png"> <img src="outsync/basn0g08.png"> <br />
|
||||
<img src="in/basn0g04.png"> <img src="out/basn0g04.png"> <img src="outsync/basn0g04.png"> <br />
|
||||
<img src="in/basn0g02.png"> <img src="out/basn0g02.png"> <img src="outsync/basn0g02.png"> <br />
|
||||
<img src="in/basn0g01.png"> <img src="out/basn0g01.png"> <img src="outsync/basn0g01.png"> <br />
|
||||
<img src="in/basi6a16.png"> <img src="out/basi6a16.png"> <img src="outsync/basi6a16.png"> <br />
|
||||
<img src="in/basi6a08.png"> <img src="out/basi6a08.png"> <img src="outsync/basi6a08.png"> <br />
|
||||
<img src="in/basi4a16.png"> <img src="out/basi4a16.png"> <img src="outsync/basi4a16.png"> <br />
|
||||
<img src="in/basi4a08.png"> <img src="out/basi4a08.png"> <img src="outsync/basi4a08.png"> <br />
|
||||
<img src="in/basi3p08.png"> <img src="out/basi3p08.png"> <img src="outsync/basi3p08.png"> <br />
|
||||
<img src="in/basi3p04.png"> <img src="out/basi3p04.png"> <img src="outsync/basi3p04.png"> <br />
|
||||
<img src="in/basi3p02.png"> <img src="out/basi3p02.png"> <img src="outsync/basi3p02.png"> <br />
|
||||
<img src="in/basi3p01.png"> <img src="out/basi3p01.png"> <img src="outsync/basi3p01.png"> <br />
|
||||
<img src="in/basi2c16.png"> <img src="out/basi2c16.png"> <img src="outsync/basi2c16.png"> <br />
|
||||
<img src="in/basi2c08.png"> <img src="out/basi2c08.png"> <img src="outsync/basi2c08.png"> <br />
|
||||
<img src="in/basi0g16.png"> <img src="out/basi0g16.png"> <img src="outsync/basi0g16.png"> <br />
|
||||
<h3>ZLib</h3>
|
||||
<img src="in/z09n2c08.png"> <img src="out/z09n2c08.png"> <br />
|
||||
<img src="in/z06n2c08.png"> <img src="out/z06n2c08.png"> <br />
|
||||
<img src="in/z03n2c08.png"> <img src="out/z03n2c08.png"> <br />
|
||||
<img src="in/z00n2c08.png"> <img src="out/z00n2c08.png"> <br />
|
||||
<img src="in/z09n2c08.png"> <img src="out/z09n2c08.png"> <img src="outsync/z09n2c08.png"> <br />
|
||||
<img src="in/z06n2c08.png"> <img src="out/z06n2c08.png"> <img src="outsync/z06n2c08.png"> <br />
|
||||
<img src="in/z03n2c08.png"> <img src="out/z03n2c08.png"> <img src="outsync/z03n2c08.png"> <br />
|
||||
<img src="in/z00n2c08.png"> <img src="out/z00n2c08.png"> <img src="outsync/z00n2c08.png"> <br />
|
||||
<h3>Transparency</h3>
|
||||
<img src="in/tp1n3p08.png"> <img src="out/tp1n3p08.png"> <br />
|
||||
<img src="in/tp0n3p08.png"> <img src="out/tp0n3p08.png"> <br />
|
||||
<img src="in/tp0n2c08.png"> <img src="out/tp0n2c08.png"> <br />
|
||||
<img src="in/tp0n0g08.png"> <img src="out/tp0n0g08.png"> <br />
|
||||
<img src="in/tm3n3p02.png"> <img src="out/tm3n3p02.png"> <br />
|
||||
<img src="in/tbyn3p08.png"> <img src="out/tbyn3p08.png"> <br />
|
||||
<img src="in/tbwn3p08.png"> <img src="out/tbwn3p08.png"> <br />
|
||||
<img src="in/tbwn0g16.png"> <img src="out/tbwn0g16.png"> <br />
|
||||
<img src="in/tbrn2c08.png"> <img src="out/tbrn2c08.png"> <br />
|
||||
<img src="in/tbgn3p08.png"> <img src="out/tbgn3p08.png"> <br />
|
||||
<img src="in/tbgn2c16.png"> <img src="out/tbgn2c16.png"> <br />
|
||||
<img src="in/tbbn3p08.png"> <img src="out/tbbn3p08.png"> <br />
|
||||
<img src="in/tbbn2c16.png"> <img src="out/tbbn2c16.png"> <br />
|
||||
<img src="in/tbbn0g04.png"> <img src="out/tbbn0g04.png"> <br />
|
||||
<img src="in/tp1n3p08.png"> <img src="out/tp1n3p08.png"> <img src="outsync/tp1n3p08.png"> <br />
|
||||
<img src="in/tp0n3p08.png"> <img src="out/tp0n3p08.png"> <img src="outsync/tp0n3p08.png"> <br />
|
||||
<img src="in/tp0n2c08.png"> <img src="out/tp0n2c08.png"> <img src="outsync/tp0n2c08.png"> <br />
|
||||
<img src="in/tp0n0g08.png"> <img src="out/tp0n0g08.png"> <img src="outsync/tp0n0g08.png"> <br />
|
||||
<img src="in/tm3n3p02.png"> <img src="out/tm3n3p02.png"> <img src="outsync/tm3n3p02.png"> <br />
|
||||
<img src="in/tbyn3p08.png"> <img src="out/tbyn3p08.png"> <img src="outsync/tbyn3p08.png"> <br />
|
||||
<img src="in/tbwn3p08.png"> <img src="out/tbwn3p08.png"> <img src="outsync/tbwn3p08.png"> <br />
|
||||
<img src="in/tbwn0g16.png"> <img src="out/tbwn0g16.png"> <img src="outsync/tbwn0g16.png"> <br />
|
||||
<img src="in/tbrn2c08.png"> <img src="out/tbrn2c08.png"> <img src="outsync/tbrn2c08.png"> <br />
|
||||
<img src="in/tbgn3p08.png"> <img src="out/tbgn3p08.png"> <img src="outsync/tbgn3p08.png"> <br />
|
||||
<img src="in/tbgn2c16.png"> <img src="out/tbgn2c16.png"> <img src="outsync/tbgn2c16.png"> <br />
|
||||
<img src="in/tbbn3p08.png"> <img src="out/tbbn3p08.png"> <img src="outsync/tbbn3p08.png"> <br />
|
||||
<img src="in/tbbn2c16.png"> <img src="out/tbbn2c16.png"> <img src="outsync/tbbn2c16.png"> <br />
|
||||
<img src="in/tbbn0g04.png"> <img src="out/tbbn0g04.png"> <img src="outsync/tbbn0g04.png"> <br />
|
||||
<h3>Sizing</h3>
|
||||
<img src="in/s40n3p04.png"> <img src="out/s40n3p04.png"> <br />
|
||||
<img src="in/s40i3p04.png"> <img src="out/s40i3p04.png"> <br />
|
||||
<img src="in/s39n3p04.png"> <img src="out/s39n3p04.png"> <br />
|
||||
<img src="in/s39i3p04.png"> <img src="out/s39i3p04.png"> <br />
|
||||
<img src="in/s38n3p04.png"> <img src="out/s38n3p04.png"> <br />
|
||||
<img src="in/s38i3p04.png"> <img src="out/s38i3p04.png"> <br />
|
||||
<img src="in/s37n3p04.png"> <img src="out/s37n3p04.png"> <br />
|
||||
<img src="in/s37i3p04.png"> <img src="out/s37i3p04.png"> <br />
|
||||
<img src="in/s36n3p04.png"> <img src="out/s36n3p04.png"> <br />
|
||||
<img src="in/s36i3p04.png"> <img src="out/s36i3p04.png"> <br />
|
||||
<img src="in/s35n3p04.png"> <img src="out/s35n3p04.png"> <br />
|
||||
<img src="in/s35i3p04.png"> <img src="out/s35i3p04.png"> <br />
|
||||
<img src="in/s34n3p04.png"> <img src="out/s34n3p04.png"> <br />
|
||||
<img src="in/s34i3p04.png"> <img src="out/s34i3p04.png"> <br />
|
||||
<img src="in/s33n3p04.png"> <img src="out/s33n3p04.png"> <br />
|
||||
<img src="in/s33i3p04.png"> <img src="out/s33i3p04.png"> <br />
|
||||
<img src="in/s32n3p04.png"> <img src="out/s32n3p04.png"> <br />
|
||||
<img src="in/s32i3p04.png"> <img src="out/s32i3p04.png"> <br />
|
||||
<img src="in/s09n3p02.png"> <img src="out/s09n3p02.png"> <br />
|
||||
<img src="in/s09i3p02.png"> <img src="out/s09i3p02.png"> <br />
|
||||
<img src="in/s08n3p02.png"> <img src="out/s08n3p02.png"> <br />
|
||||
<img src="in/s08i3p02.png"> <img src="out/s08i3p02.png"> <br />
|
||||
<img src="in/s07n3p02.png"> <img src="out/s07n3p02.png"> <br />
|
||||
<img src="in/s07i3p02.png"> <img src="out/s07i3p02.png"> <br />
|
||||
<img src="in/s06n3p02.png"> <img src="out/s06n3p02.png"> <br />
|
||||
<img src="in/s06i3p02.png"> <img src="out/s06i3p02.png"> <br />
|
||||
<img src="in/s05n3p02.png"> <img src="out/s05n3p02.png"> <br />
|
||||
<img src="in/s05i3p02.png"> <img src="out/s05i3p02.png"> <br />
|
||||
<img src="in/s04n3p01.png"> <img src="out/s04n3p01.png"> <br />
|
||||
<img src="in/s04i3p01.png"> <img src="out/s04i3p01.png"> <br />
|
||||
<img src="in/s03n3p01.png"> <img src="out/s03n3p01.png"> <br />
|
||||
<img src="in/s03i3p01.png"> <img src="out/s03i3p01.png"> <br />
|
||||
<img src="in/s02n3p01.png"> <img src="out/s02n3p01.png"> <br />
|
||||
<img src="in/s02i3p01.png"> <img src="out/s02i3p01.png"> <br />
|
||||
<img src="in/s01n3p01.png"> <img src="out/s01n3p01.png"> <br />
|
||||
<img src="in/s01i3p01.png"> <img src="out/s01i3p01.png"> <br />
|
||||
<img src="in/s40n3p04.png"> <img src="out/s40n3p04.png"> <img src="outsync/s40n3p04.png"> <br />
|
||||
<img src="in/s40i3p04.png"> <img src="out/s40i3p04.png"> <img src="outsync/s40i3p04.png"> <br />
|
||||
<img src="in/s39n3p04.png"> <img src="out/s39n3p04.png"> <img src="outsync/s39n3p04.png"> <br />
|
||||
<img src="in/s39i3p04.png"> <img src="out/s39i3p04.png"> <img src="outsync/s39i3p04.png"> <br />
|
||||
<img src="in/s38n3p04.png"> <img src="out/s38n3p04.png"> <img src="outsync/s38n3p04.png"> <br />
|
||||
<img src="in/s38i3p04.png"> <img src="out/s38i3p04.png"> <img src="outsync/s38i3p04.png"> <br />
|
||||
<img src="in/s37n3p04.png"> <img src="out/s37n3p04.png"> <img src="outsync/s37n3p04.png"> <br />
|
||||
<img src="in/s37i3p04.png"> <img src="out/s37i3p04.png"> <img src="outsync/s37i3p04.png"> <br />
|
||||
<img src="in/s36n3p04.png"> <img src="out/s36n3p04.png"> <img src="outsync/s36n3p04.png"> <br />
|
||||
<img src="in/s36i3p04.png"> <img src="out/s36i3p04.png"> <img src="outsync/s36i3p04.png"> <br />
|
||||
<img src="in/s35n3p04.png"> <img src="out/s35n3p04.png"> <img src="outsync/s35n3p04.png"> <br />
|
||||
<img src="in/s35i3p04.png"> <img src="out/s35i3p04.png"> <img src="outsync/s35i3p04.png"> <br />
|
||||
<img src="in/s34n3p04.png"> <img src="out/s34n3p04.png"> <img src="outsync/s34n3p04.png"> <br />
|
||||
<img src="in/s34i3p04.png"> <img src="out/s34i3p04.png"> <img src="outsync/s34i3p04.png"> <br />
|
||||
<img src="in/s33n3p04.png"> <img src="out/s33n3p04.png"> <img src="outsync/s33n3p04.png"> <br />
|
||||
<img src="in/s33i3p04.png"> <img src="out/s33i3p04.png"> <img src="outsync/s33i3p04.png"> <br />
|
||||
<img src="in/s32n3p04.png"> <img src="out/s32n3p04.png"> <img src="outsync/s32n3p04.png"> <br />
|
||||
<img src="in/s32i3p04.png"> <img src="out/s32i3p04.png"> <img src="outsync/s32i3p04.png"> <br />
|
||||
<img src="in/s09n3p02.png"> <img src="out/s09n3p02.png"> <img src="outsync/s09n3p02.png"> <br />
|
||||
<img src="in/s09i3p02.png"> <img src="out/s09i3p02.png"> <img src="outsync/s09i3p02.png"> <br />
|
||||
<img src="in/s08n3p02.png"> <img src="out/s08n3p02.png"> <img src="outsync/s08n3p02.png"> <br />
|
||||
<img src="in/s08i3p02.png"> <img src="out/s08i3p02.png"> <img src="outsync/s08i3p02.png"> <br />
|
||||
<img src="in/s07n3p02.png"> <img src="out/s07n3p02.png"> <img src="outsync/s07n3p02.png"> <br />
|
||||
<img src="in/s07i3p02.png"> <img src="out/s07i3p02.png"> <img src="outsync/s07i3p02.png"> <br />
|
||||
<img src="in/s06n3p02.png"> <img src="out/s06n3p02.png"> <img src="outsync/s06n3p02.png"> <br />
|
||||
<img src="in/s06i3p02.png"> <img src="out/s06i3p02.png"> <img src="outsync/s06i3p02.png"> <br />
|
||||
<img src="in/s05n3p02.png"> <img src="out/s05n3p02.png"> <img src="outsync/s05n3p02.png"> <br />
|
||||
<img src="in/s05i3p02.png"> <img src="out/s05i3p02.png"> <img src="outsync/s05i3p02.png"> <br />
|
||||
<img src="in/s04n3p01.png"> <img src="out/s04n3p01.png"> <img src="outsync/s04n3p01.png"> <br />
|
||||
<img src="in/s04i3p01.png"> <img src="out/s04i3p01.png"> <img src="outsync/s04i3p01.png"> <br />
|
||||
<img src="in/s03n3p01.png"> <img src="out/s03n3p01.png"> <img src="outsync/s03n3p01.png"> <br />
|
||||
<img src="in/s03i3p01.png"> <img src="out/s03i3p01.png"> <img src="outsync/s03i3p01.png"> <br />
|
||||
<img src="in/s02n3p01.png"> <img src="out/s02n3p01.png"> <img src="outsync/s02n3p01.png"> <br />
|
||||
<img src="in/s02i3p01.png"> <img src="out/s02i3p01.png"> <img src="outsync/s02i3p01.png"> <br />
|
||||
<img src="in/s01n3p01.png"> <img src="out/s01n3p01.png"> <img src="outsync/s01n3p01.png"> <br />
|
||||
<img src="in/s01i3p01.png"> <img src="out/s01i3p01.png"> <img src="outsync/s01i3p01.png"> <br />
|
||||
<h3>Pallettes</h3>
|
||||
<img src="in/ps2n2c16.png"> <img src="out/ps2n2c16.png"> <br />
|
||||
<img src="in/ps2n0g08.png"> <img src="out/ps2n0g08.png"> <br />
|
||||
<img src="in/ps1n2c16.png"> <img src="out/ps1n2c16.png"> <br />
|
||||
<img src="in/ps1n0g08.png"> <img src="out/ps1n0g08.png"> <br />
|
||||
<img src="in/pp0n6a08.png"> <img src="out/pp0n6a08.png"> <br />
|
||||
<img src="in/pp0n2c16.png"> <img src="out/pp0n2c16.png"> <br />
|
||||
<img src="in/ps2n2c16.png"> <img src="out/ps2n2c16.png"> <img src="outsync/ps2n2c16.png"> <br />
|
||||
<img src="in/ps2n0g08.png"> <img src="out/ps2n0g08.png"> <img src="outsync/ps2n0g08.png"> <br />
|
||||
<img src="in/ps1n2c16.png"> <img src="out/ps1n2c16.png"> <img src="outsync/ps1n2c16.png"> <br />
|
||||
<img src="in/ps1n0g08.png"> <img src="out/ps1n0g08.png"> <img src="outsync/ps1n0g08.png"> <br />
|
||||
<img src="in/pp0n6a08.png"> <img src="out/pp0n6a08.png"> <img src="outsync/pp0n6a08.png"> <br />
|
||||
<img src="in/pp0n2c16.png"> <img src="out/pp0n2c16.png"> <img src="outsync/pp0n2c16.png"> <br />
|
||||
<h3>Chunk Ordering</h3>
|
||||
<img src="in/oi9n2c16.png"> <img src="out/oi9n2c16.png"> <br />
|
||||
<img src="in/oi9n0g16.png"> <img src="out/oi9n0g16.png"> <br />
|
||||
<img src="in/oi4n2c16.png"> <img src="out/oi4n2c16.png"> <br />
|
||||
<img src="in/oi4n0g16.png"> <img src="out/oi4n0g16.png"> <br />
|
||||
<img src="in/oi2n2c16.png"> <img src="out/oi2n2c16.png"> <br />
|
||||
<img src="in/oi2n0g16.png"> <img src="out/oi2n0g16.png"> <br />
|
||||
<img src="in/oi1n2c16.png"> <img src="out/oi1n2c16.png"> <br />
|
||||
<img src="in/oi1n0g16.png"> <img src="out/oi1n0g16.png"> <br />
|
||||
<img src="in/oi9n2c16.png"> <img src="out/oi9n2c16.png"> <img src="outsync/oi9n2c16.png"> <br />
|
||||
<img src="in/oi9n0g16.png"> <img src="out/oi9n0g16.png"> <img src="outsync/oi9n0g16.png"> <br />
|
||||
<img src="in/oi4n2c16.png"> <img src="out/oi4n2c16.png"> <img src="outsync/oi4n2c16.png"> <br />
|
||||
<img src="in/oi4n0g16.png"> <img src="out/oi4n0g16.png"> <img src="outsync/oi4n0g16.png"> <br />
|
||||
<img src="in/oi2n2c16.png"> <img src="out/oi2n2c16.png"> <img src="outsync/oi2n2c16.png"> <br />
|
||||
<img src="in/oi2n0g16.png"> <img src="out/oi2n0g16.png"> <img src="outsync/oi2n0g16.png"> <br />
|
||||
<img src="in/oi1n2c16.png"> <img src="out/oi1n2c16.png"> <img src="outsync/oi1n2c16.png"> <br />
|
||||
<img src="in/oi1n0g16.png"> <img src="out/oi1n0g16.png"> <img src="outsync/oi1n0g16.png"> <br />
|
||||
<h3>Gamma</h3>
|
||||
<img src="in/g25n3p04.png"> <img src="out/g25n3p04.png"> <br />
|
||||
<img src="in/g25n2c08.png"> <img src="out/g25n2c08.png"> <br />
|
||||
<img src="in/g25n0g16.png"> <img src="out/g25n0g16.png"> <br />
|
||||
<img src="in/g10n3p04.png"> <img src="out/g10n3p04.png"> <br />
|
||||
<img src="in/g10n2c08.png"> <img src="out/g10n2c08.png"> <br />
|
||||
<img src="in/g10n0g16.png"> <img src="out/g10n0g16.png"> <br />
|
||||
<img src="in/g07n3p04.png"> <img src="out/g07n3p04.png"> <br />
|
||||
<img src="in/g07n2c08.png"> <img src="out/g07n2c08.png"> <br />
|
||||
<img src="in/g07n0g16.png"> <img src="out/g07n0g16.png"> <br />
|
||||
<img src="in/g05n3p04.png"> <img src="out/g05n3p04.png"> <br />
|
||||
<img src="in/g05n2c08.png"> <img src="out/g05n2c08.png"> <br />
|
||||
<img src="in/g05n0g16.png"> <img src="out/g05n0g16.png"> <br />
|
||||
<img src="in/g04n3p04.png"> <img src="out/g04n3p04.png"> <br />
|
||||
<img src="in/g04n2c08.png"> <img src="out/g04n2c08.png"> <br />
|
||||
<img src="in/g04n0g16.png"> <img src="out/g04n0g16.png"> <br />
|
||||
<img src="in/g03n3p04.png"> <img src="out/g03n3p04.png"> <br />
|
||||
<img src="in/g03n2c08.png"> <img src="out/g03n2c08.png"> <br />
|
||||
<img src="in/g03n0g16.png"> <img src="out/g03n0g16.png"> <br />
|
||||
<img src="in/g25n3p04.png"> <img src="out/g25n3p04.png"> <img src="outsync/g25n3p04.png"> <br />
|
||||
<img src="in/g25n2c08.png"> <img src="out/g25n2c08.png"> <img src="outsync/g25n2c08.png"> <br />
|
||||
<img src="in/g25n0g16.png"> <img src="out/g25n0g16.png"> <img src="outsync/g25n0g16.png"> <br />
|
||||
<img src="in/g10n3p04.png"> <img src="out/g10n3p04.png"> <img src="outsync/g10n3p04.png"> <br />
|
||||
<img src="in/g10n2c08.png"> <img src="out/g10n2c08.png"> <img src="outsync/g10n2c08.png"> <br />
|
||||
<img src="in/g10n0g16.png"> <img src="out/g10n0g16.png"> <img src="outsync/g10n0g16.png"> <br />
|
||||
<img src="in/g07n3p04.png"> <img src="out/g07n3p04.png"> <img src="outsync/g07n3p04.png"> <br />
|
||||
<img src="in/g07n2c08.png"> <img src="out/g07n2c08.png"> <img src="outsync/g07n2c08.png"> <br />
|
||||
<img src="in/g07n0g16.png"> <img src="out/g07n0g16.png"> <img src="outsync/g07n0g16.png"> <br />
|
||||
<img src="in/g05n3p04.png"> <img src="out/g05n3p04.png"> <img src="outsync/g05n3p04.png"> <br />
|
||||
<img src="in/g05n2c08.png"> <img src="out/g05n2c08.png"> <img src="outsync/g05n2c08.png"> <br />
|
||||
<img src="in/g05n0g16.png"> <img src="out/g05n0g16.png"> <img src="outsync/g05n0g16.png"> <br />
|
||||
<img src="in/g04n3p04.png"> <img src="out/g04n3p04.png"> <img src="outsync/g04n3p04.png"> <br />
|
||||
<img src="in/g04n2c08.png"> <img src="out/g04n2c08.png"> <img src="outsync/g04n2c08.png"> <br />
|
||||
<img src="in/g04n0g16.png"> <img src="out/g04n0g16.png"> <img src="outsync/g04n0g16.png"> <br />
|
||||
<img src="in/g03n3p04.png"> <img src="out/g03n3p04.png"> <img src="outsync/g03n3p04.png"> <br />
|
||||
<img src="in/g03n2c08.png"> <img src="out/g03n2c08.png"> <img src="outsync/g03n2c08.png"> <br />
|
||||
<img src="in/g03n0g16.png"> <img src="out/g03n0g16.png"> <img src="outsync/g03n0g16.png"> <br />
|
||||
|
||||
|
||||
</body>
|
||||
|
|
|
|||
1
test/outsync/.gitignore
vendored
Normal file
1
test/outsync/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.png
|
||||
30
test/test.js
30
test/test.js
|
|
@ -2,7 +2,6 @@
|
|||
var fs = require('fs'),
|
||||
PNG = require('../lib/png').PNG;
|
||||
|
||||
|
||||
fs.readdir(__dirname + '/in/', function(err, files) {
|
||||
if (err) throw err;
|
||||
|
||||
|
|
@ -20,6 +19,19 @@ fs.readdir(__dirname + '/in/', function(err, files) {
|
|||
expectedError = true;
|
||||
}
|
||||
|
||||
if (!expectedError) {
|
||||
var data = fs.readFileSync(__dirname + '/in/' + file);
|
||||
var png = PNG.sync.read(data);
|
||||
|
||||
var outpng = new PNG();
|
||||
PNG.adjustGamma(png);
|
||||
outpng.data = png.data;
|
||||
outpng.width = png.width;
|
||||
outpng.height = png.height;
|
||||
outpng.pack()
|
||||
.pipe(fs.createWriteStream(__dirname + '/outsync/' + file));
|
||||
}
|
||||
|
||||
fs.createReadStream(__dirname + '/in/' + file)
|
||||
.pipe(new PNG())
|
||||
.on('error', function(err) {
|
||||
|
|
@ -33,22 +45,10 @@ fs.readdir(__dirname + '/in/', function(err, files) {
|
|||
console.log("Error expected, parsed fine", file);
|
||||
}
|
||||
|
||||
if (this.gamma) {
|
||||
for (var y = 0; y < this.height; y++) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var idx = (this.width * y + x) << 2;
|
||||
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var sample = this.data[idx + i] / 255;
|
||||
sample = Math.pow(sample, 1 / 2.2 / this.gamma);
|
||||
this.data[idx + i] = Math.round(sample * 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.adjustGamma();
|
||||
|
||||
this.pack()
|
||||
.pipe(fs.createWriteStream(__dirname + '/out/' + file));
|
||||
.pipe(fs.createWriteStream(__dirname + '/out/' + file));
|
||||
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue