mirror of
https://github.com/danbulant/pngjs
synced 2026-07-08 04:30:33 +00:00
configure the rest of eslint.
This commit is contained in:
parent
8155d300f0
commit
bf5ae3c54e
16 changed files with 737 additions and 713 deletions
136
.eslintrc
136
.eslintrc
|
|
@ -2,10 +2,10 @@
|
||||||
"ecmaFeatures": {},
|
"ecmaFeatures": {},
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-alert": 2,
|
"no-alert": 2,
|
||||||
"no-array-constructor": 1,
|
"no-array-constructor": 0,
|
||||||
"no-bitwise": 0,
|
"no-bitwise": 0,
|
||||||
"no-caller": 2,
|
"no-caller": 2,
|
||||||
"no-catch-shadow": 1,
|
"no-catch-shadow": 2,
|
||||||
"no-class-assign": 2,
|
"no-class-assign": 2,
|
||||||
"no-cond-assign": 2,
|
"no-cond-assign": 2,
|
||||||
"no-console": 2,
|
"no-console": 2,
|
||||||
|
|
@ -26,15 +26,15 @@
|
||||||
"no-eq-null": 0,
|
"no-eq-null": 0,
|
||||||
"no-eval": 2,
|
"no-eval": 2,
|
||||||
"no-ex-assign": 2,
|
"no-ex-assign": 2,
|
||||||
"no-extend-native": 0,
|
"no-extend-native": 2,
|
||||||
"no-extra-bind": 1,
|
"no-extra-bind": 1,
|
||||||
"no-extra-boolean-cast": 2,
|
"no-extra-boolean-cast": 2,
|
||||||
"no-extra-parens": 0,
|
"no-extra-parens": 0,
|
||||||
"no-extra-semi": 2,
|
"no-extra-semi": 2,
|
||||||
"no-fallthrough": 2,
|
"no-fallthrough": 2,
|
||||||
"no-floating-decimal": 0,
|
"no-floating-decimal": 1,
|
||||||
"no-func-assign": 2,
|
"no-func-assign": 2,
|
||||||
"no-implicit-coercion": 0,
|
"no-implicit-coercion": 1,
|
||||||
"no-implied-eval": 1,
|
"no-implied-eval": 1,
|
||||||
"no-inline-comments": 0,
|
"no-inline-comments": 0,
|
||||||
"no-inner-declarations": [2, "functions"],
|
"no-inner-declarations": [2, "functions"],
|
||||||
|
|
@ -45,26 +45,26 @@
|
||||||
"no-label-var": 1,
|
"no-label-var": 1,
|
||||||
"no-labels": 1,
|
"no-labels": 1,
|
||||||
"no-lone-blocks": 1,
|
"no-lone-blocks": 1,
|
||||||
"no-lonely-if": 0,
|
"no-lonely-if": 1,
|
||||||
"no-loop-func": 1,
|
"no-loop-func": 1,
|
||||||
"no-mixed-requires": [0, false],
|
"no-mixed-requires": [1, false],
|
||||||
"no-mixed-spaces-and-tabs": [2, false],
|
"no-mixed-spaces-and-tabs": [2, false],
|
||||||
"linebreak-style": [0, "unix"],
|
"linebreak-style": [0, "unix"],
|
||||||
"no-multi-spaces": 1,
|
"no-multi-spaces": 1,
|
||||||
"no-multi-str": 0,
|
"no-multi-str": 0,
|
||||||
"no-multiple-empty-lines": [0, {"max": 2}],
|
"no-multiple-empty-lines": [1, {"max": 2}],
|
||||||
"no-native-reassign": 0,
|
"no-native-reassign": 2,
|
||||||
"no-negated-in-lhs": 2,
|
"no-negated-in-lhs": 2,
|
||||||
"no-nested-ternary": 0,
|
"no-nested-ternary": 1,
|
||||||
"no-new": 0,
|
"no-new": 1,
|
||||||
"no-new-func": 0,
|
"no-new-func": 1,
|
||||||
"no-new-object": 0,
|
"no-new-object": 1,
|
||||||
"no-new-require": 0,
|
"no-new-require": 1,
|
||||||
"no-new-wrappers": 0,
|
"no-new-wrappers": 1,
|
||||||
"no-obj-calls": 2,
|
"no-obj-calls": 2,
|
||||||
"no-octal": 2,
|
"no-octal": 2,
|
||||||
"no-octal-escape": 0,
|
"no-octal-escape": 0,
|
||||||
"no-param-reassign": 0,
|
"no-param-reassign": 1,
|
||||||
"no-path-concat": 0,
|
"no-path-concat": 0,
|
||||||
"no-plusplus": 0,
|
"no-plusplus": 0,
|
||||||
"no-process-env": 0,
|
"no-process-env": 0,
|
||||||
|
|
@ -73,23 +73,23 @@
|
||||||
"no-redeclare": 2,
|
"no-redeclare": 2,
|
||||||
"no-regex-spaces": 2,
|
"no-regex-spaces": 2,
|
||||||
"no-restricted-modules": 0,
|
"no-restricted-modules": 0,
|
||||||
"no-return-assign": 0,
|
"no-return-assign": 1,
|
||||||
"no-script-url": 0,
|
"no-script-url": 0,
|
||||||
"no-self-compare": 0,
|
"no-self-compare": 1,
|
||||||
"no-sequences": 0,
|
"no-sequences": 1,
|
||||||
"no-shadow": 1,
|
"no-shadow": 1,
|
||||||
"no-shadow-restricted-names": 0,
|
"no-shadow-restricted-names": 1,
|
||||||
"no-spaced-func": 1,
|
"no-spaced-func": 1,
|
||||||
"no-sparse-arrays": 2,
|
"no-sparse-arrays": 2,
|
||||||
"no-sync": 0,
|
"no-sync": 0,
|
||||||
"no-ternary": 0,
|
"no-ternary": 0,
|
||||||
"no-trailing-spaces": 1,
|
"no-trailing-spaces": 1,
|
||||||
"no-this-before-super": 0,
|
"no-this-before-super": 1,
|
||||||
"no-throw-literal": 0,
|
"no-throw-literal": 1,
|
||||||
"no-undef": 2,
|
"no-undef": 2,
|
||||||
"no-undef-init": 0,
|
"no-undef-init": 1,
|
||||||
"no-undefined": 0,
|
"no-undefined": 0,
|
||||||
"no-unexpected-multiline": 0,
|
"no-unexpected-multiline": 1,
|
||||||
"no-underscore-dangle": 0,
|
"no-underscore-dangle": 0,
|
||||||
"no-unneeded-ternary": 0,
|
"no-unneeded-ternary": 0,
|
||||||
"no-unreachable": 2,
|
"no-unreachable": 2,
|
||||||
|
|
@ -99,73 +99,75 @@
|
||||||
"no-useless-call": 2,
|
"no-useless-call": 2,
|
||||||
"no-void": 0,
|
"no-void": 0,
|
||||||
"no-var": 0,
|
"no-var": 0,
|
||||||
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
|
"no-warning-comments": [1, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
|
||||||
"no-with": 0,
|
"no-with": 1,
|
||||||
|
|
||||||
"array-bracket-spacing": [0, "never"],
|
"array-bracket-spacing": [1, "never"],
|
||||||
"arrow-parens": 0,
|
"arrow-parens": 1,
|
||||||
"arrow-spacing": 0,
|
"arrow-spacing": 1,
|
||||||
"accessor-pairs": 0,
|
"accessor-pairs": 1,
|
||||||
"block-scoped-var": 0,
|
"block-scoped-var": 0,
|
||||||
"brace-style": [0, "1tbs"],
|
"brace-style": [1, "1tbs"],
|
||||||
"callback-return": 0,
|
"callback-return": [2, ["callback", "cb", "next"]],
|
||||||
"camelcase": 0,
|
"camelcase": [2, {"properties": "always"}],
|
||||||
"comma-dangle": [2, "never"],
|
"comma-dangle": [2, "never"],
|
||||||
"comma-spacing": 0,
|
"comma-spacing": 2,
|
||||||
"comma-style": 0,
|
"comma-style": 1,
|
||||||
"complexity": [0, 11],
|
"complexity": [1, 10],
|
||||||
"computed-property-spacing": [0, "never"],
|
"computed-property-spacing": [0, "never"],
|
||||||
"consistent-return": 0,
|
"consistent-return": 0,
|
||||||
"consistent-this": [0, "that"],
|
"consistent-this": [0, "that"],
|
||||||
"constructor-super": 0,
|
"constructor-super": 1,
|
||||||
"curly": [0, "all"],
|
"curly": [1, "all"],
|
||||||
"default-case": 0,
|
"default-case": 1,
|
||||||
"dot-location": 0,
|
"dot-location": [1, "property"],
|
||||||
"dot-notation": [0, { "allowKeywords": true }],
|
"dot-notation": [1, { "allowKeywords": true }],
|
||||||
"eol-last": 0,
|
"eol-last": 0,
|
||||||
"eqeqeq": 0,
|
"eqeqeq": 1,
|
||||||
"func-names": 0,
|
"func-names": 0,
|
||||||
"func-style": [0, "declaration"],
|
"func-style": [0, "declaration"],
|
||||||
"generator-star-spacing": 0,
|
"generator-star-spacing": 0,
|
||||||
"guard-for-in": 0,
|
"guard-for-in": 1,
|
||||||
"handle-callback-err": 0,
|
"handle-callback-err": 2,
|
||||||
"id-length": 0,
|
"id-length": [2, {"min": 3, "max": 20, "exceptions":["x", "y", "i", "j"]}],
|
||||||
"indent": 0,
|
"indent": [1, 2, {"SwitchCase": 1}],
|
||||||
"init-declarations": 0,
|
"init-declarations": 0,
|
||||||
"key-spacing": [0, { "beforeColon": false, "afterColon": true }],
|
"key-spacing": [1, { "beforeColon": false, "afterColon": true }],
|
||||||
"lines-around-comment": 0,
|
"lines-around-comment": 0,
|
||||||
"max-depth": [0, 4],
|
"max-depth": [1, 4],
|
||||||
"max-len": [0, 80, 4],
|
"max-len": [1, 160, 2],
|
||||||
"max-nested-callbacks": [0, 2],
|
"max-nested-callbacks": [1, 2],
|
||||||
"max-params": [0, 3],
|
"max-params": [1, 5],
|
||||||
"max-statements": [0, 10],
|
"max-statements": [1, 30],
|
||||||
"new-cap": 0,
|
"new-cap": 1,
|
||||||
"new-parens": 0,
|
"new-parens": 1,
|
||||||
"newline-after-var": 0,
|
"newline-after-var": 0,
|
||||||
"object-curly-spacing": [0, "never"],
|
"object-curly-spacing": [1, "always"],
|
||||||
"object-shorthand": 0,
|
"object-shorthand": 0,
|
||||||
"one-var": 0,
|
"one-var": [1, {
|
||||||
|
"initialized": "never"
|
||||||
|
}],
|
||||||
"operator-assignment": [0, "always"],
|
"operator-assignment": [0, "always"],
|
||||||
"operator-linebreak": 0,
|
"operator-linebreak": [1, "after"],
|
||||||
"padded-blocks": 0,
|
"padded-blocks": 0,
|
||||||
"prefer-const": 0,
|
"prefer-const": 0,
|
||||||
"prefer-spread": 0,
|
"prefer-spread": 0,
|
||||||
"prefer-reflect": 0,
|
"prefer-reflect": 0,
|
||||||
"quote-props": 0,
|
"quote-props": 0,
|
||||||
"quotes": [0, "double"],
|
"quotes": [1, "single"],
|
||||||
"radix": 0,
|
"radix": 0,
|
||||||
"id-match": 0,
|
"id-match": 0,
|
||||||
"require-yield": 0,
|
"require-yield": 0,
|
||||||
"semi": 0,
|
"semi": [1, "always"],
|
||||||
"semi-spacing": [0, {"before": false, "after": true}],
|
"semi-spacing": [1, {"before": false, "after": true}],
|
||||||
"sort-vars": 0,
|
"sort-vars": 0,
|
||||||
"space-after-keywords": [0, "always"],
|
"space-after-keywords": [1, "always"],
|
||||||
"space-before-blocks": [0, "always"],
|
"space-before-blocks": [1, "always"],
|
||||||
"space-before-function-paren": [0, "always"],
|
"space-before-function-paren": [1, "never"],
|
||||||
"space-in-parens": [0, "never"],
|
"space-in-parens": [1, "never"],
|
||||||
"space-infix-ops": 0,
|
"space-infix-ops": 1,
|
||||||
"space-return-throw-case": 0,
|
"space-return-throw-case": 1,
|
||||||
"space-unary-ops": [0, { "words": true, "nonwords": false }],
|
"space-unary-ops": [1, { "words": true, "nonwords": false }],
|
||||||
"spaced-comment": 0,
|
"spaced-comment": 0,
|
||||||
"strict": [2, "global"],
|
"strict": [2, "global"],
|
||||||
"use-isnan": 2,
|
"use-isnan": 2,
|
||||||
|
|
|
||||||
|
|
@ -33,16 +33,17 @@ function bitRetriever(data, depth) {
|
||||||
|
|
||||||
var leftOver = [];
|
var leftOver = [];
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
|
||||||
function split() {
|
function split() {
|
||||||
if (i === data.length) {
|
if (i === data.length) {
|
||||||
throw new Error("Ran out of data");
|
throw new Error('Ran out of data');
|
||||||
}
|
}
|
||||||
var byte = data[i];
|
var byte = data[i];
|
||||||
i++;
|
i++;
|
||||||
var byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1
|
var byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
|
||||||
switch(depth) {
|
switch (depth) {
|
||||||
default:
|
default:
|
||||||
throw new Error("unrecognised depth");
|
throw new Error('unrecognised depth');
|
||||||
case 16:
|
case 16:
|
||||||
byte2 = data[i];
|
byte2 = data[i];
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -73,9 +74,10 @@ function bitRetriever(data, depth) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
get: function(count) {
|
get: function(count) {
|
||||||
while(leftOver.length < count) {
|
while (leftOver.length < count) {
|
||||||
split();
|
split();
|
||||||
}
|
}
|
||||||
var returner = leftOver.slice(0, count);
|
var returner = leftOver.slice(0, count);
|
||||||
|
|
@ -87,7 +89,8 @@ function bitRetriever(data, depth) {
|
||||||
},
|
},
|
||||||
end: function() {
|
end: function() {
|
||||||
if (i !== data.length) {
|
if (i !== data.length) {
|
||||||
throw new Error("extra data found");
|
// todo these exceptions should be emitting errors
|
||||||
|
throw new Error('extra data found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -120,10 +123,10 @@ exports.dataToBitMap = function(data, width, height, bpp, depth, interlace) {
|
||||||
nonInterlacedPxPos += 4;
|
nonInterlacedPxPos += 4;
|
||||||
return returner;
|
return returner;
|
||||||
};
|
};
|
||||||
images = [{width: width, height: height}];
|
images = [{ width: width, height: height }];
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var imageIndex = 0; imageIndex < images.length; imageIndex++) {
|
for (var imageIndex = 0; imageIndex < images.length; imageIndex++) {
|
||||||
var imageWidth = images[imageIndex].width;
|
var imageWidth = images[imageIndex].width;
|
||||||
var imageHeight = images[imageIndex].height;
|
var imageHeight = images[imageIndex].height;
|
||||||
var imagePass = images[imageIndex].index;
|
var imagePass = images[imageIndex].index;
|
||||||
|
|
@ -138,7 +141,7 @@ exports.dataToBitMap = function(data, width, height, bpp, depth, interlace) {
|
||||||
var idx = pixelBppMap[bpp][i];
|
var idx = pixelBppMap[bpp][i];
|
||||||
if (depth === 8) {
|
if (depth === 8) {
|
||||||
if (i === data.length) {
|
if (i === data.length) {
|
||||||
throw new Error("Ran out of data");
|
throw new Error('Ran out of data');
|
||||||
}
|
}
|
||||||
pxData[pxPos + i] = idx !== 0xff ? data[idx + rawPos] : maxBit;
|
pxData[pxPos + i] = idx !== 0xff ? data[idx + rawPos] : maxBit;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -155,7 +158,7 @@ exports.dataToBitMap = function(data, width, height, bpp, depth, interlace) {
|
||||||
}
|
}
|
||||||
if (depth === 8) {
|
if (depth === 8) {
|
||||||
if (rawPos !== data.length) {
|
if (rawPos !== data.length) {
|
||||||
throw new Error("extra data found");
|
throw new Error('extra data found');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bits.end();
|
bits.end();
|
||||||
|
|
|
||||||
|
|
@ -21,180 +21,189 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
var util = require('util'),
|
var util = require('util');
|
||||||
Stream = require('stream');
|
var Stream = require('stream');
|
||||||
|
|
||||||
|
|
||||||
var ChunkStream = module.exports = function() {
|
var ChunkStream = module.exports = function() {
|
||||||
Stream.call(this);
|
Stream.call(this);
|
||||||
|
|
||||||
this._buffers = [];
|
this._buffers = [];
|
||||||
this._buffered = 0;
|
this._buffered = 0;
|
||||||
|
|
||||||
this._reads = [];
|
this._reads = [];
|
||||||
this._paused = false;
|
this._paused = false;
|
||||||
|
|
||||||
this._encoding = 'utf8';
|
this._encoding = 'utf8';
|
||||||
this.writable = true;
|
this.writable = true;
|
||||||
};
|
};
|
||||||
util.inherits(ChunkStream, Stream);
|
util.inherits(ChunkStream, Stream);
|
||||||
|
|
||||||
|
|
||||||
ChunkStream.prototype.read = function(length, callback) {
|
ChunkStream.prototype.read = function(length, callback) {
|
||||||
|
|
||||||
this._reads.push({
|
this._reads.push({
|
||||||
length: Math.abs(length), // if length < 0 then at most this length
|
length: Math.abs(length), // if length < 0 then at most this length
|
||||||
allowLess: length < 0,
|
allowLess: length < 0,
|
||||||
func: callback
|
func: callback
|
||||||
});
|
});
|
||||||
|
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
this._process();
|
this._process();
|
||||||
|
|
||||||
// its paused and there is not enought data then ask for more
|
// its paused and there is not enought data then ask for more
|
||||||
if (this._paused && this._reads.length > 0) {
|
if (this._paused && this._reads.length > 0) {
|
||||||
this._paused = false;
|
this._paused = false;
|
||||||
|
|
||||||
this.emit('drain');
|
this.emit('drain');
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
ChunkStream.prototype.write = function(data, encoding) {
|
ChunkStream.prototype.write = function(data, encoding) {
|
||||||
|
|
||||||
if (!this.writable) {
|
if (!this.writable) {
|
||||||
this.emit('error', new Error('Stream not writable'));
|
this.emit('error', new Error('Stream not writable'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Buffer.isBuffer(data))
|
var dataBuffer;
|
||||||
data = new Buffer(data, encoding || this._encoding);
|
if (Buffer.isBuffer(data)) {
|
||||||
|
dataBuffer = data;
|
||||||
|
} else {
|
||||||
|
dataBuffer = new Buffer(data, encoding || this._encoding);
|
||||||
|
}
|
||||||
|
|
||||||
this._buffers.push(data);
|
this._buffers.push(dataBuffer);
|
||||||
this._buffered += data.length;
|
this._buffered += dataBuffer.length;
|
||||||
|
|
||||||
this._process();
|
this._process();
|
||||||
|
|
||||||
// ok if there are no more read requests
|
// ok if there are no more read requests
|
||||||
if (this._reads && this._reads.length == 0)
|
if (this._reads && this._reads.length == 0) {
|
||||||
this._paused = true;
|
this._paused = true;
|
||||||
|
}
|
||||||
|
|
||||||
return this.writable && !this._paused;
|
return this.writable && !this._paused;
|
||||||
};
|
};
|
||||||
|
|
||||||
ChunkStream.prototype.end = function(data, encoding) {
|
ChunkStream.prototype.end = function(data, encoding) {
|
||||||
|
|
||||||
if (data) this.write(data, encoding);
|
if (data) {
|
||||||
|
this.write(data, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
this.writable = false;
|
this.writable = false;
|
||||||
|
|
||||||
// already destroyed
|
// already destroyed
|
||||||
if (!this._buffers) return;
|
if (!this._buffers) return;
|
||||||
|
|
||||||
// enqueue or handle end
|
// enqueue or handle end
|
||||||
if (this._buffers.length == 0) {
|
if (this._buffers.length == 0) {
|
||||||
this._end();
|
this._end();
|
||||||
} else {
|
} else {
|
||||||
this._buffers.push(null);
|
this._buffers.push(null);
|
||||||
this._process();
|
this._process();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
|
ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
|
||||||
|
|
||||||
ChunkStream.prototype._end = function() {
|
ChunkStream.prototype._end = function() {
|
||||||
|
|
||||||
if (this._reads.length > 0) {
|
if (this._reads.length > 0) {
|
||||||
this.emit('error',
|
this.emit('error',
|
||||||
new Error('There are some read requests waitng on finished stream')
|
new Error('There are some read requests waitng on finished stream')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.destroy();
|
this.destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
ChunkStream.prototype.destroy = function() {
|
ChunkStream.prototype.destroy = function() {
|
||||||
|
|
||||||
if (!this._buffers) return;
|
if (!this._buffers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.writable = false;
|
this.writable = false;
|
||||||
this._reads = null;
|
this._reads = null;
|
||||||
this._buffers = null;
|
this._buffers = null;
|
||||||
|
|
||||||
this.emit('close');
|
this.emit('close');
|
||||||
};
|
};
|
||||||
|
|
||||||
ChunkStream.prototype._process = function() {
|
ChunkStream.prototype._process = function() {
|
||||||
|
|
||||||
// as long as there is any data and read requests
|
// as long as there is any data and read requests
|
||||||
while (this._buffered > 0 && this._reads && this._reads.length > 0) {
|
while (this._buffered > 0 && this._reads && this._reads.length > 0) {
|
||||||
|
|
||||||
var read = this._reads[0];
|
var read = this._reads[0];
|
||||||
|
|
||||||
// read any data (but no more than length)
|
// read any data (but no more than length)
|
||||||
if (read.allowLess) {
|
if (read.allowLess) {
|
||||||
|
|
||||||
// ok there is any data so that we can satisfy this request
|
// ok there is any data so that we can satisfy this request
|
||||||
this._reads.shift(); // == read
|
this._reads.shift(); // == read
|
||||||
|
|
||||||
// first we need to peek into first buffer
|
// first we need to peek into first buffer
|
||||||
var smallerBuf = this._buffers[0];
|
var smallerBuf = this._buffers[0];
|
||||||
|
|
||||||
// ok there is more data than we need
|
// ok there is more data than we need
|
||||||
if (smallerBuf.length > read.length) {
|
if (smallerBuf.length > read.length) {
|
||||||
|
|
||||||
this._buffered -= read.length;
|
this._buffered -= read.length;
|
||||||
this._buffers[0] = smallerBuf.slice(read.length);
|
this._buffers[0] = smallerBuf.slice(read.length);
|
||||||
|
|
||||||
read.func.call(this, smallerBuf.slice(0, read.length));
|
read.func.call(this, smallerBuf.slice(0, read.length));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// ok this is less than maximum length so use it all
|
// ok this is less than maximum length so use it all
|
||||||
this._buffered -= smallerBuf.length;
|
this._buffered -= smallerBuf.length;
|
||||||
this._buffers.shift(); // == smallerBuf
|
this._buffers.shift(); // == smallerBuf
|
||||||
|
|
||||||
read.func.call(this, smallerBuf);
|
read.func.call(this, smallerBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (this._buffered >= read.length) {
|
} else if (this._buffered >= read.length) {
|
||||||
// ok we can meet some expectations
|
// ok we can meet some expectations
|
||||||
|
|
||||||
this._reads.shift(); // == read
|
this._reads.shift(); // == read
|
||||||
|
|
||||||
var pos = 0,
|
var pos = 0;
|
||||||
count = 0,
|
var count = 0;
|
||||||
data = new Buffer(read.length);
|
var data = new Buffer(read.length);
|
||||||
|
|
||||||
// create buffer for all data
|
// create buffer for all data
|
||||||
while (pos < read.length) {
|
while (pos < read.length) {
|
||||||
|
|
||||||
var buf = this._buffers[count++],
|
var buf = this._buffers[count++];
|
||||||
len = Math.min(buf.length, read.length - pos);
|
var len = Math.min(buf.length, read.length - pos);
|
||||||
|
|
||||||
buf.copy(data, pos, 0, len);
|
buf.copy(data, pos, 0, len);
|
||||||
pos += len;
|
pos += len;
|
||||||
|
|
||||||
// last buffer wasn't used all so just slice it and leave
|
// last buffer wasn't used all so just slice it and leave
|
||||||
if (len != buf.length)
|
if (len != buf.length)
|
||||||
this._buffers[--count] = buf.slice(len);
|
this._buffers[--count] = buf.slice(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all used buffers
|
// remove all used buffers
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
this._buffers.splice(0, count);
|
this._buffers.splice(0, count);
|
||||||
|
|
||||||
this._buffered -= read.length;
|
this._buffered -= read.length;
|
||||||
|
|
||||||
read.func.call(this, data);
|
read.func.call(this, data);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// not enought data to satisfy first request in queue
|
// not enought data to satisfy first request in queue
|
||||||
// so we need to wait for more
|
// so we need to wait for more
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this._buffers && this._buffers.length > 0 && this._buffers[0] == null) {
|
if (this._buffers && this._buffers.length > 0 && this._buffers[0] == null) {
|
||||||
this._end();
|
this._end();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,18 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
|
PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
|
||||||
|
|
||||||
TYPE_IHDR: 0x49484452,
|
TYPE_IHDR: 0x49484452,
|
||||||
TYPE_IEND: 0x49454e44,
|
TYPE_IEND: 0x49454e44,
|
||||||
TYPE_IDAT: 0x49444154,
|
TYPE_IDAT: 0x49444154,
|
||||||
TYPE_PLTE: 0x504c5445,
|
TYPE_PLTE: 0x504c5445,
|
||||||
TYPE_tRNS: 0x74524e53,
|
/*eslint camelcase: 0*/
|
||||||
TYPE_gAMA: 0x67414d41,
|
TYPE_tRNS: 0x74524e53,
|
||||||
|
TYPE_gAMA: 0x67414d41,
|
||||||
|
/*eslint camelcase: 1*/
|
||||||
|
|
||||||
COLOR_PALETTE: 1,
|
COLOR_PALETTE: 1,
|
||||||
COLOR_COLOR: 2,
|
COLOR_COLOR: 2,
|
||||||
COLOR_ALPHA: 4
|
COLOR_ALPHA: 4
|
||||||
};
|
};
|
||||||
|
|
|
||||||
42
lib/crc.js
42
lib/crc.js
|
|
@ -23,41 +23,41 @@
|
||||||
var crcTable = [];
|
var crcTable = [];
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
for (var i = 0; i < 256; i++) {
|
for (var i = 0; i < 256; i++) {
|
||||||
var c = i;
|
var currentCrc = i;
|
||||||
for (var j = 0; j < 8; j++) {
|
for (var j = 0; j < 8; j++) {
|
||||||
if (c & 1) {
|
if (currentCrc & 1) {
|
||||||
c = 0xedb88320 ^ (c >>> 1);
|
currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
|
||||||
} else {
|
} else {
|
||||||
c = c >>> 1;
|
currentCrc = currentCrc >>> 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
crcTable[i] = c;
|
|
||||||
}
|
}
|
||||||
|
crcTable[i] = currentCrc;
|
||||||
|
}
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var CrcCalculator = module.exports = function() {
|
var CrcCalculator = module.exports = function() {
|
||||||
this._crc = -1;
|
this._crc = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
CrcCalculator.prototype.write = function(data) {
|
CrcCalculator.prototype.write = function(data) {
|
||||||
|
|
||||||
for (var i = 0; i < data.length; i++) {
|
for (var i = 0; i < data.length; i++) {
|
||||||
this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
|
this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
CrcCalculator.prototype.crc32 = function() {
|
CrcCalculator.prototype.crc32 = function() {
|
||||||
return this._crc ^ -1;
|
return this._crc ^ -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CrcCalculator.crc32 = function(buf) {
|
CrcCalculator.crc32 = function(buf) {
|
||||||
|
|
||||||
var crc = -1;
|
var crc = -1;
|
||||||
for (var i = 0; i < buf.length; i++) {
|
for (var i = 0; i < buf.length; i++) {
|
||||||
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
|
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
|
||||||
}
|
}
|
||||||
return crc ^ -1;
|
return crc ^ -1;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,26 +20,26 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var util = require('util'),
|
var util = require('util');
|
||||||
ChunkStream = require('./chunkstream'),
|
var ChunkStream = require('./chunkstream');
|
||||||
Filter = require('./filter');
|
var Filter = require('./filter');
|
||||||
|
|
||||||
|
|
||||||
var FilterAsync = module.exports = function(width, height, Bpp, depth, interlace, options) {
|
var FilterAsync = module.exports = function(width, height, Bpp, depth, interlace, options) {
|
||||||
ChunkStream.call(this);
|
ChunkStream.call(this);
|
||||||
|
|
||||||
var buffers = [];
|
var buffers = [];
|
||||||
var that = this;
|
var that = this;
|
||||||
this._filter = new Filter(width, height, Bpp, depth, interlace, options, {
|
this._filter = new Filter(width, height, Bpp, depth, interlace, options, {
|
||||||
read: this.read.bind(this),
|
read: this.read.bind(this),
|
||||||
complete: function() {
|
complete: function() {
|
||||||
that.emit('complete', Buffer.concat(buffers), width, height)
|
that.emit('complete', Buffer.concat(buffers), width, height)
|
||||||
},
|
},
|
||||||
write: function(buffer) {
|
write: function(buffer) {
|
||||||
buffers.push(buffer);
|
buffers.push(buffer);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._filter.start();
|
this._filter.start();
|
||||||
};
|
};
|
||||||
util.inherits(FilterAsync, ChunkStream);
|
util.inherits(FilterAsync, ChunkStream);
|
||||||
|
|
|
||||||
|
|
@ -20,24 +20,25 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var SyncReader = require('./sync-reader'),
|
var SyncReader = require('./sync-reader');
|
||||||
Filter = require('./filter');
|
var Filter = require('./filter');
|
||||||
|
|
||||||
|
|
||||||
exports.process = function(inBuffer, width, height, Bpp, depth, interlace, options) {
|
exports.process = function(inBuffer, width, height, Bpp, depth, interlace, options) {
|
||||||
|
|
||||||
var outBuffers = [];
|
var outBuffers = [];
|
||||||
var reader = new SyncReader(inBuffer);
|
var reader = new SyncReader(inBuffer);
|
||||||
var filter = new Filter(width, height, Bpp, depth, interlace, options, {
|
var filter = new Filter(width, height, Bpp, depth, interlace, options, {
|
||||||
read: reader.read.bind(reader),
|
read: reader.read.bind(reader),
|
||||||
write: function(bufferPart) {
|
write: function(bufferPart) {
|
||||||
outBuffers.push(bufferPart);
|
outBuffers.push(bufferPart);
|
||||||
},
|
},
|
||||||
complete: function(){}
|
complete: function() {
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
filter.start();
|
filter.start();
|
||||||
reader.process();
|
reader.process();
|
||||||
|
|
||||||
return Buffer.concat(outBuffers);
|
return Buffer.concat(outBuffers);
|
||||||
};
|
};
|
||||||
374
lib/filter.js
374
lib/filter.js
|
|
@ -23,265 +23,265 @@
|
||||||
var interlaceUtils = require('./interlace');
|
var interlaceUtils = require('./interlace');
|
||||||
|
|
||||||
function getByteWidth(width, bpp, depth) {
|
function getByteWidth(width, bpp, depth) {
|
||||||
var byteWidth = width * bpp;
|
var byteWidth = width * bpp;
|
||||||
if (depth !== 8) {
|
if (depth !== 8) {
|
||||||
byteWidth = Math.ceil(byteWidth / (8 / depth));
|
byteWidth = Math.ceil(byteWidth / (8 / depth));
|
||||||
}
|
}
|
||||||
return byteWidth;
|
return byteWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PaethPredictor(left, above, upLeft) {
|
function PaethPredictor(left, above, upLeft) {
|
||||||
|
|
||||||
var p = left + above - upLeft,
|
var p = left + above - upLeft,
|
||||||
pLeft = Math.abs(p - left),
|
pLeft = Math.abs(p - left),
|
||||||
pAbove = Math.abs(p - above),
|
pAbove = Math.abs(p - above),
|
||||||
pUpLeft = Math.abs(p - upLeft);
|
pUpLeft = Math.abs(p - upLeft);
|
||||||
|
|
||||||
if (pLeft <= pAbove && pLeft <= pUpLeft) {
|
if (pLeft <= pAbove && pLeft <= pUpLeft) {
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
if (pAbove <= pUpLeft) {
|
if (pAbove <= pUpLeft) {
|
||||||
return above;
|
return above;
|
||||||
}
|
}
|
||||||
return upLeft;
|
return upLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var Filter = module.exports = function(width, height, Bpp, depth, interlace, options, dependencies) {
|
var Filter = module.exports = function(width, height, Bpp, depth, interlace, options, dependencies) {
|
||||||
|
|
||||||
this._width = width;
|
this._width = width;
|
||||||
this._height = height;
|
this._height = height;
|
||||||
this._Bpp = Bpp;
|
this._Bpp = Bpp;
|
||||||
this._depth = depth;
|
this._depth = depth;
|
||||||
this._options = options;
|
this._options = options;
|
||||||
|
|
||||||
if (!('filterType' in options) || options.filterType == -1) {
|
if (!('filterType' in options) || options.filterType == -1) {
|
||||||
options.filterType = [0, 1, 2, 3, 4];
|
options.filterType = [0, 1, 2, 3, 4];
|
||||||
} else if (typeof options.filterType == 'number') {
|
} else if (typeof options.filterType == 'number') {
|
||||||
options.filterType = [options.filterType];
|
options.filterType = [options.filterType];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._filters = {
|
this._filters = {
|
||||||
0: this._filterNone.bind(this),
|
0: this._filterNone.bind(this),
|
||||||
1: this._filterSub.bind(this),
|
1: this._filterSub.bind(this),
|
||||||
2: this._filterUp.bind(this),
|
2: this._filterUp.bind(this),
|
||||||
3: this._filterAvg.bind(this),
|
3: this._filterAvg.bind(this),
|
||||||
4: this._filterPaeth.bind(this)
|
4: this._filterPaeth.bind(this)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.read = dependencies.read;
|
this.read = dependencies.read;
|
||||||
this.write = dependencies.write;
|
this.write = dependencies.write;
|
||||||
this.complete = dependencies.complete;
|
this.complete = dependencies.complete;
|
||||||
|
|
||||||
this._imageIndex = 0;
|
this._imageIndex = 0;
|
||||||
this._images = [];
|
this._images = [];
|
||||||
if (interlace) {
|
if (interlace) {
|
||||||
var passes = interlaceUtils.getImagePasses(width, height);
|
var passes = interlaceUtils.getImagePasses(width, height);
|
||||||
for(var i = 0; i < passes.length; i++) {
|
for (var i = 0; i < passes.length; i++) {
|
||||||
this._images.push({
|
this._images.push({
|
||||||
byteWidth: getByteWidth(passes[i].width, Bpp, depth),
|
byteWidth: getByteWidth(passes[i].width, Bpp, depth),
|
||||||
height: passes[i].height,
|
height: passes[i].height,
|
||||||
lineIndex: 0
|
lineIndex: 0
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._images.push({
|
|
||||||
byteWidth: getByteWidth(width, Bpp, depth),
|
|
||||||
height: height,
|
|
||||||
lineIndex: 0
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this._images.push({
|
||||||
|
byteWidth: getByteWidth(width, Bpp, depth),
|
||||||
|
height: height,
|
||||||
|
lineIndex: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Filter.prototype.start = function() {
|
Filter.prototype.start = function() {
|
||||||
this.read(this._images[this._imageIndex].byteWidth + 1, this._reverseFilterLine.bind(this));
|
this.read(this._images[this._imageIndex].byteWidth + 1, this._reverseFilterLine.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Filter.prototype._reverseFilterLine = function(rawData) {
|
Filter.prototype._reverseFilterLine = function(rawData) {
|
||||||
|
|
||||||
var currentImage = this._images[this._imageIndex];
|
var currentImage = this._images[this._imageIndex];
|
||||||
var line = new Buffer(currentImage.byteWidth);
|
var line = new Buffer(currentImage.byteWidth);
|
||||||
|
|
||||||
var filter = rawData[0];
|
var filter = rawData[0];
|
||||||
|
|
||||||
var xComparison = this._depth >= 8 ? ((this._depth === 16) ? this._Bpp * 2 : this._Bpp) : 1;
|
var xComparison = this._depth >= 8 ? ((this._depth === 16) ? this._Bpp * 2 : this._Bpp) : 1;
|
||||||
var xBiggerThan = xComparison - 1;
|
var xBiggerThan = xComparison - 1;
|
||||||
|
|
||||||
for (var x = 0; x < currentImage.byteWidth; x++) {
|
for (var x = 0; x < currentImage.byteWidth; x++) {
|
||||||
var rawByte = rawData[1 + x];
|
var rawByte = rawData[1 + x];
|
||||||
switch(filter) {
|
switch (filter) {
|
||||||
case 0:
|
case 0:
|
||||||
line[x] = rawByte;
|
line[x] = rawByte;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
var f1_left = x > xBiggerThan ? line[x - xComparison] : 0;
|
var f1_left = x > xBiggerThan ? line[x - xComparison] : 0;
|
||||||
line[x] = rawByte + f1_left;
|
line[x] = rawByte + f1_left;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
var f2_up = this._lastLine ? this._lastLine[x] : 0;
|
var f2_up = this._lastLine ? this._lastLine[x] : 0;
|
||||||
line[x] = rawByte + f2_up;
|
line[x] = rawByte + f2_up;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
var f3_up = this._lastLine ? this._lastLine[x] : 0;
|
var f3_up = this._lastLine ? this._lastLine[x] : 0;
|
||||||
var f3_left = x > xBiggerThan ? line[x - xComparison] : 0;
|
var f3_left = x > xBiggerThan ? line[x - xComparison] : 0;
|
||||||
var f3_add = Math.floor((f3_left + f3_up) / 2);
|
var f3_add = Math.floor((f3_left + f3_up) / 2);
|
||||||
line[x] = rawByte + f3_add;
|
line[x] = rawByte + f3_add;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
var f4_up = this._lastLine ? this._lastLine[x] : 0;
|
var f4_up = this._lastLine ? this._lastLine[x] : 0;
|
||||||
var f4_left = x > xBiggerThan ? line[x - xComparison] : 0;
|
var f4_left = x > xBiggerThan ? line[x - xComparison] : 0;
|
||||||
var f4_upLeft = x > xBiggerThan && this._lastLine
|
var f4_upLeft = x > xBiggerThan && this._lastLine
|
||||||
? this._lastLine[x - xComparison] : 0;
|
? this._lastLine[x - xComparison] : 0;
|
||||||
var f4_add = PaethPredictor(f4_left, f4_up, f4_upLeft);
|
var f4_add = PaethPredictor(f4_left, f4_up, f4_upLeft);
|
||||||
line[x] = rawByte + f4_add;
|
line[x] = rawByte + f4_add;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
//if (x === 5) {
|
|
||||||
// console.log("R", line[3], "G", line[4], "B", line[5]);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.write(line);
|
//if (x === 5) {
|
||||||
|
// console.log("R", line[3], "G", line[4], "B", line[5]);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
currentImage.lineIndex++;
|
this.write(line);
|
||||||
if (currentImage.lineIndex >= currentImage.height) {
|
|
||||||
this._lastLine = null;
|
|
||||||
this._imageIndex++;
|
|
||||||
currentImage = this._images[this._imageIndex];
|
|
||||||
} else {
|
|
||||||
this._lastLine = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentImage) {
|
currentImage.lineIndex++;
|
||||||
this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
|
if (currentImage.lineIndex >= currentImage.height) {
|
||||||
} else {
|
this._lastLine = null;
|
||||||
this.complete(this._width, this._height);
|
this._imageIndex++;
|
||||||
}
|
currentImage = this._images[this._imageIndex];
|
||||||
|
} else {
|
||||||
|
this._lastLine = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentImage) {
|
||||||
|
this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
|
||||||
|
} else {
|
||||||
|
this.complete(this._width, this._height);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Filter.prototype.filter = function(pxData) {
|
Filter.prototype.filter = function(pxData) {
|
||||||
|
|
||||||
var rawData = new Buffer(((this._width << 2) + 1) * this._height);
|
var rawData = new Buffer(((this._width << 2) + 1) * this._height);
|
||||||
|
|
||||||
for (var y = 0; y < this._height; y++) {
|
for (var y = 0; y < this._height; y++) {
|
||||||
|
|
||||||
// find best filter for this line (with lowest sum of values)
|
// find best filter for this line (with lowest sum of values)
|
||||||
var filterTypes = this._options.filterType,
|
var filterTypes = this._options.filterType,
|
||||||
min = Infinity,
|
min = Infinity,
|
||||||
sel = 0;
|
sel = 0;
|
||||||
|
|
||||||
for (var i = 0; i < filterTypes.length; i++) {
|
for (var i = 0; i < filterTypes.length; i++) {
|
||||||
var sum = this._filters[filterTypes[i]](pxData, y, null);
|
var sum = this._filters[filterTypes[i]](pxData, y, null);
|
||||||
if (sum < min) {
|
if (sum < min) {
|
||||||
sel = filterTypes[i];
|
sel = filterTypes[i];
|
||||||
min = sum;
|
min = sum;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this._filters[sel](pxData, y, rawData);
|
|
||||||
}
|
}
|
||||||
return rawData;
|
|
||||||
|
this._filters[sel](pxData, y, rawData);
|
||||||
|
}
|
||||||
|
return rawData;
|
||||||
};
|
};
|
||||||
|
|
||||||
Filter.prototype._filterNone = function(pxData, y, rawData) {
|
Filter.prototype._filterNone = function(pxData, y, rawData) {
|
||||||
|
|
||||||
var pxRowLength = this._width << 2,
|
var pxRowLength = this._width << 2,
|
||||||
rawRowLength = pxRowLength + 1,
|
rawRowLength = pxRowLength + 1,
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
if (!rawData) {
|
if (!rawData) {
|
||||||
for (var x = 0; x < pxRowLength; x++)
|
for (var x = 0; x < pxRowLength; x++)
|
||||||
sum += Math.abs(pxData[y * pxRowLength + x]);
|
sum += Math.abs(pxData[y * pxRowLength + x]);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rawData[y * rawRowLength] = 0;
|
rawData[y * rawRowLength] = 0;
|
||||||
pxData.copy(rawData, rawRowLength * y + 1, pxRowLength * y, pxRowLength * (y + 1));
|
pxData.copy(rawData, rawRowLength * y + 1, pxRowLength * y, pxRowLength * (y + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
};
|
};
|
||||||
|
|
||||||
Filter.prototype._filterSub = function(pxData, y, rawData) {
|
Filter.prototype._filterSub = function(pxData, y, rawData) {
|
||||||
|
|
||||||
var pxRowLength = this._width << 2,
|
var pxRowLength = this._width << 2,
|
||||||
rawRowLength = pxRowLength + 1,
|
rawRowLength = pxRowLength + 1,
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
if (rawData)
|
if (rawData)
|
||||||
rawData[y * rawRowLength] = 1;
|
rawData[y * rawRowLength] = 1;
|
||||||
|
|
||||||
for (var x = 0; x < pxRowLength; x++) {
|
for (var x = 0; x < pxRowLength; x++) {
|
||||||
|
|
||||||
var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0,
|
var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0,
|
||||||
val = pxData[y * pxRowLength + x] - left;
|
val = pxData[y * pxRowLength + x] - left;
|
||||||
|
|
||||||
if (!rawData) sum += Math.abs(val);
|
if (!rawData) sum += Math.abs(val);
|
||||||
else rawData[y * rawRowLength + 1 + x] = val;
|
else rawData[y * rawRowLength + 1 + x] = val;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
};
|
};
|
||||||
|
|
||||||
Filter.prototype._filterUp = function(pxData, y, rawData) {
|
Filter.prototype._filterUp = function(pxData, y, rawData) {
|
||||||
|
|
||||||
var pxRowLength = this._width << 2,
|
var pxRowLength = this._width << 2,
|
||||||
rawRowLength = pxRowLength + 1,
|
rawRowLength = pxRowLength + 1,
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
if (rawData)
|
if (rawData)
|
||||||
rawData[y * rawRowLength] = 2;
|
rawData[y * rawRowLength] = 2;
|
||||||
|
|
||||||
for (var x = 0; x < pxRowLength; x++) {
|
for (var x = 0; x < pxRowLength; x++) {
|
||||||
|
|
||||||
var up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
|
var up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
|
||||||
val = pxData[y * pxRowLength + x] - up;
|
val = pxData[y * pxRowLength + x] - up;
|
||||||
|
|
||||||
if (!rawData) sum += Math.abs(val);
|
if (!rawData) sum += Math.abs(val);
|
||||||
else rawData[y * rawRowLength + 1 + x] = val;
|
else rawData[y * rawRowLength + 1 + x] = val;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
};
|
};
|
||||||
|
|
||||||
Filter.prototype._filterAvg = function(pxData, y, rawData) {
|
Filter.prototype._filterAvg = function(pxData, y, rawData) {
|
||||||
|
|
||||||
var pxRowLength = this._width << 2,
|
var pxRowLength = this._width << 2,
|
||||||
rawRowLength = pxRowLength + 1,
|
rawRowLength = pxRowLength + 1,
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
if (rawData)
|
if (rawData)
|
||||||
rawData[y * rawRowLength] = 3;
|
rawData[y * rawRowLength] = 3;
|
||||||
|
|
||||||
for (var x = 0; x < pxRowLength; x++) {
|
for (var x = 0; x < pxRowLength; x++) {
|
||||||
|
|
||||||
var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0,
|
var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0,
|
||||||
up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
|
up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
|
||||||
val = pxData[y * pxRowLength + x] - ((left + up) >> 1);
|
val = pxData[y * pxRowLength + x] - ((left + up) >> 1);
|
||||||
|
|
||||||
if (!rawData) sum += Math.abs(val);
|
if (!rawData) sum += Math.abs(val);
|
||||||
else rawData[y * rawRowLength + 1 + x] = val;
|
else rawData[y * rawRowLength + 1 + x] = val;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
};
|
};
|
||||||
|
|
||||||
Filter.prototype._filterPaeth = function(pxData, y, rawData) {
|
Filter.prototype._filterPaeth = function(pxData, y, rawData) {
|
||||||
|
|
||||||
var pxRowLength = this._width << 2,
|
var pxRowLength = this._width << 2,
|
||||||
rawRowLength = pxRowLength + 1,
|
rawRowLength = pxRowLength + 1,
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
if (rawData)
|
if (rawData)
|
||||||
rawData[y * rawRowLength] = 4;
|
rawData[y * rawRowLength] = 4;
|
||||||
|
|
||||||
for (var x = 0; x < pxRowLength; x++) {
|
for (var x = 0; x < pxRowLength; x++) {
|
||||||
|
|
||||||
var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0,
|
var left = x >= 4 ? pxData[y * pxRowLength + x - 4] : 0,
|
||||||
up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
|
up = y > 0 ? pxData[(y - 1) * pxRowLength + x] : 0,
|
||||||
upLeft = x >= 4 && y > 0 ? pxData[(y - 1) * pxRowLength + x - 4] : 0,
|
upLeft = x >= 4 && y > 0 ? pxData[(y - 1) * pxRowLength + x - 4] : 0,
|
||||||
val = pxData[y * pxRowLength + x] - PaethPredictor(left, up, upLeft);
|
val = pxData[y * pxRowLength + x] - PaethPredictor(left, up, upLeft);
|
||||||
|
|
||||||
if (!rawData) sum += Math.abs(val);
|
if (!rawData) sum += Math.abs(val);
|
||||||
else rawData[y * rawRowLength + 1 + x] = val;
|
else rawData[y * rawRowLength + 1 + x] = val;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,11 @@ exports.getImagePasses = function(width, height) {
|
||||||
var yLeftOver = height % 8;
|
var yLeftOver = height % 8;
|
||||||
var xRepeats = (width - xLeftOver) / 8;
|
var xRepeats = (width - xLeftOver) / 8;
|
||||||
var yRepeats = (width - yLeftOver) / 8;
|
var yRepeats = (width - yLeftOver) / 8;
|
||||||
for(var i = 0; i < imagePasses.length; i++) {
|
for (var i = 0; i < imagePasses.length; i++) {
|
||||||
var pass = imagePasses[i];
|
var pass = imagePasses[i];
|
||||||
var passWidth = xRepeats * pass.x.length;
|
var passWidth = xRepeats * pass.x.length;
|
||||||
var passHeight = yRepeats * pass.y.length;
|
var passHeight = yRepeats * pass.y.length;
|
||||||
for(var j = 0; j < pass.x.length; j++) {
|
for (var j = 0; j < pass.x.length; j++) {
|
||||||
if (pass.x[j] < xLeftOver) {
|
if (pass.x[j] < xLeftOver) {
|
||||||
passWidth++;
|
passWidth++;
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +61,7 @@ exports.getImagePasses = function(width, height) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(j = 0; j < pass.y.length; j++) {
|
for (j = 0; j < pass.y.length; j++) {
|
||||||
if (pass.y[j] < yLeftOver) {
|
if (pass.y[j] < yLeftOver) {
|
||||||
passHeight++;
|
passHeight++;
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +70,7 @@ exports.getImagePasses = function(width, height) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (passWidth > 0 && passHeight > 0) {
|
if (passWidth > 0 && passHeight > 0) {
|
||||||
images.push({ width: passWidth, height: passHeight, index: i});
|
images.push({width: passWidth, height: passHeight, index: i});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return images;
|
return images;
|
||||||
|
|
@ -79,7 +79,7 @@ exports.getImagePasses = function(width, height) {
|
||||||
exports.getInterlaceIterator = function(width) {
|
exports.getInterlaceIterator = function(width) {
|
||||||
return function(x, y, pass) {
|
return function(x, y, pass) {
|
||||||
var outerXLeftOver = x % imagePasses[pass].x.length;
|
var outerXLeftOver = x % imagePasses[pass].x.length;
|
||||||
var outerX = (((x - outerXLeftOver)/ imagePasses[pass].x.length) * 8) + imagePasses[pass].x[outerXLeftOver];
|
var outerX = (((x - outerXLeftOver) / imagePasses[pass].x.length) * 8) + imagePasses[pass].x[outerXLeftOver];
|
||||||
var outerYLeftOver = y % imagePasses[pass].y.length;
|
var outerYLeftOver = y % imagePasses[pass].y.length;
|
||||||
var outerY = (((y - outerYLeftOver) / imagePasses[pass].y.length) * 8) + imagePasses[pass].y[outerYLeftOver];
|
var outerY = (((y - outerYLeftOver) / imagePasses[pass].y.length) * 8) + imagePasses[pass].y[outerYLeftOver];
|
||||||
return (outerX * 4) + (outerY * width * 4);
|
return (outerX * 4) + (outerY * width * 4);
|
||||||
|
|
|
||||||
104
lib/packer.js
104
lib/packer.js
|
|
@ -21,91 +21,91 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
var util = require('util'),
|
var util = require('util');
|
||||||
Stream = require('stream'),
|
var Stream = require('stream');
|
||||||
zlib = require('zlib'),
|
var zlib = require('zlib');
|
||||||
Filter = require('./filter'),
|
var Filter = require('./filter');
|
||||||
CrcStream = require('./crc'),
|
var CrcStream = require('./crc');
|
||||||
constants = require('./constants');
|
var constants = require('./constants');
|
||||||
|
|
||||||
|
|
||||||
var Packer = module.exports = function(options) {
|
var Packer = module.exports = function(options) {
|
||||||
Stream.call(this);
|
Stream.call(this);
|
||||||
|
|
||||||
this._options = options;
|
this._options = options;
|
||||||
|
|
||||||
options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
|
options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
|
||||||
options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9;
|
options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9;
|
||||||
options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3;
|
options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3;
|
||||||
|
|
||||||
this.readable = true;
|
this.readable = true;
|
||||||
};
|
};
|
||||||
util.inherits(Packer, Stream);
|
util.inherits(Packer, Stream);
|
||||||
|
|
||||||
|
|
||||||
Packer.prototype.pack = function(data, width, height) {
|
Packer.prototype.pack = function(data, width, height) {
|
||||||
|
|
||||||
// Signature
|
// Signature
|
||||||
this.emit('data', new Buffer(constants.PNG_SIGNATURE));
|
this.emit('data', new Buffer(constants.PNG_SIGNATURE));
|
||||||
this.emit('data', this._packIHDR(width, height));
|
this.emit('data', this._packIHDR(width, height));
|
||||||
|
|
||||||
// filter pixel data
|
// filter pixel data
|
||||||
//TODO {}
|
//TODO {}
|
||||||
var filter = new Filter(width, height, 4, 8, false, this._options, {});
|
var filter = new Filter(width, height, 4, 8, false, this._options, {});
|
||||||
var filteredData = filter.filter(data);
|
var filteredData = filter.filter(data);
|
||||||
|
|
||||||
// compress it
|
// compress it
|
||||||
var deflate = zlib.createDeflate({
|
var deflate = zlib.createDeflate({
|
||||||
chunkSize: this._options.deflateChunkSize,
|
chunkSize: this._options.deflateChunkSize,
|
||||||
level: this._options.deflateLevel,
|
level: this._options.deflateLevel,
|
||||||
strategy: this._options.deflateStrategy
|
strategy: this._options.deflateStrategy
|
||||||
});
|
});
|
||||||
deflate.on('error', this.emit.bind(this, 'error'));
|
deflate.on('error', this.emit.bind(this, 'error'));
|
||||||
|
|
||||||
deflate.on('data', function(compressedData) {
|
deflate.on('data', function(compressedData) {
|
||||||
this.emit('data', this._packIDAT(compressedData));
|
this.emit('data', this._packIDAT(compressedData));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
deflate.on('end', function() {
|
deflate.on('end', function() {
|
||||||
this.emit('data', this._packIEND());
|
this.emit('data', this._packIEND());
|
||||||
this.emit('end');
|
this.emit('end');
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
deflate.end(filteredData);
|
deflate.end(filteredData);
|
||||||
};
|
};
|
||||||
|
|
||||||
Packer.prototype._packChunk = function(type, data) {
|
Packer.prototype._packChunk = function(type, data) {
|
||||||
|
|
||||||
var len = (data ? data.length : 0),
|
var len = (data ? data.length : 0),
|
||||||
buf = new Buffer(len + 12);
|
buf = new Buffer(len + 12);
|
||||||
|
|
||||||
buf.writeUInt32BE(len, 0);
|
buf.writeUInt32BE(len, 0);
|
||||||
buf.writeUInt32BE(type, 4);
|
buf.writeUInt32BE(type, 4);
|
||||||
|
|
||||||
if (data) data.copy(buf, 8);
|
if (data) data.copy(buf, 8);
|
||||||
|
|
||||||
buf.writeInt32BE(CrcStream.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;
|
return buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
Packer.prototype._packIHDR = function(width, height) {
|
Packer.prototype._packIHDR = function(width, height) {
|
||||||
|
|
||||||
var buf = new Buffer(13);
|
var buf = new Buffer(13);
|
||||||
buf.writeUInt32BE(width, 0);
|
buf.writeUInt32BE(width, 0);
|
||||||
buf.writeUInt32BE(height, 4);
|
buf.writeUInt32BE(height, 4);
|
||||||
buf[8] = 8;
|
buf[8] = 8;
|
||||||
buf[9] = 6; // colorType
|
buf[9] = 6; // colorType
|
||||||
buf[10] = 0; // compression
|
buf[10] = 0; // compression
|
||||||
buf[11] = 0; // filter
|
buf[11] = 0; // filter
|
||||||
buf[12] = 0; // interlace
|
buf[12] = 0; // interlace
|
||||||
|
|
||||||
return this._packChunk(constants.TYPE_IHDR, buf);
|
return this._packChunk(constants.TYPE_IHDR, buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
Packer.prototype._packIDAT = function(data) {
|
Packer.prototype._packIDAT = function(data) {
|
||||||
return this._packChunk(constants.TYPE_IDAT, data);
|
return this._packChunk(constants.TYPE_IDAT, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
Packer.prototype._packIEND = function() {
|
Packer.prototype._packIEND = function() {
|
||||||
return this._packChunk(constants.TYPE_IEND, null);
|
return this._packChunk(constants.TYPE_IEND, null);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,108 +21,108 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
var util = require('util'),
|
var util = require('util');
|
||||||
zlib = require('zlib'),
|
var zlib = require('zlib');
|
||||||
ChunkStream = require('./chunkstream'),
|
var ChunkStream = require('./chunkstream');
|
||||||
FilterAsync = require('./filter-async'),
|
var FilterAsync = require('./filter-async');
|
||||||
Parser = require('./parser'),
|
var Parser = require('./parser');
|
||||||
bitmapper = require('./bitmapper');
|
var bitmapper = require('./bitmapper');
|
||||||
|
|
||||||
|
|
||||||
var ParserAsync = module.exports = function(options) {
|
var ParserAsync = module.exports = function(options) {
|
||||||
ChunkStream.call(this);
|
ChunkStream.call(this);
|
||||||
|
|
||||||
this._parser = new Parser(options, {
|
this._parser = new Parser(options, {
|
||||||
read: this.read.bind(this),
|
read: this.read.bind(this),
|
||||||
error: this._handleError.bind(this),
|
error: this._handleError.bind(this),
|
||||||
metadata: this.emit.bind(this, "metadata"),
|
metadata: this.emit.bind(this, "metadata"),
|
||||||
gamma: this.emit.bind(this, "gamma"),
|
gamma: this.emit.bind(this, "gamma"),
|
||||||
finished: this._finished.bind(this),
|
finished: this._finished.bind(this),
|
||||||
inflateData: this._inflateData.bind(this),
|
inflateData: this._inflateData.bind(this),
|
||||||
createData: this._createData.bind(this)
|
createData: this._createData.bind(this)
|
||||||
});
|
});
|
||||||
this._options = options;
|
this._options = options;
|
||||||
this.writable = true;
|
this.writable = true;
|
||||||
|
|
||||||
this._parser.start();
|
this._parser.start();
|
||||||
};
|
};
|
||||||
util.inherits(ParserAsync, ChunkStream);
|
util.inherits(ParserAsync, ChunkStream);
|
||||||
|
|
||||||
|
|
||||||
ParserAsync.prototype._handleError = function(err) {
|
ParserAsync.prototype._handleError = function(err) {
|
||||||
|
|
||||||
this.emit('error', err);
|
this.emit('error', err);
|
||||||
|
|
||||||
this.writable = false;
|
this.writable = false;
|
||||||
|
|
||||||
this.destroy();
|
this.destroy();
|
||||||
|
|
||||||
if (this._inflate && this._inflate.destroy) {
|
if (this._inflate && this._inflate.destroy) {
|
||||||
this._inflate.destroy();
|
this._inflate.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.errord = true;
|
this.errord = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserAsync.prototype._inflateData = function(data) {
|
ParserAsync.prototype._inflateData = function(data) {
|
||||||
if (!this._inflate) {
|
if (!this._inflate) {
|
||||||
this._inflate = zlib.createInflate();
|
this._inflate = zlib.createInflate();
|
||||||
|
|
||||||
this._inflate.on('error', this.emit.bind(this, 'error'));
|
this._inflate.on('error', this.emit.bind(this, 'error'));
|
||||||
this._filter.on('complete', this._complete.bind(this));
|
this._filter.on('complete', this._complete.bind(this));
|
||||||
|
|
||||||
this._inflate.pipe(this._filter);
|
this._inflate.pipe(this._filter);
|
||||||
}
|
}
|
||||||
this._inflate.write(data);
|
this._inflate.write(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserAsync.prototype._createData = function(width, height, bpp, depth, interlace) {
|
ParserAsync.prototype._createData = function(width, height, bpp, depth, interlace) {
|
||||||
|
|
||||||
this._bpp = bpp;
|
this._bpp = bpp;
|
||||||
this._depth = depth;
|
this._depth = depth;
|
||||||
this._interlace = interlace;
|
this._interlace = interlace;
|
||||||
|
|
||||||
this._filter = new FilterAsync(
|
this._filter = new FilterAsync(
|
||||||
width, height,
|
width, height,
|
||||||
bpp,
|
bpp,
|
||||||
depth,
|
depth,
|
||||||
interlace,
|
interlace,
|
||||||
this._options
|
this._options
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserAsync.prototype._finished = function() {
|
ParserAsync.prototype._finished = function() {
|
||||||
if (this.errord) {
|
if (this.errord) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._inflate) {
|
if (!this._inflate) {
|
||||||
this.emit('error', 'No Inflate block');
|
this.emit('error', 'No Inflate block');
|
||||||
} else {
|
} else {
|
||||||
// no more data to inflate
|
// no more data to inflate
|
||||||
this._inflate.end();
|
this._inflate.end();
|
||||||
}
|
}
|
||||||
this.destroySoon();
|
this.destroySoon();
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserAsync.prototype._complete = function(data, width, height) {
|
ParserAsync.prototype._complete = function(data, width, height) {
|
||||||
|
|
||||||
if (this.errord) {
|
if (this.errord) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
data = bitmapper.dataToBitMap(data, width, height,
|
data = bitmapper.dataToBitMap(data, width, height,
|
||||||
this._bpp,
|
this._bpp,
|
||||||
this._depth,
|
this._depth,
|
||||||
this._interlace);
|
this._interlace);
|
||||||
|
|
||||||
data = this._parser.reverseFiltered(data, this._depth, width, height);
|
data = this._parser.reverseFiltered(data, this._depth, width, height);
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch (e) {
|
||||||
this._handleError();
|
this._handleError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('parsed', data);
|
this.emit('parsed', data);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,76 +21,77 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
var zlib = require('zlib'),
|
var zlib = require('zlib');
|
||||||
SyncReader = require('./sync-reader'),
|
var SyncReader = require('./sync-reader');
|
||||||
FilterSync = require('./filter-sync'),
|
var FilterSync = require('./filter-sync');
|
||||||
Parser = require('./parser'),
|
var Parser = require('./parser');
|
||||||
bitmapper = require('./bitmapper');
|
var bitmapper = require('./bitmapper');
|
||||||
|
|
||||||
|
|
||||||
var ParserSync = module.exports = function(buffer, options) {
|
var ParserSync = module.exports = function(buffer, options) {
|
||||||
|
|
||||||
var reader = new SyncReader(buffer);
|
var reader = new SyncReader(buffer);
|
||||||
|
|
||||||
this._inflateDataList = [];
|
this._inflateDataList = [];
|
||||||
this._parser = new Parser(options, {
|
this._parser = new Parser(options, {
|
||||||
read: reader.read.bind(reader),
|
read: reader.read.bind(reader),
|
||||||
error: this._handleError.bind(this),
|
error: this._handleError.bind(this),
|
||||||
metadata: this._metaData.bind(this),
|
metadata: this._metaData.bind(this),
|
||||||
gamma: this._gamma.bind(this),
|
gamma: this._gamma.bind(this),
|
||||||
finished: function() {},
|
finished: function() {
|
||||||
inflateData: this._inflateData.bind(this),
|
},
|
||||||
createData: this._createData.bind(this)
|
inflateData: this._inflateData.bind(this),
|
||||||
});
|
createData: this._createData.bind(this)
|
||||||
this._options = options;
|
});
|
||||||
|
this._options = options;
|
||||||
|
|
||||||
this._parser.start();
|
this._parser.start();
|
||||||
reader.process();
|
reader.process();
|
||||||
|
|
||||||
//join together the inflate datas
|
//join together the inflate datas
|
||||||
var inflateData = Buffer.concat(this._inflateDataList);
|
var inflateData = Buffer.concat(this._inflateDataList);
|
||||||
|
|
||||||
var data = zlib.inflateSync(inflateData);
|
var data = zlib.inflateSync(inflateData);
|
||||||
|
|
||||||
data = FilterSync.process(
|
data = FilterSync.process(
|
||||||
data,
|
data,
|
||||||
this._width, this._height,
|
this._width, this._height,
|
||||||
this._bpp,
|
this._bpp,
|
||||||
this._depth,
|
this._depth,
|
||||||
this._interlace,
|
this._interlace,
|
||||||
this._options
|
this._options
|
||||||
);
|
);
|
||||||
|
|
||||||
this._data = bitmapper.dataToBitMap(data, this._width, this._height,
|
this._data = bitmapper.dataToBitMap(data, this._width, this._height,
|
||||||
this._bpp,
|
this._bpp,
|
||||||
this._depth,
|
this._depth,
|
||||||
this._interlace);
|
this._interlace);
|
||||||
// todo yuck
|
// todo yuck
|
||||||
this.data = this._parser.reverseFiltered(this._data, this._depth, this._width, this._height);
|
this.data = this._parser.reverseFiltered(this._data, this._depth, this._width, this._height);
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserSync.prototype._handleError = function(err) {
|
ParserSync.prototype._handleError = function(err) {
|
||||||
this.err = err;
|
this.err = err;
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserSync.prototype._metaData = function(metaData) {
|
ParserSync.prototype._metaData = function(metaData) {
|
||||||
this.metaData = metaData;
|
this.metaData = metaData;
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserSync.prototype._gamma = function(gamma) {
|
ParserSync.prototype._gamma = function(gamma) {
|
||||||
this.gamma = gamma;
|
this.gamma = gamma;
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserSync.prototype._inflateData = function(data) {
|
ParserSync.prototype._inflateData = function(data) {
|
||||||
this._inflateDataList.push(data);
|
this._inflateDataList.push(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
ParserSync.prototype._createData = function(width, height, bpp, depth, interlace) {
|
ParserSync.prototype._createData = function(width, height, bpp, depth, interlace) {
|
||||||
this._data = new Buffer(width * height * 4);
|
this._data = new Buffer(width * height * 4);
|
||||||
this._bpp = bpp;
|
this._bpp = bpp;
|
||||||
this._width = width;
|
this._width = width;
|
||||||
this._height = height;
|
this._height = height;
|
||||||
this._depth = depth;
|
this._depth = depth;
|
||||||
this._interlace = interlace;
|
this._interlace = interlace;
|
||||||
return this._data;
|
return this._data;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
var constants = require('./constants'),
|
var constants = require('./constants');
|
||||||
CrcCalculator = require('./crc');
|
var CrcCalculator = require('./crc');
|
||||||
|
|
||||||
|
|
||||||
var Parser = module.exports = function(options, dependencies) {
|
var Parser = module.exports = function(options, dependencies) {
|
||||||
|
|
@ -52,7 +52,7 @@ var Parser = module.exports = function(options, dependencies) {
|
||||||
this.parsed = dependencies.parsed;
|
this.parsed = dependencies.parsed;
|
||||||
this.createData = dependencies.createData;
|
this.createData = dependencies.createData;
|
||||||
this.inflateData = dependencies.inflateData;
|
this.inflateData = dependencies.inflateData;
|
||||||
this.finished = dependencies.finished;
|
this.finished = dependencies.finished;
|
||||||
};
|
};
|
||||||
|
|
||||||
var colorTypeToBppMap = {
|
var colorTypeToBppMap = {
|
||||||
|
|
@ -221,7 +221,7 @@ Parser.prototype._parsePLTE = function(data) {
|
||||||
this._palette.push([
|
this._palette.push([
|
||||||
data[i * 3],
|
data[i * 3],
|
||||||
data[i * 3 + 1],
|
data[i * 3 + 1],
|
||||||
data[i * 3 + 2 ],
|
data[i * 3 + 2],
|
||||||
0xff
|
0xff
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,16 @@ var Parser = require('./parser-sync');
|
||||||
|
|
||||||
exports.read = function(buffer, options) {
|
exports.read = function(buffer, options) {
|
||||||
|
|
||||||
options = options || {};
|
var parser = new Parser(buffer, options || {});
|
||||||
var parser = new Parser(buffer, options);
|
|
||||||
|
|
||||||
if (parser.err) {
|
if (parser.err) {
|
||||||
throw parser.err;
|
throw parser.err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: parser.data,
|
data: parser.data,
|
||||||
width: parser._width,
|
width: parser._width,
|
||||||
height: parser._height,
|
height: parser._height,
|
||||||
gamma: parser.gamma || 0
|
gamma: parser.gamma || 0
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
187
lib/png.js
187
lib/png.js
|
|
@ -21,47 +21,47 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
var util = require('util'),
|
var util = require('util');
|
||||||
Stream = require('stream'),
|
var Stream = require('stream');
|
||||||
Parser = require('./parser-async'),
|
var Parser = require('./parser-async');
|
||||||
Packer = require('./packer'),
|
var Packer = require('./packer');
|
||||||
PNGSync = require('./png-sync');
|
var PNGSync = require('./png-sync');
|
||||||
|
|
||||||
|
|
||||||
var PNG = exports.PNG = function(options) {
|
var PNG = exports.PNG = function(options) {
|
||||||
Stream.call(this);
|
Stream.call(this);
|
||||||
|
|
||||||
options = options || {};
|
options = options || {}; // eslint-disable-line no-param-reassign
|
||||||
|
|
||||||
this.width = options.width || 0;
|
this.width = options.width || 0;
|
||||||
this.height = options.height || 0;
|
this.height = options.height || 0;
|
||||||
|
|
||||||
this.data = this.width > 0 && this.height > 0
|
this.data = this.width > 0 && this.height > 0
|
||||||
? new Buffer(4 * this.width * this.height) : null;
|
? new Buffer(4 * this.width * this.height) : null;
|
||||||
|
|
||||||
if(options.fill && this.data){
|
if (options.fill && this.data) {
|
||||||
this.data.fill(0);
|
this.data.fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.gamma = 0;
|
this.gamma = 0;
|
||||||
this.readable = this.writable = true;
|
this.readable = this.writable = true;
|
||||||
|
|
||||||
this._parser = new Parser(options || {});
|
this._parser = new Parser(options || {});
|
||||||
|
|
||||||
this._parser.on('error', this.emit.bind(this, 'error'));
|
this._parser.on('error', this.emit.bind(this, 'error'));
|
||||||
this._parser.on('close', this._handleClose.bind(this));
|
this._parser.on('close', this._handleClose.bind(this));
|
||||||
this._parser.on('metadata', this._metadata.bind(this));
|
this._parser.on('metadata', this._metadata.bind(this));
|
||||||
this._parser.on('gamma', this._gamma.bind(this));
|
this._parser.on('gamma', this._gamma.bind(this));
|
||||||
this._parser.on('parsed', function(data) {
|
this._parser.on('parsed', function(data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.emit('parsed', data);
|
this.emit('parsed', data);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
this._packer = new Packer(options);
|
this._packer = new Packer(options);
|
||||||
this._packer.on('data', this.emit.bind(this, 'data'));
|
this._packer.on('data', this.emit.bind(this, 'data'));
|
||||||
this._packer.on('end', this.emit.bind(this, 'end'));
|
this._packer.on('end', this.emit.bind(this, 'end'));
|
||||||
this._parser.on('close', this._handleClose.bind(this));
|
this._parser.on('close', this._handleClose.bind(this));
|
||||||
this._packer.on('error', this.emit.bind(this, 'error'));
|
this._packer.on('error', this.emit.bind(this, 'error'));
|
||||||
|
|
||||||
};
|
};
|
||||||
util.inherits(PNG, Stream);
|
util.inherits(PNG, Stream);
|
||||||
|
|
@ -70,103 +70,110 @@ PNG.sync = PNGSync;
|
||||||
|
|
||||||
PNG.prototype.pack = function() {
|
PNG.prototype.pack = function() {
|
||||||
|
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
this._packer.pack(this.data, this.width, this.height);
|
this._packer.pack(this.data, this.width, this.height);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PNG.prototype.parse = function(data, callback) {
|
PNG.prototype.parse = function(data, callback) {
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
var onParsed = null, onError = null;
|
var onParsed, onError;
|
||||||
|
|
||||||
this.once('parsed', onParsed = function(parsedData) {
|
onParsed = function(parsedData) {
|
||||||
this.removeListener('error', onError);
|
this.removeListener('error', onError);
|
||||||
|
|
||||||
this.data = parsedData;
|
this.data = parsedData;
|
||||||
callback(null, this);
|
callback(null, this);
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
}.bind(this));
|
onError = function(err) {
|
||||||
|
this.removeListener('parsed', onParsed);
|
||||||
|
|
||||||
this.once('error', onError = function(err) {
|
callback(err, null);
|
||||||
this.removeListener('parsed', onParsed);
|
}.bind(this);
|
||||||
|
|
||||||
callback(err, null);
|
this.once('parsed', onParsed);
|
||||||
}.bind(this));
|
this.once('error', onError);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.end(data);
|
this.end(data);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
PNG.prototype.write = function(data) {
|
PNG.prototype.write = function(data) {
|
||||||
this._parser.write(data);
|
this._parser.write(data);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
PNG.prototype.end = function(data) {
|
PNG.prototype.end = function(data) {
|
||||||
this._parser.end(data);
|
this._parser.end(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
PNG.prototype._metadata = function(metadata) {
|
PNG.prototype._metadata = function(metadata) {
|
||||||
this.width = metadata.width;
|
this.width = metadata.width;
|
||||||
this.height = metadata.height;
|
this.height = metadata.height;
|
||||||
|
|
||||||
this.emit('metadata', metadata);
|
this.emit('metadata', metadata);
|
||||||
};
|
};
|
||||||
|
|
||||||
PNG.prototype._gamma = function(gamma) {
|
PNG.prototype._gamma = function(gamma) {
|
||||||
this.gamma = gamma;
|
this.gamma = gamma;
|
||||||
};
|
};
|
||||||
|
|
||||||
PNG.prototype._handleClose = function() {
|
PNG.prototype._handleClose = function() {
|
||||||
if (!this._parser.writable && !this._packer.readable)
|
if (!this._parser.writable && !this._packer.readable) {
|
||||||
this.emit('close');
|
this.emit('close');
|
||||||
};
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
throw new Error('bitblt reading outside image');
|
|
||||||
if (dx > dst.width || dy > 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PNG.prototype.bitblt = function(dst, sx, sy, w, h, dx, dy) {
|
PNG.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params
|
||||||
|
|
||||||
PNG.bitblt(this, dst, sx, sy, w, h, dx, dy);
|
if (srcX > src.width || srcY > src.height || srcX + width > src.width || srcY + height > src.height) {
|
||||||
return this;
|
throw new Error('bitblt reading outside image');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deltaX > dst.width || deltaY > dst.height || deltaX + width > dst.width || deltaY + height > dst.height) {
|
||||||
|
throw new Error('bitblt writing outside image');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var y = 0; y < height; y++) {
|
||||||
|
src.data.copy(dst.data,
|
||||||
|
((deltaY + y) * dst.width + deltaX) << 2,
|
||||||
|
((srcY + y) * src.width + srcX) << 2,
|
||||||
|
((srcY + y) * src.width + srcX + width) << 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PNG.prototype.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params
|
||||||
|
|
||||||
|
PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
PNG.adjustGamma = function(src) {
|
PNG.adjustGamma = function(src) {
|
||||||
if (src.gamma) {
|
if (src.gamma) {
|
||||||
for (var y = 0; y < src.height; y++) {
|
for (var y = 0; y < src.height; y++) {
|
||||||
for (var x = 0; x < src.width; x++) {
|
for (var x = 0; x < src.width; x++) {
|
||||||
var idx = (src.width * y + x) << 2;
|
var idx = (src.width * y + x) << 2;
|
||||||
|
|
||||||
for (var i = 0; i < 3; i++) {
|
for (var i = 0; i < 3; i++) {
|
||||||
var sample = src.data[idx + i] / 255;
|
var sample = src.data[idx + i] / 255;
|
||||||
sample = Math.pow(sample, 1 / 2.2 / src.gamma);
|
sample = Math.pow(sample, 1 / 2.2 / src.gamma);
|
||||||
src.data[idx + i] = Math.round(sample * 255);
|
src.data[idx + i] = Math.round(sample * 255);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
src.gamma = 0;
|
}
|
||||||
}
|
}
|
||||||
|
src.gamma = 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PNG.prototype.adjustGamma = function() { PNG.adjustGamma(this); };
|
PNG.prototype.adjustGamma = function() {
|
||||||
|
PNG.adjustGamma(this);
|
||||||
|
};
|
||||||
|
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var SyncReader = module.exports = function (buffer) {
|
var SyncReader = module.exports = function(buffer) {
|
||||||
|
|
||||||
this._buffer = buffer;
|
this._buffer = buffer;
|
||||||
this._reads = [];
|
this._reads = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncReader.prototype.read = function (length, callback) {
|
SyncReader.prototype.read = function(length, callback) {
|
||||||
|
|
||||||
this._reads.push({
|
this._reads.push({
|
||||||
length: Math.abs(length), // if length < 0 then at most this length
|
length: Math.abs(length), // if length < 0 then at most this length
|
||||||
|
|
@ -35,7 +35,7 @@ SyncReader.prototype.read = function (length, callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncReader.prototype.process = function () {
|
SyncReader.prototype.process = function() {
|
||||||
|
|
||||||
// as long as there is any data and read requests
|
// as long as there is any data and read requests
|
||||||
while (this._reads.length > 0 && this._buffer.length) {
|
while (this._reads.length > 0 && this._buffer.length) {
|
||||||
|
|
@ -54,13 +54,13 @@ SyncReader.prototype.process = function () {
|
||||||
read.func.call(this, buf.slice(0, read.length));
|
read.func.call(this, buf.slice(0, read.length));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._reads.length > 0) {
|
if (this._reads.length > 0) {
|
||||||
return new Error('There are some read requests waitng on finished stream');
|
return new Error('There are some read requests waitng on finished stream');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._buffer.length > 0) {
|
if (this._buffer.length > 0) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue