"use strict"; var PNG = function(){ // initialize all members to keep the same hidden class this.width = 0; this.height = 0; this.bitDepth = 0; this.colorType = 0; this.compressionMethod = 0; this.filterMethod = 0; this.interlaceMethod = 0; this.colors = 0; this.alpha = false; this.pixelBits = 0; this.palette = null; this.pixels = null; }; PNG.prototype.getWidth = function(){ return this.width; }; PNG.prototype.setWidth = function(width){ this.width = width; }; PNG.prototype.getHeight = function(){ return this.height; }; PNG.prototype.setHeight = function(height){ this.height = height; }; PNG.prototype.getBitDepth = function(){ return this.bitDepth; }; PNG.prototype.setBitDepth = function(bitDepth){ if ([2, 4, 8, 16].indexOf(bitDepth) === -1){ throw new Error("invalid bith depth " + bitDepth); } this.bitDepth = bitDepth; }; PNG.prototype.getColorType = function(){ return this.colorType; }; PNG.prototype.setColorType = function(colorType){ // Color Allowed Interpretation // Type Bit Depths // // 0 1,2,4,8,16 Each pixel is a grayscale sample. // // 2 8,16 Each pixel is an R,G,B triple. // // 3 1,2,4,8 Each pixel is a palette index; // a PLTE chunk must appear. // // 4 8,16 Each pixel is a grayscale sample, // followed by an alpha sample. // // 6 8,16 Each pixel is an R,G,B triple, // followed by an alpha sample. var colors = 0, alpha = false; switch (colorType){ case 0: colors = 1; break; case 2: colors = 3; break; case 3: colors = 1; break; case 4: colors = 2; alpha = true; break; case 6: colors = 4; alpha = true; break; default: throw new Error("invalid color type"); } this.colors = colors; this.alpha = alpha; this.colorType = colorType; }; PNG.prototype.getCompressionMethod = function(){ return this.compressionMethod; }; PNG.prototype.setCompressionMethod = function(compressionMethod){ if (compressionMethod !== 0){ throw new Error("invalid compression method " + compressionMethod); } this.compressionMethod = compressionMethod; }; PNG.prototype.getFilterMethod = function(){ return this.filterMethod; }; PNG.prototype.setFilterMethod = function(filterMethod){ if (filterMethod !== 0){ throw new Error("invalid filter method " + filterMethod); } this.filterMethod = filterMethod; }; PNG.prototype.getInterlaceMethod = function(){ return this.interlaceMethod; }; PNG.prototype.setInterlaceMethod = function(interlaceMethod){ if (interlaceMethod !== 0 && interlaceMethod !== 1){ throw new Error("invalid interlace method " + interlaceMethod); } this.interlaceMethod = interlaceMethod; }; PNG.prototype.setPalette = function(palette){ if (palette.length % 3 !== 0){ throw new Error("incorrect PLTE chunk length"); } if (palette.length > (Math.pow(2, this.bitDepth) * 3)){ throw new Error("palette has more colors than 2^bitdepth"); } this.palette = palette; }; PNG.prototype.getPalette = function(){ return this.palette; }; /** * get the pixel color on a certain location in a normalized way * result is an array: [red, green, blue, alpha] */ PNG.prototype.getPixel = function(x, y){ if (!this.pixels) throw new Error("pixel data is empty"); if (x >= this.width || y >= this.height){ throw new Error("x,y position out of bound"); } var i = this.colors * this.bitDepth / 8 * (y * this.width + x); var pixels = this.pixels; switch (this.colorType){ case 0: return [pixels[i], pixels[i], pixels[i], 255]; case 2: return [pixels[i], pixels[i + 1], pixels[i + 2], 255]; case 3: return [ this.palette[pixels[i] * 3 + 0], this.palette[pixels[i] * 3 + 1], this.palette[pixels[i] * 3 + 2], 255]; case 4: return [pixels[i], pixels[i], pixels[i], pixels[i + 1]]; case 6: return [pixels[i], pixels[i + 1], pixels[i + 2], pixels[i + 3]]; } }; module.exports = PNG;