diff --git a/lib/constants.js b/lib/constants.js index 96af8eb..22d919d 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -12,9 +12,23 @@ module.exports = { TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase - COLOR_PALETTE: 1, - COLOR_COLOR: 2, - COLOR_ALPHA: 4, + // color-type bits + COLORTYPE_GRAYSCALE: 0, + COLORTYPE_PALETTE: 1, + COLORTYPE_COLOR: 2, + COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha + + // color-type combinations + COLORTYPE_PALETTE_COLOR: 3, + COLORTYPE_COLOR_ALPHA: 6, + + COLORTYPE_TO_BPP_MAP: { + 0: 1, + 2: 3, + 3: 1, + 4: 2, + 6: 4 + }, GAMMA_DIVISION: 100000 }; diff --git a/lib/packer.js b/lib/packer.js index e342cc8..273b82d 100644 --- a/lib/packer.js +++ b/lib/packer.js @@ -1,6 +1,5 @@ 'use strict'; - var util = require('util'); var Stream = require('stream'); var zlib = require('zlib'); @@ -8,20 +7,24 @@ var filter = require('./filter-pack'); var CrcStream = require('./crc'); var constants = require('./constants'); -var COLORTYPE_TRUECOLOR = 2; -var COLORTYPE_TRUECOLOR_ALPHA = 6; - var Packer = module.exports = function(options) { Stream.call(this); this._options = options; options.deflateChunkSize = options.deflateChunkSize || 32 * 1024; - options.deflateLevel = options.deflateLevel !== null ? options.deflateLevel : 9; - options.deflateStrategy = options.deflateStrategy !== null ? options.deflateStrategy : 3; + options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9; + options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3; options.deflateFactory = options.deflateFactory || zlib.createDeflate; options.bitDepth = options.bitDepth || 8; - options.colorType = (typeof options.colorType === 'number') ? options.colorType : COLORTYPE_TRUECOLOR_ALPHA; + options.colorType = (typeof options.colorType === 'number') ? options.colorType : constants.COLORTYPE_COLOR_ALPHA; + + if (options.colorType !== constants.COLORTYPE_COLOR && options.colorType !== constants.COLORTYPE_COLOR_ALPHA) { + throw new Error('option color type:' + options.colorType + ' is not supported at present'); + } + if (options.bitDepth !== 8) { + throw new Error('option bit depth:' + options.bitDepth + ' is not supported at present'); + } this.readable = true; }; @@ -38,10 +41,7 @@ Packer.prototype.pack = function(data, width, height, gamma) { } // filter pixel data - var bpp = 4; - if (this._options.colorType === COLORTYPE_TRUECOLOR) { - bpp = 3; - } + var bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType]; var filteredData = filter(data, width, height, this._options, bpp); // compress it diff --git a/lib/parser.js b/lib/parser.js index 4573794..ebe5f57 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -36,14 +36,6 @@ var Parser = module.exports = function(options, dependencies) { this.finished = dependencies.finished; }; -var colorTypeToBppMap = { - 0: 1, - 2: 3, - 3: 1, - 4: 2, - 6: 4 -}; - Parser.prototype.start = function() { this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this) @@ -150,7 +142,7 @@ Parser.prototype._parseIHDR = function(data) { this.error(new Error('Unsupported bit depth ' + depth)); return; } - if (!(colorType in colorTypeToBppMap)) { + if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) { this.error(new Error('Unsupported color type')); return; } @@ -169,7 +161,7 @@ Parser.prototype._parseIHDR = function(data) { this._colorType = colorType; - var bpp = colorTypeToBppMap[this._colorType]; + var bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType]; this._hasIHDR = true; @@ -178,9 +170,9 @@ Parser.prototype._parseIHDR = function(data) { height: height, depth: depth, interlace: Boolean(interlace), - palette: Boolean(colorType & constants.COLOR_PALETTE), - color: Boolean(colorType & constants.COLOR_COLOR), - alpha: Boolean(colorType & constants.COLOR_ALPHA), + palette: Boolean(colorType & constants.COLORTYPE_PALETTE), + color: Boolean(colorType & constants.COLORTYPE_COLOR), + alpha: Boolean(colorType & constants.COLORTYPE_ALPHA), bpp: bpp, colorType: colorType }); @@ -221,7 +213,7 @@ Parser.prototype._parseTRNS = function(data) { this._crc.write(data); // palette - if (this._colorType === 3) { + if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) { if (this._palette.length === 0) { this.error(new Error('Transparency chunk must be after palette')); return; @@ -238,11 +230,11 @@ Parser.prototype._parseTRNS = function(data) { // for colorType 0 (grayscale) and 2 (rgb) // there might be one gray/color defined as transparent - if (this._colorType === 0) { + if (this._colorType === constants.COLORTYPE_GRAYSCALE) { // grey, 2 bytes this.transColor([data.readUInt16BE(0)]); } - if (this._colorType === 2) { + if (this._colorType === constants.COLORTYPE_COLOR) { this.transColor([data.readUInt16BE(0), data.readUInt16BE(2), data.readUInt16BE(4)]); } @@ -267,7 +259,7 @@ Parser.prototype._parseIDAT = function(length, data) { this._crc.write(data); - if (this._colorType === 3 && this._palette.length === 0) { + if (this._colorType === constants.COLORTYPE_PALETTE_COLOR && this._palette.length === 0) { throw new Error('Expected palette not found'); } diff --git a/test/bg.png b/test/bg.png index b1885d9..e4361e0 100644 Binary files a/test/bg.png and b/test/bg.png differ diff --git a/test/png-parse-spec.js b/test/png-parse-spec.js index f7f46a6..61aa587 100644 --- a/test/png-parse-spec.js +++ b/test/png-parse-spec.js @@ -55,6 +55,7 @@ test("should correctly parse an 1-bit colormap png", function (t) { if (getPixel(png, x, y) !== 0x000000FF) { t.fail("pixel does not match - " + getPixel(png, x, y) + " !== 0x000000FF"); isOk = false; + break; } } t.ok(isOk, "The pixels should all be black"); @@ -82,6 +83,7 @@ test("should correctly parse an 8-bit grayscale png", function (t) { if (getPixel(png, x, y) !== (x ^ y) * 286331136 + 255) { t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + ((x ^ y) * 286331136 + 255)); isOk = false; + break; } } } @@ -110,6 +112,7 @@ test("should correctly parse an 8-bit truecolor png", function (t) { if (getPixel(png, x, y) !== x * 285212672 + y * 1114112 + (x ^ y) * 4352 + 255) { t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + (x * 285212672 + y * 1114112 + (x ^ y) * 4352 + 255)); isOk = false; + break; } } } @@ -138,12 +141,8 @@ test("should correctly parse an 8-bit truecolor png with alpha", function (t) { if (getPixel(png, x, y) !== x * 285212672 + y * 1114112 + (x ^ y) * 17) { t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + (x * 285212672 + y * 1114112 + (x ^ y) * 17)); isOk = false; + break; } - - t.equal( - getPixel(png, x, y), - x * 285212672 + y * 1114112 + (x ^ y) * 17 - ) } } t.ok(isOk, "The pixels should match"); @@ -205,6 +204,7 @@ test("should correctly read an indexed color image", function (t) { if (getPixel(png, x, y) !== expected) { t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + expected); isOk = false; + break; } } } @@ -249,6 +249,7 @@ test("should correctly read an indexed color image with alpha", function (t) { if (getPixel(png, x, y) !== expected) { t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + expected); isOk = false; + break; } } }