From d7a8638b72534848aadcf017608f6f029b2dfa30 Mon Sep 17 00:00:00 2001 From: Luke Page Date: Sun, 13 Sep 2015 19:19:32 +0100 Subject: [PATCH] do not use the output format to determine the input one --- README.md | 14 +++++++ examples/{writePng.js => set-colortype.js} | 17 ++------ lib/bitpacker.js | 47 ++++++++++++++++++++++ lib/packer.js | 7 +++- 4 files changed, 71 insertions(+), 14 deletions(-) rename examples/{writePng.js => set-colortype.js} (67%) create mode 100644 lib/bitpacker.js diff --git a/README.md b/README.md index e22c03c..f5b2b0d 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,8 @@ As input any color type is accepted (grayscale, rgb, palette, grayscale with alp - `deflateStrategy` - compression strategy for delate (default: 3) - `deflateFactory` - deflate stream factory (default: `zlib.createDeflate`) - `filterType` - png filtering method for scanlines (default: -1 => auto, accepts array of numbers 0-4) +- `colorType` - the output colorType - see constants. 2 = color, no alpha, 6 = color & alpha. Default currently 6, but in the future may calculate best mode. +- `inputHasAlpha` - whether the input bitmap has 4 bits per pixel (rgb and alpha) or 3 (rgb - no alpha). ### Event "metadata" @@ -231,6 +233,18 @@ PNG.adjustGamma(png); Changelog ============ +### 1.2.0 - 13/09/2015 + - support passing colorType to write PNG's and writing bitmaps without alpha information + +### 1.1.0 - 07/09/2015 + - support passing a deflate factory for controlled compression + +### 1.0.2 - 22/08/2015 + - Expose all PNG creation info + +### 1.0.1 - 21/08/2015 + - Fix non square interlaced files + ### 1.0.0 - 08/08/2015 - More tests - source linted diff --git a/examples/writePng.js b/examples/set-colortype.js similarity index 67% rename from examples/writePng.js rename to examples/set-colortype.js index de6ac91..7947fb2 100644 --- a/examples/writePng.js +++ b/examples/set-colortype.js @@ -15,28 +15,19 @@ var png = new PNG({ width: w, height:h, bitDepth: 8, - colorType: 2 + colorType: 2, + inputHasAlpha: false }); png.data = bitmapWithoutAlpha; png.pack().pipe(fs.createWriteStream('colortype2.png')); - - -bitmapWithoutAlpha = new Buffer(w * h * 4); -ofs=0; -for (var i = 0; i < bitmapWithoutAlpha.length; i+=4) { - bitmapWithoutAlpha[ofs++] = 0xff; - bitmapWithoutAlpha[ofs++] = i % 0xff; - bitmapWithoutAlpha[ofs++] = (i/4) % 0xff; - bitmapWithoutAlpha[ofs++] = 0xff; -} - var png = new PNG({ width: w, height:h, bitDepth: 8, - colorType: 6 + colorType: 6, + inputHasAlpha: false }); png.data = bitmapWithoutAlpha; diff --git a/lib/bitpacker.js b/lib/bitpacker.js new file mode 100644 index 0000000..6b8eb2a --- /dev/null +++ b/lib/bitpacker.js @@ -0,0 +1,47 @@ +'use strict'; + +var constants = require('./constants'); + +module.exports = function(data, width, height, options) { + var outHasAlpha = options.colorType === constants.COLORTYPE_COLOR_ALPHA; + if (options.inputHasAlpha && outHasAlpha) { + return data; + } + if (!options.inputHasAlpha && !outHasAlpha) { + return data; + } + + var outBpp = outHasAlpha ? 4 : 3; + var outData = new Buffer(width * height * outBpp); + var inBpp = options.inputHasAlpha ? 4 : 3; + var inIndex = 0; + var outIndex = 0; + + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + var red = data[inIndex]; + var green = data[inIndex + 1]; + var blue = data[inIndex + 2]; + + var alpha; + if (options.inputHasAlpha) { + alpha = data[inIndex + 3]; + } + else { + alpha = 255; + } + + outData[outIndex] = red; + outData[outIndex + 1] = green; + outData[outIndex + 2] = blue; + if (outHasAlpha) { + outData[outIndex + 3] = alpha; + } + + inIndex += inBpp; + outIndex += outBpp; + } + } + + return outData; +}; \ No newline at end of file diff --git a/lib/packer.js b/lib/packer.js index 273b82d..7318d21 100644 --- a/lib/packer.js +++ b/lib/packer.js @@ -6,6 +6,7 @@ var zlib = require('zlib'); var filter = require('./filter-pack'); var CrcStream = require('./crc'); var constants = require('./constants'); +var bitPacker = require('./bitpacker'); var Packer = module.exports = function(options) { Stream.call(this); @@ -15,6 +16,7 @@ var Packer = module.exports = function(options) { options.deflateChunkSize = options.deflateChunkSize || 32 * 1024; options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9; options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3; + options.inputHasAlpha = options.inputHasAlpha != null ? options.inputHasAlpha : true; options.deflateFactory = options.deflateFactory || zlib.createDeflate; options.bitDepth = options.bitDepth || 8; options.colorType = (typeof options.colorType === 'number') ? options.colorType : constants.COLORTYPE_COLOR_ALPHA; @@ -40,9 +42,12 @@ Packer.prototype.pack = function(data, width, height, gamma) { this.emit('data', this._packGAMA(gamma)); } + // convert to correct format for filtering (e.g. right bpp and bit depth) + var packedData = bitPacker(data, width, height, this._options); + // filter pixel data var bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType]; - var filteredData = filter(data, width, height, this._options, bpp); + var filteredData = filter(packedData, width, height, this._options, bpp); // compress it var deflate = this._options.deflateFactory({