UNPKG

fsk-imgoptimize

Version:
144 lines (128 loc) 3.88 kB
'use strict'; var Stream = require('stream'); var Readable = Stream.Readable; var Writable = Stream.Writable; var util = require('util'); var PNG_CONSTANTS = require('./constants.js').png; util.inherits(ImageStream, Readable); var keys = Object.keys(Writable.prototype); for (var v = 0; v < keys.length; v++) { var method = keys[v]; if (!ImageStream.prototype[method]) ImageStream.prototype[method] = Writable.prototype[method]; } function ImageStream(path, options) { options = options || {}; Stream.call(this, options); Readable.call(this, options); console.log('111') console.dir(this._readableState ) this.writable = true; this.pos = options.hasOwnProperty('pos') ? options.pos : 0; this.buffers = []; this.buffer_length = 0; this._queue = []; this._chunks = {}; this.content = []; this.readSignature(); } ImageStream.prototype._read = function() { this.push(); }; ImageStream.prototype.write = function(data, encoding) { if (!this.writable) { this.emit('error', new Error('Stream not writable')); return; } if (!util.isBuffer(data)) { data = new Buffer(data, encoding, this._encoding); } this.buffers.push(data); this.buffer_length += data.length; this._parseTrunk(); }; ImageStream.prototype.readSignature = function() { this._queue.push({ length: 8, callback: this.parseSignature.bind(this) }); this._parseTrunk(); }; ImageStream.prototype.parseSignature = function(data) { if (PNG_CONSTANTS.PNG_SIGNATURE.every(function(o, n) { return o === data[n]; })) { this.content.push(data); this.push(data); this.readTrunkStart(); } else { this.emit('error', 'Invalid file signature'); } }; ImageStream.prototype.readTrunkStart = function() { this._queue.push({ length: 8, callback: this.parseTrunkStart.bind(this) }); this._parseTrunk(); }; ImageStream.prototype.parseTrunkStart = function(data) { var length = data.readUInt32BE(0); var type = data.readUInt32BE(4); var name = data.slice(4).toString(); var self = this; if (this._chunks[type]) { this.content.push(data); this.push(data); this._queue.push({ length: length + 4, callback: function(content) { self.content.push(content); this.push(content); self.readTrunkStart(); } }) } else { this._queue.push({ length: length + 4, callback: self.readTrunkStart.bind(self) }); } }; ImageStream.prototype.end = function(data, cb) { console.log(this.content); } ImageStream.prototype._parseTrunk = function() { console.log('start', this._queue[0] , this.buffers) while (this.buffer_length > 0 && this._queue && this._queue.length > 0) { var read = this._queue[0]; if (this.buffer_length >= read.length) { // ok we can meet some expectations this._queue.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.buffer_length -= read.length; read.callback.call(this, data); } else { // not enought data to satisfy first request in queue // so we need to wait for more break; } } } var fs = require('fs'); fs.createReadStream('iBtn.png').pipe(new ImageStream()).pipe(fs.createWriteStream('test.png'));