// Generated by CoffeeScript 1.4.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. */ (function() { var PNG, fs, zlib; fs = require('fs'); zlib = require('zlib'); module.exports = PNG = (function() { PNG.decode = function(path, fn) { return fs.readFile(path, function(err, file) { var png; png = new PNG(file); return png.decode(function(pixels) { return fn(pixels); }); }); }; PNG.load = function(path) { var file; file = fs.readFileSync(path); return new PNG(file); }; function PNG(data) { var chunkSize, colors, i, index, key, section, short, text, _i, _j, _ref; this.data = data; this.pos = 8; this.palette = []; this.imgData = []; this.transparency = {}; this.text = {}; while (true) { chunkSize = this.readUInt32(); //console.log("chunkSize") //console.log(chunkSize) section = ((function() { var _i, _results; _results = []; for (i = _i = 0; _i < 4; i = ++_i) { _results.push(String.fromCharCode(this.data[this.pos++])); } return _results; }).call(this)).join(''); //console.log("section") //console.log(section) switch (section) { case 'IHDR': this.width = this.readUInt32(); this.height = this.readUInt32(); this.bits = this.data[this.pos++]; this.colorType = this.data[this.pos++]; this.compressionMethod = this.data[this.pos++]; this.filterMethod = this.data[this.pos++]; this.interlaceMethod = this.data[this.pos++]; break; case 'PLTE': this.palette = this.read(chunkSize); break; case 'IDAT': for (i = _i = 0; _i < chunkSize; i = _i += 1) { this.imgData.push(this.data[this.pos++]); } break; case 'tRNS': this.transparency = {}; switch (this.colorType) { case 3: 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) { this.transparency.indexed.push(255); } } break; case 0: this.transparency.grayscale = this.read(chunkSize)[0]; break; case 2: this.transparency.rgb = this.read(chunkSize); } break; case 'tEXt': text = this.read(chunkSize); index = text.indexOf(0); key = String.fromCharCode.apply(String, text.slice(0, index)); this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1)); break; case 'IEND': this.colors = (function() { switch (this.colorType) { case 0: case 3: case 4: return 1; case 2: case 6: return 3; } }).call(this); this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6; colors = this.colors + (this.hasAlphaChannel ? 1 : 0); this.pixelBitlength = this.bits * colors; this.colorSpace = (function() { switch (this.colors) { case 1: return 'DeviceGray'; case 3: return 'DeviceRGB'; } }).call(this); this.imgData = new Buffer(this.imgData); return; default: this.pos += chunkSize; } this.pos += 4; if (this.pos > this.data.length) { throw new Error("Incomplete or corrupt PNG file"); } } return; } 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++]); } return _results; }; PNG.prototype.readUInt32 = function() { var b1, b2, b3, b4; b1 = this.data[this.pos++] << 24; b2 = this.data[this.pos++] << 16; b3 = this.data[this.pos++] << 8; b4 = this.data[this.pos++]; return b1 | b2 | b3 | b4; }; PNG.prototype.readUInt16 = function() { var b1, b2; b1 = this.data[this.pos++] << 8; b2 = this.data[this.pos++]; return b1 | b2; }; PNG.prototype.decodePixels = function(fn) { //console.log("start decodePixels in png-node.js") 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; //console.log("pixelBytes="+ pixelBytes); //console.log("scanlineLength="+ scanlineLength); 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)]; } 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++; } //console.log("in png-node") //console.log("decoded pixels length=" + pixels.length); //console.log("decoded pixels="); //console.log(pixels); return fn(pixels); }); }; PNG.prototype.decodePalette = function() { var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1; 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) { ret[pos++] = palette[i]; ret[pos++] = palette[i + 1]; ret[pos++] = palette[i + 2]; 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; colors = this.colors; palette = null; alpha = this.hasAlphaChannel; if (this.palette.length) { palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette(); colors = 4; alpha = true; } data = (imageData != null ? imageData.data : void 0) || imageData; length = data.length; input = palette || pixels; i = j = 0; if (colors === 1) { while (i < length) { k = palette ? pixels[i / 4] * 4 : j; v = input[k++]; data[i++] = v; data[i++] = v; data[i++] = v; data[i++] = alpha ? input[k++] : 255; j = k; } } else { while (i < length) { k = palette ? pixels[i / 4] * 4 : j; data[i++] = input[k++]; data[i++] = input[k++]; data[i++] = input[k++]; data[i++] = alpha ? input[k++] : 255; j = k; } } }; PNG.prototype.decode = function(fn) { //console.log("another call to decodePixels") var ret, _this = this; ret = new Buffer(this.width * this.height * 4); return this.decodePixels(function(pixels) { _this.copyToImageData(ret, pixels); return fn(ret); }); }; return PNG; })(); }).call(this);