diff --git a/png-node.coffee b/png-node.coffee index 10e4b2f..84a1eca 100644 --- a/png-node.coffee +++ b/png-node.coffee @@ -132,11 +132,9 @@ module.exports = class PNG b1 = @data[@pos++] << 8 b2 = @data[@pos++] b1 | b2 - - decodePixels: (fn) -> - zlib.inflate @imgData, (err, data) => - throw err if err - + + decodePixels: (fn, sync) -> + worker = (data) => pixelBytes = @pixelBitlength / 8 scanlineLength = pixelBytes * @width @@ -205,7 +203,14 @@ module.exports = class PNG row++ fn pixels - + + if sync + worker (zlib.inflateSync @imgData) + else + zlib.inflate @imgData, (err, data) => + throw err if err + worker data + decodePalette: -> palette = @palette transparency = @transparency.indexed or [] @@ -256,9 +261,10 @@ module.exports = class PNG j = k return - - decode: (fn) -> + + decode: (fn, sync) -> ret = new Buffer(@width * @height * 4) - @decodePixels (pixels) => + worker = (pixels) => @copyToImageData ret, pixels - fn ret \ No newline at end of file + fn ret + @decodePixels worker, sync \ No newline at end of file diff --git a/png-node.js b/png-node.js index 76a5a34..947fe53 100644 --- a/png-node.js +++ b/png-node.js @@ -1,25 +1,24 @@ -// Generated by CoffeeScript 1.4.0 +// Generated by CoffeeScript 1.10.0 /* -# MIT LICENSE -# Copyright (c) 2011 Devon Govett -# -# 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. -*/ - + * MIT LICENSE + * Copyright (c) 2011 Devon Govett + * + * 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. + */ (function() { var PNG, fs, zlib; @@ -29,7 +28,6 @@ zlib = require('zlib'); module.exports = PNG = (function() { - PNG.decode = function(path, fn) { return fs.readFile(path, function(err, file) { var png; @@ -46,9 +44,9 @@ return new PNG(file); }; - function PNG(data) { - var chunkSize, colors, i, index, key, section, short, text, _i, _j, _ref; - this.data = data; + function PNG(data1) { + var chunkSize, colors, i, index, key, l, m, ref, ref1, ref2, section, short, text; + this.data = data1; this.pos = 8; this.palette = []; this.imgData = []; @@ -57,12 +55,12 @@ while (true) { chunkSize = this.readUInt32(); section = ((function() { - var _i, _results; - _results = []; - for (i = _i = 0; _i < 4; i = ++_i) { - _results.push(String.fromCharCode(this.data[this.pos++])); + var l, results; + results = []; + for (i = l = 0; l < 4; i = ++l) { + results.push(String.fromCharCode(this.data[this.pos++])); } - return _results; + return results; }).call(this)).join(''); switch (section) { case 'IHDR': @@ -78,7 +76,7 @@ this.palette = this.read(chunkSize); break; case 'IDAT': - for (i = _i = 0; _i < chunkSize; i = _i += 1) { + for (i = l = 0, ref = chunkSize; l < ref; i = l += 1) { this.imgData.push(this.data[this.pos++]); } break; @@ -89,7 +87,7 @@ this.transparency.indexed = this.read(chunkSize); short = 255 - this.transparency.indexed.length; if (short > 0) { - for (i = _j = 0; 0 <= short ? _j < short : _j > short; i = 0 <= short ? ++_j : --_j) { + for (i = m = 0, ref1 = short; 0 <= ref1 ? m < ref1 : m > ref1; i = 0 <= ref1 ? ++m : --m) { this.transparency.indexed.push(255); } } @@ -119,7 +117,7 @@ return 3; } }).call(this); - this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6; + this.hasAlphaChannel = (ref2 = this.colorType) === 4 || ref2 === 6; colors = this.colors + (this.hasAlphaChannel ? 1 : 0); this.pixelBitlength = this.bits * colors; this.colorSpace = (function() { @@ -144,12 +142,12 @@ } PNG.prototype.read = function(bytes) { - var i, _i, _results; - _results = []; - for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) { - _results.push(this.data[this.pos++]); + var i, l, ref, results; + results = []; + for (i = l = 0, ref = bytes; 0 <= ref ? l < ref : l > ref; i = 0 <= ref ? ++l : --l) { + results.push(this.data[this.pos++]); } - return _results; + return results; }; PNG.prototype.readUInt32 = function() { @@ -168,109 +166,120 @@ return b1 | b2; }; - PNG.prototype.decodePixels = function(fn) { - var _this = this; - return zlib.inflate(this.imgData, function(err, data) { - var byte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m; - if (err) { - throw err; - } - pixelBytes = _this.pixelBitlength / 8; - scanlineLength = pixelBytes * _this.width; - pixels = new Buffer(scanlineLength * _this.height); - length = data.length; - row = 0; - pos = 0; - c = 0; - while (pos < length) { - switch (data[pos++]) { - case 0: - for (i = _i = 0; _i < scanlineLength; i = _i += 1) { - pixels[c++] = data[pos++]; - } - break; - case 1: - for (i = _j = 0; _j < scanlineLength; i = _j += 1) { - byte = data[pos++]; - left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; - pixels[c++] = (byte + left) % 256; - } - break; - case 2: - for (i = _k = 0; _k < scanlineLength; i = _k += 1) { - byte = data[pos++]; - col = (i - (i % pixelBytes)) / pixelBytes; - upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; - pixels[c++] = (upper + byte) % 256; - } - break; - case 3: - for (i = _l = 0; _l < scanlineLength; i = _l += 1) { - byte = data[pos++]; - col = (i - (i % pixelBytes)) / pixelBytes; - left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; - upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; - pixels[c++] = (byte + Math.floor((left + upper) / 2)) % 256; - } - break; - case 4: - for (i = _m = 0; _m < scanlineLength; i = _m += 1) { - byte = data[pos++]; - col = (i - (i % pixelBytes)) / pixelBytes; - left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; - if (row === 0) { - upper = upperLeft = 0; - } else { - upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; - upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)]; + PNG.prototype.decodePixels = function(fn, sync) { + var worker; + worker = (function(_this) { + return function(data) { + var byte, c, col, i, l, left, length, m, n, o, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, q, ref, ref1, ref2, ref3, ref4, row, scanlineLength, upper, upperLeft; + pixelBytes = _this.pixelBitlength / 8; + scanlineLength = pixelBytes * _this.width; + pixels = new Buffer(scanlineLength * _this.height); + length = data.length; + row = 0; + pos = 0; + c = 0; + while (pos < length) { + switch (data[pos++]) { + case 0: + for (i = l = 0, ref = scanlineLength; l < ref; i = l += 1) { + pixels[c++] = data[pos++]; } - p = left + upper - upperLeft; - pa = Math.abs(p - left); - pb = Math.abs(p - upper); - pc = Math.abs(p - upperLeft); - if (pa <= pb && pa <= pc) { - paeth = left; - } else if (pb <= pc) { - paeth = upper; - } else { - paeth = upperLeft; + break; + case 1: + for (i = m = 0, ref1 = scanlineLength; m < ref1; i = m += 1) { + byte = data[pos++]; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + pixels[c++] = (byte + left) % 256; } - pixels[c++] = (byte + paeth) % 256; - } - break; - default: - throw new Error("Invalid filter algorithm: " + data[pos - 1]); + break; + case 2: + for (i = n = 0, ref2 = scanlineLength; n < ref2; i = n += 1) { + byte = data[pos++]; + col = (i - (i % pixelBytes)) / pixelBytes; + upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; + pixels[c++] = (upper + byte) % 256; + } + break; + case 3: + for (i = o = 0, ref3 = scanlineLength; o < ref3; i = o += 1) { + byte = data[pos++]; + col = (i - (i % pixelBytes)) / pixelBytes; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; + pixels[c++] = (byte + Math.floor((left + upper) / 2)) % 256; + } + break; + case 4: + for (i = q = 0, ref4 = scanlineLength; q < ref4; i = q += 1) { + byte = data[pos++]; + col = (i - (i % pixelBytes)) / pixelBytes; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + if (row === 0) { + upper = upperLeft = 0; + } else { + upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; + upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)]; + } + p = left + upper - upperLeft; + pa = Math.abs(p - left); + pb = Math.abs(p - upper); + pc = Math.abs(p - upperLeft); + if (pa <= pb && pa <= pc) { + paeth = left; + } else if (pb <= pc) { + paeth = upper; + } else { + paeth = upperLeft; + } + pixels[c++] = (byte + paeth) % 256; + } + break; + default: + throw new Error("Invalid filter algorithm: " + data[pos - 1]); + } + row++; } - row++; - } - return fn(pixels); - }); + return fn(pixels); + }; + })(this); + if (sync) { + return worker(zlib.inflateSync(this.imgData)); + } else { + return zlib.inflate(this.imgData, (function(_this) { + return function(err, data) { + if (err) { + throw err; + } + return worker(data); + }; + })(this)); + } }; PNG.prototype.decodePalette = function() { - var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1; + var c, i, l, length, palette, pos, ref, ref1, ret, transparency; palette = this.palette; transparency = this.transparency.indexed || []; ret = new Buffer(transparency.length + palette.length); pos = 0; length = palette.length; c = 0; - for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) { + for (i = l = 0, ref = palette.length; l < ref; i = l += 3) { ret[pos++] = palette[i]; ret[pos++] = palette[i + 1]; ret[pos++] = palette[i + 2]; - ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255; + ret[pos++] = (ref1 = transparency[c++]) != null ? ref1 : 255; } return ret; }; PNG.prototype.copyToImageData = function(imageData, pixels) { - var alpha, colors, data, i, input, j, k, length, palette, v, _ref; + var alpha, colors, data, i, input, j, k, length, palette, v; colors = this.colors; palette = null; alpha = this.hasAlphaChannel; if (this.palette.length) { - palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette(); + palette = this._decodedPalette != null ? this._decodedPalette : this._decodedPalette = this.decodePalette(); colors = 4; alpha = true; } @@ -300,14 +309,16 @@ } }; - PNG.prototype.decode = function(fn) { - var ret, - _this = this; + PNG.prototype.decode = function(fn, sync) { + var ret, worker; ret = new Buffer(this.width * this.height * 4); - return this.decodePixels(function(pixels) { - _this.copyToImageData(ret, pixels); - return fn(ret); - }); + worker = (function(_this) { + return function(pixels) { + _this.copyToImageData(ret, pixels); + return fn(ret); + }; + })(this); + return this.decodePixels(worker, sync); }; return PNG;