mirror of
https://github.com/danbulant/pngjs
synced 2026-06-20 06:51:46 +00:00
streams
This commit is contained in:
parent
43a7c3dc4e
commit
14b9f6ddcf
14 changed files with 533 additions and 347 deletions
|
|
@ -24,7 +24,7 @@ png.on('parsed', function() {
|
|||
}
|
||||
}
|
||||
|
||||
png.pack();
|
||||
png.pack().pipe(dst);
|
||||
});
|
||||
|
||||
src.pipe(png).pipe(dst);
|
||||
src.pipe(png);
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs'),
|
||||
PNG = require('../lib/png').PNG;
|
||||
|
||||
|
||||
fs.readFile(process.argv[2], function(err, data) {
|
||||
if (err) throw err;
|
||||
|
||||
var png = new PNG();
|
||||
png.parse(data, function(err) {
|
||||
if (err) console.log(err.stack);
|
||||
|
||||
for (var y = 0; y < png.height; y++) {
|
||||
for (var x = 0; x < png.width; x++) {
|
||||
var idx = (png.width * y + x) << 2;
|
||||
|
||||
// invert color
|
||||
png.data[idx] = 255 - png.data[idx];
|
||||
png.data[idx+1] = 255 - png.data[idx+1];
|
||||
png.data[idx+2] = 255 - png.data[idx+2];
|
||||
|
||||
// and reduce opacity
|
||||
png.data[idx+3] = png.data[idx+3] >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
png.pipe(fs.createWriteStream(process.argv[3] || 'out.png'));
|
||||
png.pack();
|
||||
});
|
||||
});
|
||||
|
|
@ -24,5 +24,4 @@ for (var y = 0; y < png.height; y++) {
|
|||
}
|
||||
}
|
||||
|
||||
png.pipe(fs.createWriteStream('bg.png'));
|
||||
png.pack();
|
||||
png.pack().pipe(fs.createWriteStream(__dirname + '/bg.png'));
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 95 B After Width: | Height: | Size: 93 B |
0
examples/test/list.html
Normal file → Executable file
0
examples/test/list.html
Normal file → Executable file
17
examples/test/test.js
Normal file → Executable file
17
examples/test/test.js
Normal file → Executable file
|
|
@ -6,12 +6,12 @@ var fs = require('fs'),
|
|||
fs.readdir(__dirname + '/img/', function(err, files) {
|
||||
if (err) throw err;
|
||||
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
files.forEach(function(file) {
|
||||
|
||||
if (!files[i].match(/\.png$/i))
|
||||
continue;
|
||||
if (!file.match(/\.png$/i))
|
||||
return;
|
||||
|
||||
fs.createReadStream(__dirname + '/img/' + files[i])
|
||||
fs.createReadStream(__dirname + '/img/' + file)
|
||||
.pipe(new PNG())
|
||||
.on('parsed', function() {
|
||||
|
||||
|
|
@ -29,7 +29,10 @@ fs.readdir(__dirname + '/img/', function(err, files) {
|
|||
}
|
||||
}
|
||||
|
||||
this.pack();
|
||||
}).pipe(fs.createWriteStream(__dirname + '/out/' + files[i]));
|
||||
}
|
||||
this.pack()
|
||||
.pipe(fs.createWriteStream(__dirname + '/out/' + file));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
|||
199
lib/chunkstream.js
Executable file
199
lib/chunkstream.js
Executable file
|
|
@ -0,0 +1,199 @@
|
|||
// 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'),
|
||||
Stream = require('stream');
|
||||
|
||||
|
||||
var ChunkStream = module.exports = function() {
|
||||
Stream.call(this);
|
||||
|
||||
this._buffers = [];
|
||||
this._buffered = 0;
|
||||
|
||||
this._reads = [];
|
||||
this._paused = false;
|
||||
|
||||
this._encoding = 'utf8';
|
||||
this.writable = true;
|
||||
};
|
||||
util.inherits(ChunkStream, Stream);
|
||||
|
||||
|
||||
ChunkStream.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
|
||||
});
|
||||
|
||||
this._process();
|
||||
|
||||
// its paused and there is not enought data then ask for more
|
||||
if (this._paused && this._reads.length > 0) {
|
||||
this._paused = false;
|
||||
|
||||
this.emit('drain');
|
||||
}
|
||||
};
|
||||
|
||||
ChunkStream.prototype.write = function(data, encoding) {
|
||||
|
||||
if (!this.writable) {
|
||||
this.emit('error', new Error('Stream not writable'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Buffer.isBuffer(data))
|
||||
data = new Buffer(data, encoding || this._encoding);
|
||||
|
||||
this._buffers.push(data);
|
||||
this._buffered += data.length;
|
||||
|
||||
this._process();
|
||||
|
||||
// ok if there are no more read requests
|
||||
if (this._reads && this._reads.length == 0)
|
||||
this._paused = true;
|
||||
|
||||
return this.writable && !this._paused;
|
||||
};
|
||||
|
||||
ChunkStream.prototype.end = function(data, encoding) {
|
||||
|
||||
if (!this.writable) {
|
||||
this.emit('error', new Error('Stream not writable'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data) this.write(data, encoding);
|
||||
|
||||
this.writable = false;
|
||||
|
||||
if (this._buffers.length == 0) {
|
||||
this._end();
|
||||
} else {
|
||||
this._buffers.push(null);
|
||||
this._process();
|
||||
}
|
||||
};
|
||||
|
||||
ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
|
||||
|
||||
ChunkStream.prototype._end = function() {
|
||||
|
||||
if (this._reads.length > 0) {
|
||||
this.emit('error',
|
||||
new Error('There are some read requests waitng on finished stream')
|
||||
);
|
||||
}
|
||||
|
||||
this.destroy();
|
||||
};
|
||||
|
||||
ChunkStream.prototype.destroy = function() {
|
||||
|
||||
if (!this._buffers) return;
|
||||
|
||||
this.writable = false;
|
||||
this._reads = null;
|
||||
this._buffers = null;
|
||||
|
||||
this.emit('close');
|
||||
};
|
||||
|
||||
ChunkStream.prototype._process = function() {
|
||||
|
||||
// as long as there is any data and read requests
|
||||
while (this._buffered > 0 && this._reads.length > 0) {
|
||||
|
||||
var read = this._reads[0];
|
||||
|
||||
// read any data (but no more than length)
|
||||
if (read.allowLess) {
|
||||
|
||||
// ok there is any data so that we can satisfy this request
|
||||
this._reads.shift(); // == read
|
||||
|
||||
// first we need to peek into first buffer
|
||||
var buf = this._buffers[0];
|
||||
|
||||
// ok there is more data than we need
|
||||
if (buf.length > read.length) {
|
||||
|
||||
this._buffered -= read.length;
|
||||
this._buffers[0] = buf.slice(read.length);
|
||||
|
||||
read.func.call(this, buf.slice(0, read.length));
|
||||
|
||||
} else {
|
||||
// ok this is less than maximum length so use it all
|
||||
this._buffered -= buf.length;
|
||||
this._buffers.shift(); // == buf
|
||||
|
||||
read.func.call(this, buf);
|
||||
}
|
||||
|
||||
} else if (this._buffered >= read.length) {
|
||||
// ok we can meet some expectations
|
||||
|
||||
this._reads.shift(); // == read
|
||||
|
||||
var pos = 0,
|
||||
count = 0,
|
||||
data = new Buffer(read.length);
|
||||
|
||||
// create buffer for all data
|
||||
while (pos < read.length) {
|
||||
|
||||
var buf = this._buffers[count++],
|
||||
len = Math.min(buf.length, read.length - pos);
|
||||
|
||||
buf.copy(data, pos, 0, len);
|
||||
pos += len;
|
||||
|
||||
// last buffer wasn't used all so just slice it and leave
|
||||
if (len != buf.length)
|
||||
this._buffers[--count] = buf.slice(len);
|
||||
}
|
||||
|
||||
// remove all used buffers
|
||||
if (count > 0)
|
||||
this._buffers.splice(0, count);
|
||||
|
||||
this._buffered -= read.length;
|
||||
|
||||
read.func.call(this, data);
|
||||
|
||||
} else {
|
||||
// not enought data to satisfy first request in queue
|
||||
// so we need to wait for more
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._buffers && this._buffers.length > 0 && this._buffers[0] == null) {
|
||||
this._end();
|
||||
}
|
||||
};
|
||||
0
lib/constants.js
Normal file → Executable file
0
lib/constants.js
Normal file → Executable file
52
lib/helpers.js → lib/crc.js
Normal file → Executable file
52
lib/helpers.js → lib/crc.js
Normal file → Executable file
|
|
@ -20,6 +20,49 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var util = require('util'),
|
||||
Stream = require('stream');
|
||||
|
||||
|
||||
var CrcStream = module.exports = function() {
|
||||
Stream.call(this);
|
||||
|
||||
this._crc = -1;
|
||||
|
||||
this.writable = true;
|
||||
};
|
||||
util.inherits(CrcStream, Stream);
|
||||
|
||||
|
||||
CrcStream.prototype.write = function(data) {
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
CrcStream.prototype.end = function(data) {
|
||||
if (data) this.write(data);
|
||||
|
||||
this.emit('crc', this.crc32());
|
||||
};
|
||||
|
||||
CrcStream.prototype.crc32 = function() {
|
||||
return this._crc ^ -1;
|
||||
};
|
||||
|
||||
|
||||
CrcStream.crc32 = function(buf) {
|
||||
|
||||
var crc = -1;
|
||||
for (var i = 0; i < buf.length; i++) {
|
||||
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
|
||||
}
|
||||
return crc ^ -1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
var crcTable = [];
|
||||
|
||||
|
|
@ -34,12 +77,3 @@ for (var i = 0; i < 256; i++) {
|
|||
}
|
||||
crcTable[i] = c;
|
||||
}
|
||||
|
||||
exports.crc32 = function(buf) {
|
||||
|
||||
var crc = -1;
|
||||
for (var i = 0; i < buf.length; i++) {
|
||||
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
|
||||
}
|
||||
return crc ^ -1;
|
||||
};
|
||||
237
lib/filter.js
Normal file → Executable file
237
lib/filter.js
Normal file → Executable file
|
|
@ -22,17 +22,21 @@
|
|||
|
||||
var util = require('util'),
|
||||
zlib = require('zlib'),
|
||||
events = require('events');
|
||||
ChunkStream = require('./chunkstream');
|
||||
|
||||
|
||||
var Filter = module.exports = function(options) {
|
||||
events.EventEmitter.call(this);
|
||||
var Filter = module.exports = function(width, height, Bpp, data, options) {
|
||||
ChunkStream.call(this);
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._Bpp = Bpp;
|
||||
this._data = data;
|
||||
this._options = options;
|
||||
options.filterType = 'filterType' in options ? options.filterType : -1;
|
||||
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
this._line = 0;
|
||||
|
||||
options.filterType = 'filterType' in options ? options.filterType : -1;
|
||||
|
||||
this._filters = {
|
||||
0: this._filterNone.bind(this),
|
||||
|
|
@ -42,134 +46,135 @@ var Filter = module.exports = function(options) {
|
|||
4: this._filterPaeth.bind(this)
|
||||
};
|
||||
|
||||
this.read(this._width * Bpp + 1, this._reverseFilterLine.bind(this));
|
||||
};
|
||||
util.inherits(Filter, events.EventEmitter);
|
||||
util.inherits(Filter, ChunkStream);
|
||||
|
||||
|
||||
Filter.prototype.prepare = function(width, height, type) {
|
||||
|
||||
if (type != 0)
|
||||
throw new Error('Unsupported filter method');
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
var pixelBppMap = {
|
||||
1: { // L
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0xff,
|
||||
},
|
||||
2: { // LA
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 1
|
||||
},
|
||||
3: { // RGB
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 0xff
|
||||
},
|
||||
4: { // RGBA
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3
|
||||
}
|
||||
};
|
||||
|
||||
Filter.prototype.unfilter = function(rawData, Bpp) {
|
||||
Filter.prototype._reverseFilterLine = function(rawData) {
|
||||
|
||||
var pxLineLength = this.width << 2,
|
||||
rawLineLength = this.width * Bpp + 1,
|
||||
pxData = new Buffer(pxLineLength * this.height);
|
||||
var pxData = this._data,
|
||||
pxLineLength = this._width << 2,
|
||||
pxRowPos = this._line * pxLineLength,
|
||||
filter = rawData[0];
|
||||
|
||||
for (var y = 0; y < this.height; y++) {
|
||||
if (filter == 0) {
|
||||
for (var x = 0; x < this._width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = 1 + x * this._Bpp;
|
||||
|
||||
var rawRowPos = rawLineLength * y + 1,
|
||||
pxRowPos = y * pxLineLength,
|
||||
filter = rawData[rawRowPos - 1];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var idx = pixelBppMap[this._Bpp][i];
|
||||
pxData[pxPos + i] = idx != 0xff ? rawData[rawPos + idx] : 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (filter == 1) {
|
||||
for (var x = 0; x < this._width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = 1 + x * this._Bpp;
|
||||
|
||||
if (filter == 0) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = rawRowPos + x * Bpp;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var idx = pixelBppMap[this._Bpp][i],
|
||||
left = x > 0 ? pxData[pxPos + i - 4] : 0;
|
||||
|
||||
for (var i = 0; i < Bpp; i++)
|
||||
pxData[pxPos + i] = rawData[rawPos + i];
|
||||
pxData[pxPos + i] = idx != 0xff ? rawData[rawPos + idx] + left : 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (filter == 2) {
|
||||
for (var x = 0; x < this._width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = 1 + x * this._Bpp;
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var idx = pixelBppMap[this._Bpp][i],
|
||||
up = this._line > 0 ? pxData[pxPos - pxLineLength + i] : 0;
|
||||
|
||||
pxData[pxPos + i] = idx != 0xff ? rawData[rawPos + idx] + up : 0xff;
|
||||
}
|
||||
|
||||
} else if (filter == 1) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = rawRowPos + x * Bpp;
|
||||
}
|
||||
|
||||
for (var i = 0; i < Bpp; i++) {
|
||||
var left = x > 0 ? pxData[pxPos + i - 4] : 0;
|
||||
pxData[pxPos + i] = rawData[rawPos + i] + left;
|
||||
}
|
||||
} else if (filter == 3) {
|
||||
for (var x = 0; x < this._width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = 1 + x * this._Bpp;
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var idx = pixelBppMap[this._Bpp][i],
|
||||
left = x > 0 ? pxData[pxPos + i - 4] : 0,
|
||||
up = this._line > 0 ? pxData[pxPos - pxLineLength + i] : 0,
|
||||
add = Math.floor((left + up) / 2);
|
||||
|
||||
pxData[pxPos + i] = idx != 0xff ? rawData[rawPos + idx] + add : 0xff;
|
||||
}
|
||||
|
||||
} else if (filter == 2) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = rawRowPos + x * Bpp;
|
||||
}
|
||||
|
||||
for (var i = 0; i < Bpp; i++) {
|
||||
var up = y > 0 ? pxData[pxPos - pxLineLength + i] : 0;
|
||||
pxData[pxPos + i] = rawData[rawPos + i] + up;
|
||||
}
|
||||
}
|
||||
} else if (filter == 4) {
|
||||
for (var x = 0; x < this._width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = 1 + x * this._Bpp;
|
||||
|
||||
} else if (filter == 3) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = rawRowPos + x * Bpp;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var idx = pixelBppMap[this._Bpp][i],
|
||||
left = x > 0 ? pxData[pxPos + i - 4] : 0,
|
||||
up = this._line > 0 ? pxData[pxPos - pxLineLength + i] : 0,
|
||||
upLeft = x > 0 && this._line > 0
|
||||
? pxData[pxPos - pxLineLength + i - 4] : 0,
|
||||
add = PaethPredictor(left, up, upLeft);
|
||||
|
||||
for (var i = 0; i < Bpp; i++) {
|
||||
var left = x > 0 ? pxData[pxPos + i - 4] : 0,
|
||||
up = y > 0 ? pxData[pxPos - pxLineLength + i] : 0;
|
||||
|
||||
pxData[pxPos + i] = rawData[rawPos + i]
|
||||
+ Math.floor((left + up) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (filter == 4) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
rawPos = rawRowPos + x * Bpp;
|
||||
|
||||
for (var i = 0; i < Bpp; i++) {
|
||||
var left = x > 0 ? pxData[pxPos + i - 4] : 0,
|
||||
up = y > 0 ? pxData[pxPos - pxLineLength + i] : 0,
|
||||
upLeft = x > 0 && y > 0
|
||||
? pxData[pxPos - pxLineLength + i - 4] : 0;
|
||||
|
||||
pxData[pxPos + i] = rawData[rawPos + i]
|
||||
+ PaethPredictor(left, up, upLeft)
|
||||
}
|
||||
pxData[pxPos + i] = idx != 0xff ? rawData[rawPos + idx] + add : 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// expand data to 32 bit
|
||||
for (var y = 0; y < this.height; y++) {
|
||||
var pxRowPos = y * pxLineLength;
|
||||
|
||||
if (Bpp == 1) { // L
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2);
|
||||
this._line++;
|
||||
|
||||
pxData[pxPos + 1] = pxData[pxPos + 2] = pxData[pxPos];
|
||||
pxData[pxPos + 3] = 0xff;
|
||||
}
|
||||
|
||||
} else if (Bpp == 2) { // LA
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2);
|
||||
|
||||
pxData[pxPos + 3] = pxData[pxPos + 1];
|
||||
pxData[pxPos + 1] = pxData[pxPos + 2] = pxData[pxPos];
|
||||
}
|
||||
|
||||
} else if (Bpp == 3) { // RGB
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2);
|
||||
|
||||
pxData[pxPos + 3] = 0xff;
|
||||
}
|
||||
|
||||
} // else RGBA
|
||||
}
|
||||
|
||||
return pxData;
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
Filter.prototype.filter = function(pxData, width, height) {
|
||||
|
||||
var rawData = new Buffer(((width << 2) + 1) * height);
|
||||
|
||||
for (var y = 0; y < height; y++) {
|
||||
Filter.prototype.filter = function() {
|
||||
|
||||
var pxData = this._data,
|
||||
rawData = new Buffer(((this._width << 2) + 1) * this._height);
|
||||
|
||||
for (var y = 0; y < this._height; y++) {
|
||||
|
||||
// find best filter for this line (with lowest sum of values)
|
||||
if (this._options.filterType == -1) {
|
||||
|
|
@ -177,7 +182,7 @@ Filter.prototype.filter = function(pxData, width, height) {
|
|||
sel = 0;
|
||||
|
||||
for (var f in this._filters) {
|
||||
var sum = this._filters[f](pxData, y, width, height, null);
|
||||
var sum = this._filters[f](pxData, y, null);
|
||||
if (sum < min) {
|
||||
sel = f;
|
||||
min = sum;
|
||||
|
|
@ -187,14 +192,14 @@ Filter.prototype.filter = function(pxData, width, height) {
|
|||
} else {
|
||||
sel = this._options.filterType;
|
||||
}
|
||||
this._filters[sel](pxData, y, width, height, rawData);
|
||||
this._filters[sel](pxData, y, rawData);
|
||||
}
|
||||
return rawData;
|
||||
};
|
||||
|
||||
Filter.prototype._filterNone = function(pxData, y, width, height, rawData) {
|
||||
Filter.prototype._filterNone = function(pxData, y, rawData) {
|
||||
|
||||
var pxRowLength = width << 2,
|
||||
var pxRowLength = this._width << 2,
|
||||
rawRowLength = pxRowLength + 1,
|
||||
sum = 0;
|
||||
|
||||
|
|
@ -210,9 +215,9 @@ Filter.prototype._filterNone = function(pxData, y, width, height, rawData) {
|
|||
return sum;
|
||||
};
|
||||
|
||||
Filter.prototype._filterSub = function(pxData, y, width, height, rawData) {
|
||||
Filter.prototype._filterSub = function(pxData, y, rawData) {
|
||||
|
||||
var pxRowLength = width << 2,
|
||||
var pxRowLength = this._width << 2,
|
||||
rawRowLength = pxRowLength + 1,
|
||||
sum = 0;
|
||||
|
||||
|
|
@ -230,9 +235,9 @@ Filter.prototype._filterSub = function(pxData, y, width, height, rawData) {
|
|||
return sum;
|
||||
};
|
||||
|
||||
Filter.prototype._filterUp = function(pxData, y, width, height, rawData) {
|
||||
Filter.prototype._filterUp = function(pxData, y, rawData) {
|
||||
|
||||
var pxRowLength = width << 2,
|
||||
var pxRowLength = this._width << 2,
|
||||
rawRowLength = pxRowLength + 1,
|
||||
sum = 0;
|
||||
|
||||
|
|
@ -250,9 +255,9 @@ Filter.prototype._filterUp = function(pxData, y, width, height, rawData) {
|
|||
return sum;
|
||||
};
|
||||
|
||||
Filter.prototype._filterAvg = function(pxData, y, width, height, rawData) {
|
||||
Filter.prototype._filterAvg = function(pxData, y, rawData) {
|
||||
|
||||
var pxRowLength = width << 2,
|
||||
var pxRowLength = this._width << 2,
|
||||
rawRowLength = pxRowLength + 1,
|
||||
sum = 0;
|
||||
|
||||
|
|
@ -271,9 +276,9 @@ Filter.prototype._filterAvg = function(pxData, y, width, height, rawData) {
|
|||
return sum;
|
||||
};
|
||||
|
||||
Filter.prototype._filterPaeth = function(pxData, y, width, height, rawData) {
|
||||
Filter.prototype._filterPaeth = function(pxData, y, rawData) {
|
||||
|
||||
var pxRowLength = width << 2,
|
||||
var pxRowLength = this._width << 2,
|
||||
rawRowLength = pxRowLength + 1,
|
||||
sum = 0;
|
||||
|
||||
|
|
|
|||
66
lib/packer.js
Normal file → Executable file
66
lib/packer.js
Normal file → Executable file
|
|
@ -23,45 +23,55 @@
|
|||
|
||||
var util = require('util'),
|
||||
Stream = require('stream'),
|
||||
Compress = require('./compress'),
|
||||
Filter = require('./filter');
|
||||
zlib = require('zlib'),
|
||||
Filter = require('./filter'),
|
||||
CrcStream = require('./crc'),
|
||||
constants = require('./constants');
|
||||
|
||||
|
||||
var Parser = module.exports = function(options) {
|
||||
var Packer = module.exports = function(options) {
|
||||
Stream.call(this);
|
||||
|
||||
this._options = options;
|
||||
|
||||
// this._compress = new Compress(options);
|
||||
// this._compress.on('error', this.emit.bind(this, 'error'));
|
||||
// this._compress.on('deflated', this._packData.bind(this));
|
||||
options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
|
||||
options.deflateLevel = options.deflateLevel || 9;
|
||||
|
||||
this.readable = true;
|
||||
};
|
||||
util.inherits(Parser, Stream);
|
||||
util.inherits(Packer, Stream);
|
||||
|
||||
|
||||
Parser.prototype._pack = function(width, height, data) {
|
||||
Packer.prototype.pack = function(data, width, height) {
|
||||
|
||||
// Signature
|
||||
this.emit('data', new Buffer(signature));
|
||||
this.emit('data', new Buffer(constants.PNG_SIGNATURE));
|
||||
this.emit('data', this._packIHDR(width, height));
|
||||
|
||||
// filter pixel data
|
||||
var data = this._filter.filter(data, width, height);
|
||||
var filter = new Filter(width, height, 4, data, this._options);
|
||||
var data = filter.filter();
|
||||
|
||||
// compress it
|
||||
this._compress.deflate(data);
|
||||
var deflate = zlib.createDeflate({
|
||||
chunkSize: this._options.deflateChunkSize,
|
||||
level: this._options.deflateLevel
|
||||
});
|
||||
deflate.on('error', this.emit.bind(this, 'error'));
|
||||
|
||||
deflate.on('data', function(data) {
|
||||
this.emit('data', this._packIDAT(data));
|
||||
}.bind(this));
|
||||
|
||||
deflate.on('end', function() {
|
||||
this.emit('data', this._packIEND());
|
||||
this.emit('end');
|
||||
}.bind(this));
|
||||
|
||||
deflate.end(data);
|
||||
};
|
||||
|
||||
Parser.prototype._packData = function(data) {
|
||||
|
||||
// console.log('deflate', data.length);
|
||||
|
||||
this.emit('data', this._packIDAT(data));
|
||||
this.emit('data', this._packIEND());
|
||||
this.emit('end');
|
||||
};
|
||||
|
||||
Parser.prototype._packChunk = function(type, data) {
|
||||
Packer.prototype._packChunk = function(type, data) {
|
||||
|
||||
var len = (data ? data.length : 0),
|
||||
buf = new Buffer(len + 12);
|
||||
|
|
@ -71,11 +81,11 @@ Parser.prototype._packChunk = function(type, data) {
|
|||
|
||||
if (data) data.copy(buf, 8);
|
||||
|
||||
buf.writeInt32BE(crc32(buf.slice(4, buf.length - 4)), buf.length - 4);
|
||||
buf.writeInt32BE(CrcStream.crc32(buf.slice(4, buf.length - 4)), buf.length - 4);
|
||||
return buf;
|
||||
};
|
||||
|
||||
Parser.prototype._packIHDR = function(width, height) {
|
||||
Packer.prototype._packIHDR = function(width, height) {
|
||||
|
||||
var buf = new Buffer(13);
|
||||
buf.writeUInt32BE(width, 0);
|
||||
|
|
@ -86,13 +96,13 @@ Parser.prototype._packIHDR = function(width, height) {
|
|||
buf[11] = 0; // filter
|
||||
buf[12] = 0; // interlace
|
||||
|
||||
return this._packChunk(TYPE_IHDR, buf);
|
||||
return this._packChunk(constants.TYPE_IHDR, buf);
|
||||
};
|
||||
|
||||
Parser.prototype._packIDAT = function(data) {
|
||||
return this._packChunk(TYPE_IDAT, data);
|
||||
Packer.prototype._packIDAT = function(data) {
|
||||
return this._packChunk(constants.TYPE_IDAT, data);
|
||||
};
|
||||
|
||||
Parser.prototype._packIEND = function() {
|
||||
return this._packChunk(TYPE_IEND, null);
|
||||
Packer.prototype._packIEND = function() {
|
||||
return this._packChunk(constants.TYPE_IEND, null);
|
||||
};
|
||||
|
|
|
|||
163
lib/parser.js
Normal file → Executable file
163
lib/parser.js
Normal file → Executable file
|
|
@ -22,15 +22,15 @@
|
|||
|
||||
|
||||
var util = require('util'),
|
||||
Stream = require('stream'),
|
||||
zlib = require('zlib'),
|
||||
helpers = require('./helpers'),
|
||||
CrcStream = require('./crc'),
|
||||
ChunkStream = require('./chunkstream'),
|
||||
constants = require('./constants'),
|
||||
Filter = require('./filter');
|
||||
|
||||
|
||||
var Parser = module.exports = function(options) {
|
||||
Stream.call(this);
|
||||
ChunkStream.call(this);
|
||||
|
||||
this._options = options;
|
||||
options.checkCRC = options.checkCRC !== false;
|
||||
|
|
@ -38,14 +38,13 @@ var Parser = module.exports = function(options) {
|
|||
this._hasIHDR = false;
|
||||
this._hasIEND = false;
|
||||
|
||||
this._stream = new ReadStream();
|
||||
this._inflate = null;
|
||||
this._filter = null;
|
||||
this._crc = null;
|
||||
|
||||
// input flags/metadata
|
||||
this._palette = [];
|
||||
this._colorType = 0;
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
|
||||
this._chunks = {};
|
||||
this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this);
|
||||
|
|
@ -58,31 +57,23 @@ var Parser = module.exports = function(options) {
|
|||
this.writable = true;
|
||||
|
||||
this.on('error', this._handleError.bind(this));
|
||||
|
||||
this._handleSignature();
|
||||
};
|
||||
util.inherits(Parser, Stream);
|
||||
util.inherits(Parser, ChunkStream);
|
||||
|
||||
|
||||
Parser.prototype.write = function(data) {
|
||||
this._stream.write(data);
|
||||
};
|
||||
|
||||
Parser.prototype.end = function(data) {
|
||||
this._stream.end(data);
|
||||
};
|
||||
|
||||
Parser.prototype._handleError = function() {
|
||||
|
||||
this.writable = false;
|
||||
this._stream.destroy();
|
||||
|
||||
this.destroy();
|
||||
|
||||
if (this._inflate)
|
||||
this._inflate.destroy();
|
||||
};
|
||||
|
||||
Parser.prototype._handleSignature = function() {
|
||||
this._stream.read(constants.PNG_SIGNATURE.length,
|
||||
this.read(constants.PNG_SIGNATURE.length,
|
||||
this._parseSignature.bind(this)
|
||||
);
|
||||
};
|
||||
|
|
@ -91,13 +82,13 @@ Parser.prototype._parseSignature = function(data) {
|
|||
|
||||
var signature = constants.PNG_SIGNATURE;
|
||||
|
||||
for (var i = 0; i < signature.length; i++)
|
||||
for (var i = 0; i < signature.length; i++) {
|
||||
if (data[i] != signature[i]) {
|
||||
this.emit('error', new Error('Invalid file signature'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._stream.read(8, this._parseChunkBegin.bind(this));
|
||||
this.read(8, this._parseChunkBegin.bind(this));
|
||||
};
|
||||
|
||||
Parser.prototype._parseChunkBegin = function(data) {
|
||||
|
|
@ -111,6 +102,8 @@ Parser.prototype._parseChunkBegin = function(data) {
|
|||
for (var i = 4; i < 8; i++)
|
||||
name += String.fromCharCode(data[i]);
|
||||
|
||||
// console.log('chunk ', name, length);
|
||||
|
||||
// chunk flags
|
||||
var ancillary = !!(data[4] & 0x20), // or critical
|
||||
priv = !!(data[5] & 0x20), // or public
|
||||
|
|
@ -121,52 +114,55 @@ Parser.prototype._parseChunkBegin = function(data) {
|
|||
return;
|
||||
}
|
||||
|
||||
this._crc = new CrcStream();
|
||||
this._crc.write(new Buffer(name));
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
Parser.prototype._skipChunk = function(data) {
|
||||
this.read(8, this._parseChunkBegin.bind(this));
|
||||
};
|
||||
|
||||
Parser.prototype._handleChunkEnd = function() {
|
||||
this._stream.read(4, this._parseChunkEnd.bind(this));
|
||||
this.read(4, this._parseChunkEnd.bind(this));
|
||||
};
|
||||
|
||||
Parser.prototype._parseChunkEnd = function(data) {
|
||||
|
||||
var fileCrc = data.readInt32BE(0);
|
||||
var fileCrc = data.readInt32BE(0),
|
||||
calcCrc = this._crc.crc32();
|
||||
|
||||
// // calc CRC (of chunk type and content)
|
||||
// var calcCrc = helpers.crc32(data.slice(idx - 4, idx + length)),
|
||||
// content = data.slice(idx, idx + length);
|
||||
// idx += length;
|
||||
|
||||
// // read CRC
|
||||
// var fileCrc = data.readInt32BE(idx);
|
||||
// idx += 4;
|
||||
|
||||
// // and check CRC
|
||||
// if (this._options.checkCRC && calcCrc != fileCrc)
|
||||
// throw new Error('Crc error');
|
||||
|
||||
// TODO: calc crc on stream
|
||||
// check CRC
|
||||
if (this._options.checkCRC && calcCrc != fileCrc) {
|
||||
this.emit('error', new Error('Crc error'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._hasIEND) {
|
||||
this._stream.destroy();
|
||||
this.destroySoon();
|
||||
|
||||
} else {
|
||||
this._stream.read(8, this._parseChunkBegin.bind(this));
|
||||
this.read(8, this._parseChunkBegin.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Parser.prototype._handleIHDR = function(length) {
|
||||
this._stream.read(length, this._parseIHDR.bind(this));
|
||||
this.read(length, this._parseIHDR.bind(this));
|
||||
};
|
||||
Parser.prototype._parseIHDR = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
|
||||
var width = data.readUInt32BE(0),
|
||||
height = data.readUInt32BE(4),
|
||||
depth = data[8],
|
||||
|
|
@ -175,15 +171,19 @@ Parser.prototype._parseIHDR = function(data) {
|
|||
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;
|
||||
|
|
@ -198,8 +198,15 @@ Parser.prototype._parseIHDR = function(data) {
|
|||
}
|
||||
|
||||
this._colorType = colorType;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
this._data = new Buffer(width * height * 4);
|
||||
this._filter = new Filter(
|
||||
width, height,
|
||||
colorTypeToBppMap[this._colorType],
|
||||
this._data,
|
||||
this._options
|
||||
);
|
||||
|
||||
this._hasIHDR = true;
|
||||
|
||||
this.emit('metadata', {
|
||||
|
|
@ -207,7 +214,8 @@ Parser.prototype._parseIHDR = function(data) {
|
|||
height: height,
|
||||
palette: !!(colorType & constants.COLOR_PALETTE),
|
||||
color: !!(colorType & constants.COLOR_COLOR),
|
||||
alpha: !!(colorType & constants.COLOR_ALPHA)
|
||||
alpha: !!(colorType & constants.COLOR_ALPHA),
|
||||
data: this._data
|
||||
});
|
||||
|
||||
this._handleChunkEnd();
|
||||
|
|
@ -215,12 +223,14 @@ Parser.prototype._parseIHDR = function(data) {
|
|||
|
||||
|
||||
Parser.prototype._handlePLTE = function(length) {
|
||||
this._stream.read(length, this._parsePLTE.bind(this));
|
||||
this.read(length, this._parsePLTE.bind(this));
|
||||
};
|
||||
Parser.prototype._parsePLTE = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
|
||||
var entries = Math.floor(data.length / 3);
|
||||
console.log('Palette:', entries);
|
||||
// console.log('Palette:', entries);
|
||||
|
||||
for (var i = 0; i < entries; i++) {
|
||||
this._palette.push([
|
||||
|
|
@ -235,10 +245,12 @@ Parser.prototype._parsePLTE = function(data) {
|
|||
};
|
||||
|
||||
Parser.prototype._handleTRNS = function(length) {
|
||||
this._stream.read(length, this._parseTRNS.bind(this));
|
||||
this.read(length, this._parseTRNS.bind(this));
|
||||
};
|
||||
Parser.prototype._parseTRNS = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
|
||||
// palette
|
||||
if (this._colorType == 3) {
|
||||
if (this._palette.length == 0) {
|
||||
|
|
@ -261,19 +273,22 @@ Parser.prototype._parseTRNS = function(data) {
|
|||
};
|
||||
|
||||
Parser.prototype._handleGAMA = function(length) {
|
||||
this._stream.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._handleChunkEnd();
|
||||
};
|
||||
|
||||
Parser.prototype._handleIDAT = function(length) {
|
||||
this._stream.read(-length, this._parseIDAT.bind(this, length));
|
||||
this.read(-length, this._parseIDAT.bind(this, length));
|
||||
};
|
||||
Parser.prototype._parseIDAT = function(lenght, data) {
|
||||
Parser.prototype._parseIDAT = function(length, data) {
|
||||
|
||||
this._crc.write(data);
|
||||
|
||||
if (this._colorType == 3 && this._palette.length == 0)
|
||||
throw new Error('Expected palette not found');
|
||||
|
|
@ -282,7 +297,9 @@ Parser.prototype._parseIDAT = function(lenght, data) {
|
|||
this._inflate = zlib.createInflate();
|
||||
|
||||
this._inflate.on('error', this.emit.bind(this, 'error'));
|
||||
//this._inflate.pipe(filter);
|
||||
this._filter.on('complete', this._reverseFiltered.bind(this));
|
||||
|
||||
this._inflate.pipe(this._filter);
|
||||
}
|
||||
|
||||
this._inflate.write(data);
|
||||
|
|
@ -296,10 +313,12 @@ Parser.prototype._parseIDAT = function(lenght, data) {
|
|||
|
||||
|
||||
Parser.prototype._handleIEND = function(length) {
|
||||
this._stream.read(length, this._parseIEND.bind(this));
|
||||
this.read(length, this._parseIEND.bind(this));
|
||||
};
|
||||
Parser.prototype._parseIEND = function(data) {
|
||||
|
||||
this._crc.write(data);
|
||||
|
||||
// no more data to inflate
|
||||
this._inflate.end();
|
||||
|
||||
|
|
@ -308,26 +327,25 @@ Parser.prototype._parseIEND = function(data) {
|
|||
};
|
||||
|
||||
|
||||
var colorTypeToBppMap = {
|
||||
0: 1,
|
||||
2: 3,
|
||||
3: 1,
|
||||
4: 2,
|
||||
6: 4
|
||||
};
|
||||
|
||||
Parser.prototype._unfilter = function(data) {
|
||||
Parser.prototype._reverseFiltered = function(data, width, height) {
|
||||
|
||||
// expand data to 32 bit depending on colorType
|
||||
if (this._colorType == 0) { // L
|
||||
data = this._filter.unfilter(data, 1); // 1 Bpp
|
||||
if (this._colorType == 3) { // paletted
|
||||
|
||||
} else if (this._colorType == 2) { // RGB
|
||||
data = this._filter.unfilter(data, 3); // 3 Bpp
|
||||
// use values from palette
|
||||
var pxLineLength = width << 2;
|
||||
|
||||
} else if (this._colorType == 3) { // I
|
||||
data = this._filter.unfilter(data, 1); // 1 Bpp
|
||||
|
||||
// use values fom palette
|
||||
var pxLineLength = this.width << 2;
|
||||
|
||||
for (var y = 0; y < this.height; y++) {
|
||||
for (var y = 0; y < height; y++) {
|
||||
var pxRowPos = y * pxLineLength;
|
||||
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
for (var x = 0; x < width; x++) {
|
||||
var pxPos = pxRowPos + (x << 2),
|
||||
color = this._palette[data[pxPos]];
|
||||
|
||||
|
|
@ -335,14 +353,7 @@ Parser.prototype._unfilter = function(data) {
|
|||
data[pxPos + i] = color[i];
|
||||
}
|
||||
}
|
||||
|
||||
} else if (this._colorType == 4) { // LA
|
||||
data = this._filter.unfilter(data, 2); // 2 Bpp
|
||||
|
||||
} else if (this._colorType == 6) { // RGBA
|
||||
data = this._filter.unfilter(data, 4); // 4 Bpp
|
||||
|
||||
} else throw new Error('Unsupported color type');
|
||||
}
|
||||
|
||||
this.emit('parsed', data);
|
||||
};
|
||||
|
|
|
|||
53
lib/png.js
Normal file → Executable file
53
lib/png.js
Normal file → Executable file
|
|
@ -22,11 +22,15 @@
|
|||
|
||||
|
||||
var util = require('util'),
|
||||
Parser = require('./parser');
|
||||
Stream = require('stream'),
|
||||
Parser = require('./parser'),
|
||||
Packer = require('./packer');
|
||||
|
||||
|
||||
var PNG = exports.PNG = function(options) {
|
||||
Parser.call(this, options = options || {});
|
||||
Stream.call(this);
|
||||
|
||||
options = options || {};
|
||||
|
||||
this.width = options.width || 0;
|
||||
this.height = options.height || 0;
|
||||
|
|
@ -35,23 +39,34 @@ var PNG = exports.PNG = function(options) {
|
|||
? new Buffer(4 * this.width * this.height) : null;
|
||||
|
||||
this.gamma = 0;
|
||||
|
||||
this.readable = this.writable = true;
|
||||
this._buffers = [];
|
||||
this._buffLen = 0;
|
||||
|
||||
this.on('metadata', this._metadata.bind(this));
|
||||
this.on('gamma', this._gamma.bind(this));
|
||||
this._parser = new Parser(options || {});
|
||||
|
||||
this.on('parsed', function(data) {
|
||||
this._parser.on('error', this.emit.bind(this, 'error'));
|
||||
this._parser.on('close', this.emit.bind(this, 'close'));
|
||||
this._parser.on('metadata', this._metadata.bind(this));
|
||||
this._parser.on('gamma', this._gamma.bind(this));
|
||||
this._parser.on('parsed', function(data) {
|
||||
this.data = data;
|
||||
this.emit('parsed', data);
|
||||
}.bind(this));
|
||||
|
||||
this._packer = new Packer(options);
|
||||
this._packer.on('data', this.emit.bind(this, 'data'));
|
||||
this._packer.on('end', this.emit.bind(this, 'end'));
|
||||
this._packer.on('error', this.emit.bind(this, 'error'));
|
||||
|
||||
};
|
||||
util.inherits(PNG, Parser);
|
||||
util.inherits(PNG, Stream);
|
||||
|
||||
|
||||
PNG.prototype.pack = function() {
|
||||
this._pack(this.width, this.height, this.data);
|
||||
|
||||
process.nextTick(function() {
|
||||
this._packer.pack(this.data, this.width, this.height);
|
||||
}.bind(this));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
|
@ -76,27 +91,23 @@ PNG.prototype.parse = function(data, callback) {
|
|||
}.bind(this));
|
||||
}
|
||||
|
||||
this._parse(data);
|
||||
this.end(data);
|
||||
return this;
|
||||
};
|
||||
|
||||
PNG.prototype.write = function(data) {
|
||||
this._buffers.push(data);
|
||||
this._buffLen += data.length;
|
||||
this._parser.write(data);
|
||||
return true;
|
||||
};
|
||||
|
||||
PNG.prototype.end = function(data) {
|
||||
if (data) this.write(data);
|
||||
this._parse(Buffer.concat(this._buffers, this._buffLen));
|
||||
this._buffers = [];
|
||||
this._buffLen = 0;
|
||||
this._parser.end(data);
|
||||
};
|
||||
|
||||
PNG.prototype._metadata = function(width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.data = null;
|
||||
PNG.prototype._metadata = function(metadata) {
|
||||
this.width = metadata.width;
|
||||
this.height = metadata.height;
|
||||
this.data = metadata.data;
|
||||
};
|
||||
|
||||
PNG.prototype._gamma = function(gamma) {
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
// 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'),
|
||||
Stream = require('stream');
|
||||
|
||||
|
||||
var ReadStream = module.exports = function() {
|
||||
Stream.call(this);
|
||||
|
||||
|
||||
|
||||
this.writeable = true;
|
||||
};
|
||||
util.inherits(ReadStream, Stream);
|
||||
|
||||
|
||||
// length < 0 -> at most this length
|
||||
ReadStream.prototype.read = function(length, callback) {
|
||||
|
||||
};
|
||||
|
||||
ReadStream.prototype.destroy = function() {
|
||||
|
||||
};
|
||||
|
||||
|
||||
ReadStream.prototype.write = function(data) {
|
||||
|
||||
};
|
||||
|
||||
ReadStream.prototype.end = function(data) {
|
||||
|
||||
};
|
||||
|
||||
Loading…
Reference in a new issue