pngjs-image
Advanced tools
Comparing version 0.11.6 to 0.11.7
@@ -158,4 +158,4 @@ // Copyright 2015 Yahoo! Inc. | ||
* Use this method when you have to do some preliminary | ||
* modifications to the image like decompression, | ||
* applying of changes before the image is scaled. | ||
* modifications to the image or data like decompression, | ||
* applying of changes before the image is scaled, etc. | ||
* | ||
@@ -218,7 +218,7 @@ * @method decode | ||
* @method decodeData | ||
* @param {object} data Data-object that will be used to export values | ||
* @param {object} decodeData Data-object that will be used to export values | ||
* @param {boolean} strict Should parsing be strict? | ||
* @param {object} options Decoding options | ||
*/ | ||
Chunk.prototype.decodeData = function (data, strict, options) { | ||
Chunk.prototype.decodeData = function (decodeData, strict, options) { | ||
// Do nothing by default | ||
@@ -238,6 +238,6 @@ }; | ||
* @method encodeData | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
Chunk.prototype.encodeData = function (data) { | ||
Chunk.prototype.encodeData = function (options) { | ||
// Do nothing by default | ||
@@ -257,5 +257,6 @@ return []; | ||
* @param {Buffer} image | ||
* @param {object} options Encoding options | ||
* @return {Buffer} | ||
*/ | ||
Chunk.prototype.preEncode = function (image) { | ||
Chunk.prototype.preEncode = function (image, options) { | ||
// Do nothing by default | ||
@@ -275,5 +276,6 @@ return image; | ||
* @param {Buffer} image | ||
* @param {object} options Encoding options | ||
* @return {Buffer} | ||
*/ | ||
Chunk.prototype.encode = function (image) { | ||
Chunk.prototype.encode = function (image, options) { | ||
// Do nothing by default | ||
@@ -293,4 +295,5 @@ return image; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
Chunk.prototype.compose = function (stream) { | ||
Chunk.prototype.compose = function (stream, options) { | ||
throw new Error('Unimplemented method "compose".'); | ||
@@ -315,7 +318,8 @@ }; | ||
* @param {string} type Chunk-type | ||
* @param {object} data Object that will holds all the data from the decoded chunks | ||
* @param {object} decodeData Object that will holds all the data from the decoded chunks | ||
* @param {object} chunks Dictionary of already decoded chunks | ||
* @param {boolean} strict Should parsing be strict? | ||
* @param {object} [options] | ||
*/ | ||
Chunk.decodeTypeData = function (type, data, chunks, strict) { | ||
Chunk.decodeTypeData = function (type, decodeData, chunks, strict, options) { | ||
var methods = this.getChunkType(type); | ||
@@ -329,3 +333,3 @@ | ||
methods._staticChunks = chunks; | ||
methods.decodeData(data, strict); | ||
methods.decodeData(decodeData, strict, options); | ||
} | ||
@@ -341,7 +345,7 @@ }; | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that holds all the data that should be encoded | ||
* @param {object} options Encoding options | ||
* @param {object} chunks Dictionary of already determined chunks | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
Chunk.encodeTypeData = function (type, image, data, chunks) { | ||
Chunk.encodeTypeData = function (type, image, options, chunks) { | ||
var methods = this.getChunkType(type); | ||
@@ -355,3 +359,3 @@ | ||
methods._staticChunks = chunks; | ||
return methods.encodeData(image, data); | ||
return methods.encodeData(image, options); | ||
} else { | ||
@@ -462,3 +466,4 @@ return []; | ||
'bKGD', 'cHRM', 'gAMA', 'hIST', 'iCCP', 'IDAT', 'IEND', 'IHDR', // 'iTXt' | ||
'pHYs', 'PLTE', 'sRGB', 'tEXt', 'tIME', 'tRNS', 'zTXt' // 'sBIT', 'sPLT' | ||
'pHYs', 'PLTE', 'sRGB', 'tEXt', 'tIME', 'tRNS', 'zTXt', // 'sBIT', 'sPLT' | ||
'oFFs', 'sCAL', 'sTER' // 'pCAL' | ||
], | ||
@@ -465,0 +470,0 @@ module; |
@@ -229,12 +229,12 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.backgroundColor) { | ||
if (options.backgroundColor) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setColor(data.backgroundColor); | ||
chunk.setColor(options.backgroundColor); | ||
@@ -254,4 +254,5 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -258,0 +259,0 @@ var headerChunk = this.getHeaderChunk(), |
@@ -267,34 +267,34 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.chromaticities) { | ||
if (options.chromaticities) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
if (data.chromaticities.whitePointX !== undefined) { | ||
chunk.setWhitePointX(data.chromaticities.whitePointX); | ||
if (options.chromaticities.whitePointX !== undefined) { | ||
chunk.setWhitePointX(options.chromaticities.whitePointX); | ||
} | ||
if (data.chromaticities.whitePointY !== undefined) { | ||
chunk.setWhitePointY(data.chromaticities.whitePointY); | ||
if (options.chromaticities.whitePointY !== undefined) { | ||
chunk.setWhitePointY(options.chromaticities.whitePointY); | ||
} | ||
if (data.chromaticities.redX !== undefined) { | ||
chunk.setRedX(data.chromaticities.redX); | ||
if (options.chromaticities.redX !== undefined) { | ||
chunk.setRedX(options.chromaticities.redX); | ||
} | ||
if (data.chromaticities.redY !== undefined) { | ||
chunk.setRedY(data.chromaticities.redY); | ||
if (options.chromaticities.redY !== undefined) { | ||
chunk.setRedY(options.chromaticities.redY); | ||
} | ||
if (data.chromaticities.greenX !== undefined) { | ||
chunk.setGreenX(data.chromaticities.greenX); | ||
if (options.chromaticities.greenX !== undefined) { | ||
chunk.setGreenX(options.chromaticities.greenX); | ||
} | ||
if (data.chromaticities.greenY !== undefined) { | ||
chunk.setGreenY(data.chromaticities.greenY); | ||
if (options.chromaticities.greenY !== undefined) { | ||
chunk.setGreenY(options.chromaticities.greenY); | ||
} | ||
if (data.chromaticities.blueX !== undefined) { | ||
chunk.setBlueX(data.chromaticities.blueX); | ||
if (options.chromaticities.blueX !== undefined) { | ||
chunk.setBlueX(options.chromaticities.blueX); | ||
} | ||
if (data.chromaticities.blueY !== undefined) { | ||
chunk.setBlueY(data.chromaticities.blueY); | ||
if (options.chromaticities.blueY !== undefined) { | ||
chunk.setBlueY(options.chromaticities.blueY); | ||
} | ||
@@ -315,4 +315,5 @@ | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
stream.writeUInt32BE(this.getWhitePointX() * 100000); | ||
@@ -319,0 +320,0 @@ stream.writeUInt32BE(this.getWhitePointY() * 100000); |
@@ -165,12 +165,12 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.gamma) { | ||
if (options.gamma) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setGamma(data.gamma); | ||
chunk.setGamma(options.gamma); | ||
@@ -190,6 +190,7 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
stream.writeUInt32BE(this.getGamma() * 100000); | ||
} | ||
}; |
@@ -111,12 +111,12 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.histogram) { | ||
if (options.histogram) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setFrequencies(data.histogram); | ||
chunk.setFrequencies(options.histogram); | ||
@@ -136,4 +136,5 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
if (this._frequency) { | ||
@@ -140,0 +141,0 @@ stream.writeBuffer(this._frequency); |
@@ -124,4 +124,4 @@ // Copyright 2015 Yahoo! Inc. | ||
// Decompress | ||
compressor = new Compressor(); | ||
buffer = compressor.decompress(buffer); | ||
compressor = new Compressor(options); | ||
buffer = compressor.decode(buffer); | ||
@@ -171,13 +171,13 @@ // Set profile | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.ICC) { | ||
if (options.ICC) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setWhitePointX(data.ICC.name); | ||
chunk.setWhitePointY(data.ICC.profile); | ||
chunk.setWhitePointX(options.ICC.name); | ||
chunk.setWhitePointY(options.ICC.profile); | ||
@@ -197,4 +197,5 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -217,4 +218,4 @@ var string, buffer, compressor; | ||
// Compress | ||
compressor = new Compressor(); | ||
buffer = compressor.compress(buffer); | ||
compressor = new Compressor(options); | ||
buffer = compressor.encode(buffer); | ||
@@ -221,0 +222,0 @@ // Write compressed data to stream |
@@ -76,6 +76,7 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
stream.writeBufferedStream(this.getStream()); | ||
} | ||
}; |
@@ -56,6 +56,6 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
@@ -72,6 +72,7 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
// Nothing to do - it is empty | ||
} | ||
}; |
@@ -428,2 +428,13 @@ // Copyright 2015 Yahoo! Inc. | ||
/** | ||
* Gets the dimensions of the image | ||
* | ||
* @method getDimensions | ||
* @return {int} | ||
*/ | ||
getDimensions: function () { | ||
return this.getWidth() * this.getHeight(); | ||
}, | ||
/** | ||
* Parsing of chunk data | ||
@@ -441,2 +452,4 @@ * | ||
var maxWidth, maxHeight, maxDim, maxSize; | ||
// Validation | ||
@@ -476,2 +489,21 @@ if ((strict && (length !== 13)) || (length < 13)) { | ||
} | ||
// Check for de-compression bombs | ||
maxWidth = (options.maxWidth !== undefined) ? options.maxWidth : 0; | ||
if (options.checkBombs && (maxWidth !== 0) && (this.width > maxWidth)) { | ||
throw new Error('Image width is larger than allowed.'); | ||
} | ||
maxHeight = (options.maxHeight !== undefined) ? options.maxHeight : 0; | ||
if (options.checkBombs && (maxHeight !== 0) && (this.height > maxHeight)) { | ||
throw new Error('Image height is larger than allowed.'); | ||
} | ||
maxDim = (options.maxDim !== undefined) ? options.maxDim : 0; | ||
if (options.checkBombs && (maxDim !== 0) && (this.getDimensions() > maxDim)) { | ||
throw new Error('Image resolution is larger than allowed.'); | ||
} | ||
maxSize = (options.maxSize !== undefined) ? options.maxSize : 16 * 1024 * 1024; | ||
if (options.checkBombs && (maxSize !== 0) && (this.getImageSizeInBytes() > maxSize)) { | ||
throw new Error('Image size in byte is larger than allowed.'); | ||
} | ||
}, | ||
@@ -502,15 +534,15 @@ | ||
// Decompress | ||
compressor = new Compressor(); | ||
localImage = compressor.decompress(localImage); | ||
compressor = new Compressor(options); | ||
localImage = compressor.decode(localImage); | ||
// Run through filters | ||
filter = new Filter(this); | ||
localImage = filter.reverse(localImage); | ||
filter = new Filter(this, options); | ||
localImage = filter.decode(localImage); | ||
// Parses scanlines | ||
parser = new Parser(this); | ||
parser = new Parser(this, options); | ||
localImage = parser.decode(localImage); | ||
// Normalizes color values | ||
normalizer = new Normalizer(this); | ||
normalizer = new Normalizer(this, options); | ||
localImage = normalizer.decode(localImage); | ||
@@ -538,8 +570,8 @@ | ||
scaler = new Scaler(this); | ||
scaler = new Scaler(this, options); | ||
localImage = scaler.decode(localImage); | ||
// Run through interlace method | ||
interlace = new Interlace(this); | ||
localImage = interlace.reverse(localImage); | ||
interlace = new Interlace(this, options); | ||
localImage = interlace.decode(localImage); | ||
@@ -620,16 +652,16 @@ return localImage; | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setWidth(data.header.width); | ||
chunk.setHeight(data.header.height); | ||
chunk.setBitDepth(data.header.bitDepth); | ||
chunk.setColorType(data.header.colorType); | ||
chunk.setCompressionMethod(data.header.compression); | ||
chunk.setFilterMethod(data.header.filter); | ||
chunk.setInterlaceMethod(data.header.interlace); | ||
chunk.setWidth(options.header.width); | ||
chunk.setHeight(options.header.height); | ||
chunk.setBitDepth(options.header.bitDepth); | ||
chunk.setColorType(options.header.colorType); | ||
chunk.setCompressionMethod(options.header.compression); | ||
chunk.setFilterMethod(options.header.filter); | ||
chunk.setInterlaceMethod(options.header.interlace); | ||
@@ -649,5 +681,6 @@ return [chunk]; | ||
* @param {Buffer} image | ||
* @param {object} options Encoding options | ||
* @return {Buffer} | ||
*/ | ||
preEncode: function (image) { | ||
preEncode: function (image, options) { | ||
@@ -659,3 +692,3 @@ var imageStream, scaledStream, reducedStream, withdrawnStream, | ||
interlace = new Interlace(this); | ||
image = interlace.interlace(image, 0); | ||
image = interlace.encode(image, options); | ||
@@ -722,5 +755,6 @@ if (this.isColorTypeIndexedColor()) { | ||
* @param {Buffer} image | ||
* @param {object} options Encoding options | ||
* @return {Buffer} | ||
*/ | ||
encode: function (image) { | ||
encode: function (image, options) { | ||
@@ -731,11 +765,11 @@ var compressor, | ||
// Run through filters | ||
filter = new Filter(this); | ||
image = filter.filter(image, 0); | ||
filter = new Filter(this, options); | ||
image = filter.encode(image); | ||
// Compress | ||
compressor = new Compressor(); | ||
image = compressor.compress(image); | ||
compressor = new Compressor(options); | ||
image = compressor.encode(image); | ||
// Combine all data chunks | ||
this._separate(image); | ||
// Separate image to data chunks | ||
this._separate(image, options); | ||
@@ -753,4 +787,5 @@ // Finished since this is the last chunk | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
stream.writeUInt32BE(this.getWidth()); | ||
@@ -770,7 +805,9 @@ stream.writeUInt32BE(this.getHeight()); | ||
* @param {Buffer} buffer | ||
* @param {object} options Encoding options | ||
* @param {int} [options.chunkSize=8192] Max. size of the IDAT chunk | ||
* @private | ||
*/ | ||
_separate: function (buffer) { | ||
_separate: function (buffer, options) { | ||
var chunkLength = 8192, | ||
var chunkLength = options.chunkSize || 8192, | ||
chunkQuantity = Math.ceil(buffer.length / chunkLength), | ||
@@ -777,0 +814,0 @@ |
@@ -61,6 +61,6 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
//TODO | ||
@@ -77,4 +77,5 @@ return []; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
throw new Error('Not implemented!'); | ||
@@ -81,0 +82,0 @@ //TODO |
// Copyright 2015 Yahoo! Inc. | ||
// Copyrights licensed under the Mit License. See the accompanying LICENSE file for terms. | ||
var units = require('../utils/constants').units; | ||
var units = require('../utils/constants').physicalUnits; | ||
@@ -161,3 +161,3 @@ /** | ||
data.physical = { | ||
data.physicalSize = { | ||
xPixelPerUnit: chunks[0].getXPixelPerUnit(), | ||
@@ -178,19 +178,19 @@ yPixelPerUnit: chunks[0].getYPixelPerUnit(), | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.physical) { | ||
if (options.physicalSize) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
if (data.physical.xPixelPerUnit !== undefined) { | ||
chunk.setXPixelPerUnit(data.physical.xPixelPerUnit); | ||
if (options.physicalSize.xPixelPerUnit !== undefined) { | ||
chunk.setXPixelPerUnit(options.physicalSize.xPixelPerUnit); | ||
} | ||
if (data.physical.yPixelPerUnit !== undefined) { | ||
chunk.setYPixelPerUnit(data.physical.yPixelPerUnit); | ||
if (options.physicalSize.yPixelPerUnit !== undefined) { | ||
chunk.setYPixelPerUnit(options.physicalSize.yPixelPerUnit); | ||
} | ||
if (data.physical.unit !== undefined) { | ||
chunk.setUnit(data.physical.unit); | ||
if (options.physicalSize.unit !== undefined) { | ||
chunk.setUnit(options.physicalSize.unit); | ||
} | ||
@@ -211,4 +211,5 @@ | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
stream.writeUInt32BE(this.getXPixelPerUnit()); | ||
@@ -215,0 +216,0 @@ stream.writeUInt32BE(this.getYPixelPerUnit()); |
@@ -226,12 +226,12 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.paletteColors) { | ||
if (options.paletteColors) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setColors(data.paletteColors); | ||
chunk.setColors(options.paletteColors); | ||
@@ -251,5 +251,6 @@ return [chunk]; | ||
* @param {Buffer} image | ||
* @param {object} options Encoding options | ||
* @return {Buffer} | ||
*/ | ||
preEncode: function (image) { | ||
preEncode: function (image, options) { | ||
@@ -299,4 +300,5 @@ var i, len, | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -303,0 +305,0 @@ var i, len, |
@@ -68,6 +68,6 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
//TODO | ||
@@ -84,4 +84,5 @@ return []; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
throw new Error('Not implemented!'); | ||
@@ -88,0 +89,0 @@ //TODO |
@@ -62,6 +62,6 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
//TODO | ||
@@ -78,4 +78,5 @@ return []; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
throw new Error('Not implemented!'); | ||
@@ -82,0 +83,0 @@ //TODO |
@@ -152,12 +152,12 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.renderingIntent) { | ||
if (options.renderingIntent) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setRenderingIntent(data.renderingIntent); | ||
chunk.setRenderingIntent(options.renderingIntent); | ||
@@ -177,6 +177,7 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
stream.writeUInt8(this.getRenderingIntent()); | ||
} | ||
}; |
@@ -158,8 +158,8 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.texts) { | ||
if (options.texts) { | ||
@@ -171,3 +171,3 @@ var chunk, | ||
data.texts.forEach(function (text) { | ||
options.texts.forEach(function (text) { | ||
@@ -200,4 +200,5 @@ chunk = this.createChunk(type, chunks); | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -204,0 +205,0 @@ var string, buffer; |
@@ -113,12 +113,12 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.modificationDate) { | ||
if (options.modificationDate) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setDate(data.modificationDate); | ||
chunk.setDate(options.modificationDate); | ||
@@ -138,4 +138,5 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -142,0 +143,0 @@ var date = this.getDate(); |
@@ -272,12 +272,12 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.transparentColors) { | ||
if (options.transparentColors) { | ||
var chunk = this.createChunk(this.getType(), this.getChunks()); | ||
chunk.setColors(data.transparentColors); | ||
chunk.setColors(options.transparentColors); | ||
@@ -297,4 +297,5 @@ return [chunk]; | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -301,0 +302,0 @@ var headerChunk, paletteChunk, |
@@ -129,4 +129,4 @@ // Copyright 2015 Yahoo! Inc. | ||
// Decompress | ||
compressor = new Compressor(); | ||
buffer = compressor.decompress(buffer); | ||
compressor = new Compressor(options); | ||
buffer = compressor.decode(buffer); | ||
@@ -176,8 +176,8 @@ // Convert text content from latin1 | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.compressedTexts) { | ||
if (options.compressedTexts) { | ||
@@ -189,3 +189,3 @@ var chunk, | ||
data.compressedTexts.forEach(function (text) { | ||
options.compressedTexts.forEach(function (text) { | ||
@@ -218,4 +218,5 @@ chunk = this.createChunk(type, chunks); | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -240,4 +241,4 @@ var string, buffer, compressor; | ||
// Compress | ||
compressor = new Compressor(); | ||
buffer = compressor.compress(buffer); | ||
compressor = new Compressor(options); | ||
buffer = compressor.encode(buffer); | ||
@@ -244,0 +245,0 @@ // Write compressed data to stream |
@@ -118,4 +118,4 @@ // Copyright 2015 Yahoo! Inc. | ||
// Decompress | ||
compressor = new Compressor(); | ||
data = compressor.decompress(data); | ||
compressor = new Compressor(options); | ||
data = compressor.decode(data); | ||
@@ -164,8 +164,8 @@ // Convert buffer into string | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.JSON) { | ||
if (options.JSON) { | ||
@@ -176,3 +176,3 @@ var result = [], | ||
data.JSON.forEach(function (entry) { | ||
options.JSON.forEach(function (entry) { | ||
@@ -201,4 +201,5 @@ var chunk = this.createChunk(type, chunks); | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -214,4 +215,4 @@ var compressor, | ||
// Compress the data | ||
compressor = new Compressor(); | ||
data = compressor.compress(new Buffer(dataStr, 'utf8')); | ||
compressor = new Compressor(options); | ||
data = compressor.encode(new Buffer(dataStr, 'utf8')); | ||
@@ -218,0 +219,0 @@ // Write title to stream |
@@ -154,4 +154,4 @@ // Copyright 2015 Yahoo! Inc. | ||
// Decompress | ||
compressor = new Compressor(); | ||
data = compressor.decompress(data); | ||
compressor = new Compressor(options); | ||
data = compressor.decode(data); | ||
@@ -203,8 +203,8 @@ // Convert buffer into string | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.structures) { | ||
if (options.structures) { | ||
@@ -215,3 +215,3 @@ var result = [], | ||
data.structures.forEach(function (structure) { | ||
options.structures.forEach(function (structure) { | ||
@@ -250,4 +250,5 @@ var chunk = this.createChunk(type, chunks); | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
@@ -261,4 +262,4 @@ var compressor, | ||
// Compress the data | ||
compressor = new Compressor(); | ||
data = compressor.compress(new Buffer(dataStr, 'utf8')); | ||
compressor = new Compressor(options); | ||
data = compressor.encode(new Buffer(dataStr, 'utf8')); | ||
@@ -265,0 +266,0 @@ // Write the data-type |
@@ -138,8 +138,8 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Buffer} image Image data | ||
* @param {object} data Object that will be used to import data to the chunk | ||
* @param {object} options Encoding options | ||
* @return {Chunk[]} List of chunks to encode | ||
*/ | ||
encodeData: function (image, data) { | ||
encodeData: function (image, options) { | ||
if (data.unknownChunks) { | ||
if (options.unknownChunks) { | ||
@@ -150,3 +150,3 @@ var result = [], | ||
data.unknownChunks.forEach(function (info) { | ||
options.unknownChunks.forEach(function (info) { | ||
@@ -179,6 +179,7 @@ var chunk = this.createChunk(type, chunks); | ||
* @param {BufferedStream} stream Data stream | ||
* @param {object} options Encoding options | ||
*/ | ||
compose: function (stream) { | ||
compose: function (stream, options) { | ||
stream.writeBuffer(this.getBuffer()); | ||
} | ||
}; |
@@ -40,2 +40,3 @@ // Copyright 2015 Yahoo! Inc. | ||
/** | ||
@@ -45,7 +46,7 @@ * Decodes the supplied data | ||
* @method decode | ||
* @param {Buffer} data Image data | ||
* @param {Buffer} buffer Image data | ||
* @param {object} [options] Decoding options | ||
* @param {boolean} [options.strict=false] Strict decoding | ||
*/ | ||
Decoder.prototype.decode = function (data, options) { | ||
Decoder.prototype.decode = function (buffer, options) { | ||
@@ -59,3 +60,3 @@ options = options || {}; | ||
strict = !!options.strict, | ||
stream = new BufferedStream(data, false); | ||
stream = new BufferedStream(buffer, false); | ||
@@ -62,0 +63,0 @@ this._chunks = {}; |
@@ -52,2 +52,4 @@ // Copyright 2015 Yahoo! Inc. | ||
options = options || {}; | ||
var i, len, | ||
@@ -59,8 +61,8 @@ stream, | ||
this._chunks = {}; | ||
this._chunkData = options || {}; | ||
this._chunkData = options; | ||
// Use optimization to figure out what format to safe in | ||
this._optimize(buffer, width, height, this._chunkData); | ||
// Use optimization to figure out what format to safe it in | ||
this._optimize(buffer, width, height, options); | ||
// Run through all chunks-types (not chunks) to gather chunks | ||
// Run through all chunk-types (not chunks) to gather chunks | ||
// Phase 1 - Forward | ||
@@ -70,3 +72,3 @@ this.applyWithSortedChunks(function (chunk) { | ||
// Figure out which chunks we need for the image | ||
var chunks = Chunk.encodeTypeData(chunk.getType(), image, this._chunkData, this._chunks); | ||
var chunks = Chunk.encodeTypeData(chunk.getType(), image, options, this._chunks); | ||
@@ -83,3 +85,3 @@ // Add all returned chunks | ||
this.applyWithSortedChunks(function (chunk) { | ||
buffer = chunk.preEncode(buffer); | ||
buffer = chunk.preEncode(buffer, options); | ||
}, true, true); | ||
@@ -91,3 +93,3 @@ | ||
this.applyWithSortedChunks(function (chunk) { | ||
buffer = chunk.encode(buffer); | ||
buffer = chunk.encode(buffer, options); | ||
}, true, true); | ||
@@ -105,3 +107,3 @@ | ||
this.applyWithSortedChunks(function (chunk) { | ||
this._encodeChunk(stream, chunk); | ||
this._encodeChunk(stream, chunk, options); | ||
}.bind(this), true, false); | ||
@@ -118,5 +120,6 @@ | ||
* @param {Chunk} chunk Chunk that should be serialized to the stream | ||
* @param {object} options Encoding options | ||
* @private | ||
*/ | ||
Encoder.prototype._encodeChunk = function (stream, chunk) { | ||
Encoder.prototype._encodeChunk = function (stream, chunk, options) { | ||
@@ -134,3 +137,3 @@ var crc, | ||
crcStartOffset = stream.writeOffset; | ||
if (chunk.getInternalType) { | ||
if (chunk.getInternalType) { // Use this for unknown chunks | ||
stream.writeASCIIString(chunk.getInternalType()); | ||
@@ -143,3 +146,3 @@ } else { | ||
stream.writeCounter = 0; | ||
chunk.compose(stream); | ||
chunk.compose(stream, options); | ||
chunkLength = stream.writeCounter; | ||
@@ -163,20 +166,21 @@ | ||
* @param {int} height Height of image | ||
* @param {object} data Object that holds all the data that should be encoded | ||
* @param {object} options Encoding options | ||
* @private | ||
*/ | ||
Encoder.prototype._optimize = function (image, width, height, data) { | ||
Encoder.prototype._optimize = function (image, width, height, options) { | ||
// Setup header data | ||
data.header = data.header || {}; | ||
data.header.width = width; | ||
data.header.height = height; | ||
options.header = options.header || {}; | ||
options.header.width = width; | ||
options.header.height = height; | ||
// Default configuration | ||
data.header.bitDepth = 8; | ||
data.header.colorType = 6; // True-color | ||
data.header.compression = 0; // Deflate | ||
data.header.filter = 0; // Default | ||
data.header.interlace = 0; // Default - non-streaming | ||
options.header.bitDepth = 8; | ||
options.header.colorType = 6; // True-color | ||
options.header.compression = 0; // Deflate | ||
options.header.filter = 0; // Default | ||
options.header.interlace = options.interlace || 0; // Default - non-streaming | ||
}; | ||
module.exports = Encoder; |
@@ -10,7 +10,7 @@ // Copyright 2015 Yahoo! Inc. | ||
* @submodule PNGCore | ||
* @param {object} options Options for the compressor | ||
* @param {object} [options] Options for the compressor | ||
* @constructor | ||
*/ | ||
var Compressor = function (options) { | ||
this._options = options; | ||
this._options = options || {}; | ||
}; | ||
@@ -32,7 +32,7 @@ | ||
* | ||
* @method compress | ||
* @method encode | ||
* @param {Buffer} data | ||
* @return {Buffer} | ||
*/ | ||
Compressor.prototype.compress = function (data) { | ||
Compressor.prototype.encode = function (data) { | ||
if (!zlib.deflateSync) { | ||
@@ -48,7 +48,7 @@ return new Buffer(require("pako").deflate(data, this.getOptions())); | ||
* | ||
* @method decompress | ||
* @method decode | ||
* @param {Buffer} data | ||
* @return {Buffer} | ||
*/ | ||
Compressor.prototype.decompress = function (data) { | ||
Compressor.prototype.decode = function (data) { | ||
if (!zlib.inflateSync) { | ||
@@ -55,0 +55,0 @@ return new Buffer(require("pako").inflate(data, this.getOptions())); |
@@ -5,2 +5,3 @@ // Copyright 2015 Yahoo! Inc. | ||
var Interlace = require('./interlace'); | ||
var Compressor = require('./compressor'); | ||
@@ -12,9 +13,21 @@ /** | ||
* @param {Chunk} headerChunk Header chunk of data stream | ||
* @param {object} [options] Options for the compressor | ||
* @constructor | ||
*/ | ||
var Filter = function (headerChunk) { | ||
var Filter = function (headerChunk, options) { | ||
this._headerChunk = headerChunk; | ||
this._options = options || {}; | ||
}; | ||
/** | ||
* Gets the options | ||
* | ||
* @method getOptions | ||
* @return {object} | ||
*/ | ||
Filter.prototype.getOptions = function () { | ||
return this._options; | ||
}; | ||
/** | ||
@@ -34,8 +47,49 @@ * Gets the header chunk | ||
* | ||
* @method filter | ||
* @method encode | ||
* @param {Buffer} image | ||
* @return {Buffer} | ||
*/ | ||
Filter.prototype.filter = function (image) { | ||
return this._filter(image); | ||
Filter.prototype.encode = function (image) { | ||
var headerChunk = this.getHeaderChunk(), | ||
interlace = new Interlace(headerChunk), | ||
bytesPerPixel = headerChunk.getBytesPerPixel(), | ||
bytesPerPosition = Math.max(1, bytesPerPixel), | ||
outputData, | ||
length = 0, | ||
info = {}, | ||
options = this.getOptions(); | ||
// Determine required size of buffer | ||
interlace.processPasses(function (width, height, scanLineLength) { | ||
length += (scanLineLength + 1) * height; | ||
}); | ||
outputData = new Buffer(length); | ||
// Process each interlace pass (or only one for non-interlaced images) | ||
interlace.processPasses(function (width, height, scanLineLength) { | ||
info = { | ||
inputData: image, | ||
inputOffset: info.inputOffset || 0, | ||
outputData: outputData, | ||
outputOffset: info.outputOffset || 0, | ||
bytesPerPosition: bytesPerPosition, | ||
scanLineLength: scanLineLength, | ||
scanLines: height, | ||
previousLineOffset: null | ||
}; | ||
this._encode(info, options); | ||
}.bind(this)); | ||
return outputData; | ||
}; | ||
@@ -46,42 +100,104 @@ | ||
* | ||
* @method _filter | ||
* @param {Buffer} image | ||
* @return {Buffer} | ||
* @method _encode | ||
* @param {object} info Information for filtering process | ||
* @param {object} options Options for encoding | ||
* @private | ||
*/ | ||
Filter.prototype._filter = function (image) { | ||
Filter.prototype._encode = function (info, options) { | ||
var input, | ||
output, | ||
headerChunk = this.getHeaderChunk(), | ||
width = headerChunk.getWidth(), | ||
height = headerChunk.getHeight(), | ||
bytesPerPixel = headerChunk.getImageBytesPerPixel(); | ||
var filterType = options.filter || 0, | ||
filterMapping; | ||
input = { | ||
data: image, | ||
offset: 0, | ||
previousLineOffset: null, | ||
width: width, | ||
height: height, | ||
bytesPerPixel: bytesPerPixel, | ||
bytesPerPosition: Math.max(1, bytesPerPixel), | ||
scanLineLength: width * bytesPerPixel // TODO: Is this right? | ||
// Reverse mapping for filter-types | ||
filterMapping = { | ||
0: this._encodeNone, | ||
1: this._encodeSub, | ||
2: this._encodeUp, | ||
3: this._encodeAverage, | ||
4: this._encodePaeth, | ||
5: this._optimalEncode // Auto | ||
}; | ||
output = { | ||
previousLineOffset: null, | ||
data: new Buffer((width * height * input.bytesPerPixel) + height), // Add height-times filter-type byte | ||
//TODO: Resolution is not right anymore - see decoder | ||
offset: 0 | ||
// Validate options given | ||
if (!filterMapping[filterType]) { | ||
throw new Error('Unknown filter-type ' + filterType + ' was selected.'); | ||
} | ||
// Run through all scanlines | ||
for (var y = 0; y < info.scanLines; y++) { | ||
// Reverse per filter-type | ||
filterMapping[filterType].call(this, info, options); | ||
info.previousLineOffset = info.inputOffset; | ||
info.inputOffset += info.scanLineLength; | ||
info.outputOffset += info.scanLineLength + 1; | ||
} | ||
}; | ||
/** | ||
* Applies the optimal filter to the data | ||
* | ||
* Note: | ||
* Since it compresses only a subset of the data, this might not be really the optimal filter. | ||
* But, it is close enough. | ||
* | ||
* @method _optimalEncode | ||
* @param {object} info Information for filtering process | ||
* @param {object} options Options for encoding | ||
* @private | ||
*/ | ||
Filter.prototype._optimalEncode = function (info, options) { | ||
var filterList = [4, 3, 2, 1, 0], | ||
filterType, | ||
filterMapping, | ||
compressor = new Compressor(options), | ||
length, | ||
lowestSize = null, | ||
lowestFilter = 0, | ||
// Backup of real data | ||
originalOutputData = info.outputData, | ||
originalOutputOffset = info.outputOffset; | ||
// Reverse mapping for actual filter-types | ||
filterMapping = { | ||
0: this._encodeNone, | ||
1: this._encodeSub, | ||
2: this._encodeUp, | ||
3: this._encodeAverage, | ||
4: this._encodePaeth | ||
}; | ||
for (var y = 0; y < height; y++) { | ||
//TODO: Find a better way than just use the simplest | ||
this._filterNone(input, output); | ||
input.previousLineOffset = input.offset; | ||
input.offset += input.scanLineLength; | ||
output.offset += input.scanLineLength + 1; | ||
// Create temp buffer for size testing | ||
info.outputData = new Buffer(info.scanLineLength + 1); | ||
info.outputOffset = 0; | ||
// Walk through all filters to see which one is the best one | ||
while(filterList.length > 0) { | ||
// Use next filter in the list | ||
filterType = filterList.pop(); | ||
filterMapping[filterType].call(this, info); | ||
// Trial compress | ||
length = compressor.encode(info.outputData).length; | ||
// Is this the best filter for the compression? (Prefer low complexity filters) | ||
if ((lowestSize === null) || (lowestSize > length)) { | ||
lowestSize = length; | ||
lowestFilter = filterType; | ||
} | ||
} | ||
return output.data; | ||
// Recover original data | ||
info.outputData = originalOutputData; | ||
info.outputOffset = originalOutputOffset; | ||
// Apply optimal filter | ||
filterMapping[lowestFilter].call(this, info); | ||
}; | ||
@@ -92,10 +208,9 @@ | ||
* | ||
* @method _filterNone | ||
* @param {object} input Input data | ||
* @param {object} output Output data | ||
* @method _encodeNone | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._filterNone = function (input, output) { | ||
output.data[output.offset] = 0; | ||
input.data.copy(output.data, output.offset + 1, input.offset, input.offset + input.scanLineLength); | ||
Filter.prototype._encodeNone = function (info) { | ||
info.outputData[info.outputOffset] = 0; | ||
info.inputData.copy(info.outputData, info.outputOffset + 1, info.inputOffset, info.inputOffset + info.scanLineLength); | ||
}; | ||
@@ -106,11 +221,10 @@ | ||
* | ||
* @method _filterSub | ||
* @param {object} input Input data | ||
* @param {object} output Output data | ||
* @method _encodeSub | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._filterSub = function (input, output) { | ||
output.data[output.offset] = 1; | ||
for (var x = 0; x < input.scanLineLength; x++) { | ||
output.data[output.offset + x + 1] = Math.abs(this._getPixel(input, x) - this._getLeftPixel(input, x)); | ||
Filter.prototype._encodeSub = function (info) { | ||
info.outputData[info.outputOffset] = 1; | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x + 1] = this._getInputPixel(info, x) - this._getLeftInputPixel(info, x); | ||
} | ||
@@ -122,11 +236,10 @@ }; | ||
* | ||
* @method _filterUp | ||
* @param {object} input Input data | ||
* @param {object} output Output data | ||
* @method _encodeUp | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._filterUp = function (input, output) { | ||
output.data[output.offset] = 2; | ||
for (var x = 0; x < input.scanLineLength; x++) { | ||
output.data[output.offset + x + 1] = Math.abs(this._getPixel(input, x) - this._getTopPixel(input, x)); | ||
Filter.prototype._encodeUp = function (info) { | ||
info.outputData[info.outputOffset] = 2; | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x + 1] = this._getInputPixel(info, x) - this._getTopInputPixel(info, x); | ||
} | ||
@@ -138,11 +251,10 @@ }; | ||
* | ||
* @method _filterAverage | ||
* @param {object} input Input data | ||
* @param {object} output Output data | ||
* @method _encodeAverage | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._filterAverage = function (input, output) { | ||
output.data[output.offset] = 3; | ||
for (var x = 0; x < input.scanLineLength; x++) { | ||
output.data[output.offset + x + 1] = Math.abs(this._getPixel(input, x) - Math.floor((this._getLeftPixel(input, x) + this._getTopPixel(input, x)) / 2)); | ||
Filter.prototype._encodeAverage = function (info) { | ||
info.outputData[info.outputOffset] = 3; | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x + 1] = this._getInputPixel(info, x) - Math.floor((this._getLeftInputPixel(info, x) + this._getTopInputPixel(info, x)) / 2); | ||
} | ||
@@ -154,16 +266,13 @@ }; | ||
* | ||
* @method _filterPaeth | ||
* @param {object} input Input data | ||
* @param {object} output Output data | ||
* @method _encodePaeth | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._filterPaeth = function (input, output) { | ||
output.data[output.offset] = 4; | ||
for (var x = 0; x < input.scanLineLength; x++) { | ||
output.data[output.offset + x + 1] = Math.abs( | ||
this._getPixel(input, x) - this._paethPredictor( | ||
this._getLeftPixel(input, x), | ||
this._getTopPixel(input, x), | ||
this._getTopLeftPixel(input, x) | ||
) | ||
Filter.prototype._encodePaeth = function (info) { | ||
info.outputData[info.outputOffset] = 4; | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x + 1] = this._getInputPixel(info, x) - this._paethPredictor( | ||
this._getLeftInputPixel(info, x), | ||
this._getTopInputPixel(info, x), | ||
this._getTopLeftInputPixel(info, x) | ||
); | ||
@@ -177,7 +286,7 @@ } | ||
* | ||
* @method reverse | ||
* @method decode | ||
* @param {Buffer} image | ||
* @return {Buffer} Reversed data | ||
*/ | ||
Filter.prototype.reverse = function (image) { | ||
Filter.prototype.decode = function (image) { | ||
@@ -192,3 +301,4 @@ var headerChunk = this.getHeaderChunk(), | ||
length = 0, | ||
info = {}; | ||
info = {}, | ||
options = this.getOptions(); | ||
@@ -220,3 +330,3 @@ // Determine required size of buffer | ||
this._reverse(info); | ||
this._decode(info, options); | ||
@@ -231,7 +341,8 @@ }.bind(this)); | ||
* | ||
* @method _reverse | ||
* @method _decode | ||
* @param {object} info | ||
* @param {object} options | ||
* @private | ||
*/ | ||
Filter.prototype._reverse = function (info) { | ||
Filter.prototype._decode = function (info, options) { | ||
@@ -243,7 +354,7 @@ var filterType, | ||
filterMapping = { | ||
0: this._reverseNone, | ||
1: this._reverseSub, | ||
2: this._reverseUp, | ||
3: this._reverseAverage, | ||
4: this._reversePaeth | ||
0: this._decodeNone, | ||
1: this._decodeSub, | ||
2: this._decodeUp, | ||
3: this._decodeAverage, | ||
4: this._decodePaeth | ||
}; | ||
@@ -273,7 +384,7 @@ | ||
* | ||
* @method _reverseNone | ||
* @method _decodeNone | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._reverseNone = function (info) { | ||
Filter.prototype._decodeNone = function (info) { | ||
info.inputData.copy(info.outputData, info.outputOffset, info.inputOffset, info.inputOffset + info.scanLineLength); | ||
@@ -285,9 +396,9 @@ }; | ||
* | ||
* @method _reverseSub | ||
* @method _decodeSub | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._reverseSub = function (info) { | ||
Filter.prototype._decodeSub = function (info) { | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x] = (this._getPixel(info, x) + this._getLeftPixel(info, x)) & 0xff; | ||
info.outputData[info.outputOffset + x] = (this._getInputPixel(info, x) + this._getLeftOutputPixel(info, x)) & 0xff; | ||
} | ||
@@ -299,9 +410,9 @@ }; | ||
* | ||
* @method _reverseUp | ||
* @method _decodeUp | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._reverseUp = function (info) { | ||
Filter.prototype._decodeUp = function (info) { | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x] = (this._getPixel(info, x) + this._getTopPixel(info, x)) & 0xff; | ||
info.outputData[info.outputOffset + x] = (this._getInputPixel(info, x) + this._getTopOutputPixel(info, x)) & 0xff; | ||
} | ||
@@ -313,9 +424,9 @@ }; | ||
* | ||
* @method _reverseAverage | ||
* @method _decodeAverage | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._reverseAverage = function (info) { | ||
Filter.prototype._decodeAverage = function (info) { | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x] = (this._getPixel(info, x) + Math.floor((this._getLeftPixel(info, x) + this._getTopPixel(info, x)) / 2)) & 0xff; | ||
info.outputData[info.outputOffset + x] = (this._getInputPixel(info, x) + Math.floor((this._getLeftOutputPixel(info, x) + this._getTopOutputPixel(info, x)) / 2)) & 0xff; | ||
} | ||
@@ -327,13 +438,13 @@ }; | ||
* | ||
* @method _reversePaeth | ||
* @method _decodePaeth | ||
* @param {object} info | ||
* @private | ||
*/ | ||
Filter.prototype._reversePaeth = function (info) { | ||
Filter.prototype._decodePaeth = function (info) { | ||
for (var x = 0; x < info.scanLineLength; x++) { | ||
info.outputData[info.outputOffset + x] = | ||
this._getPixel(info, x) + this._paethPredictor( | ||
this._getLeftPixel(info, x), | ||
this._getTopPixel(info, x), | ||
this._getTopLeftPixel(info, x) | ||
this._getInputPixel(info, x) + this._paethPredictor( | ||
this._getLeftOutputPixel(info, x), | ||
this._getTopOutputPixel(info, x), | ||
this._getTopLeftOutputPixel(info, x) | ||
) & 0xff; | ||
@@ -376,3 +487,3 @@ } | ||
* | ||
* @method _getPixel | ||
* @method _getInputPixel | ||
* @param {object} info | ||
@@ -383,10 +494,11 @@ * @param {int} x X-coordinate in current scanline | ||
*/ | ||
Filter.prototype._getPixel = function (info, x) { | ||
Filter.prototype._getInputPixel = function (info, x) { | ||
return info.inputData[info.inputOffset + x]; | ||
}; | ||
/** | ||
* Gets the pixel at the left from the current pixel | ||
* Gets the pixel at the left from the current pixel from the output buffer | ||
* | ||
* @method _getLeftPixel | ||
* @method _getLeftOutputPixel | ||
* @param {object} info | ||
@@ -397,3 +509,3 @@ * @param {int} x X-coordinate in current scanline | ||
*/ | ||
Filter.prototype._getLeftPixel = function (info, x) { | ||
Filter.prototype._getLeftOutputPixel = function (info, x) { | ||
return (x < info.bytesPerPosition) ? 0 : info.outputData[info.outputOffset + x - info.bytesPerPosition]; | ||
@@ -403,5 +515,5 @@ }; | ||
/** | ||
* Gets the pixel at the top from the current pixel | ||
* Gets the pixel at the top from the current pixel from the output buffer | ||
* | ||
* @method _getTopPixel | ||
* @method _getTopOutputPixel | ||
* @param {object} info | ||
@@ -412,10 +524,10 @@ * @param {int} x X-coordinate in current scanline | ||
*/ | ||
Filter.prototype._getTopPixel = function (info, x) { | ||
return (info.previousLineOffset === null) ? 0: info.outputData[info.previousLineOffset + x]; | ||
Filter.prototype._getTopOutputPixel = function (info, x) { | ||
return (info.previousLineOffset === null) ? 0 : info.outputData[info.previousLineOffset + x]; | ||
}; | ||
/** | ||
* Gets the pixel at the top-left from the current pixel | ||
* Gets the pixel at the top-left from the current pixel from the output buffer | ||
* | ||
* @method _getTopLeftPixel | ||
* @method _getTopLeftOutputPixel | ||
* @param {object} info | ||
@@ -426,6 +538,47 @@ * @param {int} x X-coordinate in current scanline | ||
*/ | ||
Filter.prototype._getTopLeftPixel = function (info, x) { | ||
Filter.prototype._getTopLeftOutputPixel = function (info, x) { | ||
return ((info.previousLineOffset === null) || (x < info.bytesPerPosition)) ? 0 : info.outputData[info.previousLineOffset + x - info.bytesPerPosition]; | ||
}; | ||
/** | ||
* Gets the pixel at the left from the current pixel from the input buffer | ||
* | ||
* @method _getLeftInputPixel | ||
* @param {object} info | ||
* @param {int} x X-coordinate in current scanline | ||
* @return {int} | ||
* @private | ||
*/ | ||
Filter.prototype._getLeftInputPixel = function (info, x) { | ||
return (x < info.bytesPerPosition) ? 0 : info.inputData[info.inputOffset + x - info.bytesPerPosition]; | ||
}; | ||
/** | ||
* Gets the pixel at the top from the current pixel from the input buffer | ||
* | ||
* @method _getTopInputPixel | ||
* @param {object} info | ||
* @param {int} x X-coordinate in current scanline | ||
* @return {int} | ||
* @private | ||
*/ | ||
Filter.prototype._getTopInputPixel = function (info, x) { | ||
return (info.previousLineOffset === null) ? 0 : info.inputData[info.previousLineOffset + x]; | ||
}; | ||
/** | ||
* Gets the pixel at the top-left from the current pixel from the input buffer | ||
* | ||
* @method _getTopLeftInputPixel | ||
* @param {object} info | ||
* @param {int} x X-coordinate in current scanline | ||
* @return {int} | ||
* @private | ||
*/ | ||
Filter.prototype._getTopLeftInputPixel = function (info, x) { | ||
return ((info.previousLineOffset === null) || (x < info.bytesPerPosition)) ? 0 : info.inputData[info.previousLineOffset + x - info.bytesPerPosition]; | ||
}; | ||
module.exports = Filter; |
@@ -11,9 +11,21 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Chunk} headerChunk Header chunk of data stream | ||
* @param {object} [options] Options for the compressor | ||
* @constructor | ||
*/ | ||
var Interlace = function (headerChunk) { | ||
var Interlace = function (headerChunk, options) { | ||
this._headerChunk = headerChunk; | ||
this._options = options || {}; | ||
}; | ||
/** | ||
* Gets the options | ||
* | ||
* @method getOptions | ||
* @return {object} | ||
*/ | ||
Interlace.prototype.getOptions = function () { | ||
return this._options; | ||
}; | ||
/** | ||
@@ -33,16 +45,17 @@ * Gets the header chunk | ||
* | ||
* @method interlace | ||
* Note: | ||
* The input-buffer will be equal to output-buffer | ||
* when there is no selected interlace-method. | ||
* | ||
* @method encode | ||
* @param {Buffer} data Image data | ||
* @return {Buffer} Interlaces image data | ||
*/ | ||
Interlace.prototype.interlace = function (data) { | ||
Interlace.prototype.encode = function (data) { | ||
var headerChunk = this.getHeaderChunk(), | ||
output; | ||
output = data; | ||
if (headerChunk.getInterlaceMethod() === interlace.ADAM7) { | ||
output = this._adam7(data, headerChunk.getWidth(), headerChunk.getHeight(), false); | ||
} else { | ||
output = new Buffer(data.length); | ||
data.copy(output, 0, 0, output.length); | ||
} | ||
@@ -56,16 +69,17 @@ | ||
* | ||
* @method reverse | ||
* Note: | ||
* The input-buffer will be equal to output-buffer | ||
* when there is no selected interlace-method. | ||
* | ||
* @method decode | ||
* @param {Buffer} data Image data | ||
* @return {Buffer} Plain image data | ||
*/ | ||
Interlace.prototype.reverse = function (data) { | ||
Interlace.prototype.decode = function (data) { | ||
var headerChunk = this.getHeaderChunk(), | ||
output; | ||
output = data; | ||
if (headerChunk.getInterlaceMethod() === interlace.ADAM7) { | ||
output = this._adam7(data, headerChunk.getWidth(), headerChunk.getHeight(), true); | ||
} else { | ||
output = new Buffer(data.length); | ||
data.copy(output, 0, 0, output.length); | ||
} | ||
@@ -72,0 +86,0 @@ |
@@ -11,9 +11,21 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Chunk} headerChunk Header chunk of data stream | ||
* @param {object} [options] Options for the compressor | ||
* @constructor | ||
*/ | ||
var Normalizer = function (headerChunk) { | ||
var Normalizer = function (headerChunk, options) { | ||
this._headerChunk = headerChunk; | ||
this._options = options || {}; | ||
}; | ||
/** | ||
* Gets the options | ||
* | ||
* @method getOptions | ||
* @return {object} | ||
*/ | ||
Normalizer.prototype.getOptions = function () { | ||
return this._options; | ||
}; | ||
/** | ||
@@ -20,0 +32,0 @@ * Gets the header chunk |
@@ -12,9 +12,22 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Chunk} headerChunk Header chunk of data stream | ||
* @param {object} [options] Options for the compressor | ||
* @constructor | ||
*/ | ||
var Parser = function (headerChunk) { | ||
var Parser = function (headerChunk, options) { | ||
this._headerChunk = headerChunk; | ||
this._options = options || {}; | ||
}; | ||
/** | ||
* Gets the options | ||
* | ||
* @method getOptions | ||
* @return {object} | ||
*/ | ||
Parser.prototype.getOptions = function () { | ||
return this._options; | ||
}; | ||
/** | ||
* Gets the header chunk | ||
@@ -21,0 +34,0 @@ * |
@@ -11,9 +11,21 @@ // Copyright 2015 Yahoo! Inc. | ||
* @param {Chunk} headerChunk Header chunk of data stream | ||
* @param {object} [options] Options for the compressor | ||
* @constructor | ||
*/ | ||
var Scaler = function (headerChunk) { | ||
var Scaler = function (headerChunk, options) { | ||
this._headerChunk = headerChunk; | ||
this._options = options || {}; | ||
}; | ||
/** | ||
* Gets the options | ||
* | ||
* @method getOptions | ||
* @return {object} | ||
*/ | ||
Scaler.prototype.getOptions = function () { | ||
return this._options; | ||
}; | ||
/** | ||
@@ -20,0 +32,0 @@ * Scaler factor for 1-to-8-bit value conversion |
@@ -33,12 +33,23 @@ // Copyright 2015 Yahoo! Inc. | ||
/** | ||
* List of unit types | ||
* List of physical unit types | ||
* | ||
* @type {object} | ||
*/ | ||
var units = { | ||
var physicalUnits = { | ||
UNKNOWN: 0, | ||
METER: 1 | ||
METER: 1, | ||
RADIAN: 2 | ||
}; | ||
/** | ||
* List of offset unit types | ||
* | ||
* @type {object} | ||
*/ | ||
var offsetUnits = { | ||
PIXEL: 0, | ||
MICROMETER: 1 | ||
}; | ||
/** | ||
* List of rendering intents | ||
@@ -65,8 +76,20 @@ * | ||
/** | ||
* List of stereo layouts | ||
* | ||
* @type {object} | ||
*/ | ||
var stereoLayouts = { | ||
CROSS_FUSE: 0, | ||
DIVERGING_FUSE: 1 | ||
}; | ||
module.exports = { | ||
signature: signature, | ||
colorTypes: colorTypes, | ||
units: units, | ||
physicalUnits: physicalUnits, | ||
offsetUnits: offsetUnits, | ||
intents: intents, | ||
interlace: interlace | ||
interlace: interlace, | ||
stereoLayouts: stereoLayouts | ||
}; |
{ | ||
"name": "pngjs-image", | ||
"version": "0.11.6", | ||
"version": "0.11.7", | ||
"description": "JavaScript-based PNG image encoder, decoder, and manipulator", | ||
@@ -32,3 +32,3 @@ "license": "MIT", | ||
"pako": "^0.2.6", | ||
"pngjs": "0.4.0", | ||
"pngjs": "2.3.1", | ||
"request": "^2.55.0", | ||
@@ -35,0 +35,0 @@ "stream-buffers": "1.0.1", |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
235699
60
8595
1
+ Addedpngjs@2.3.1(transitive)
- Removedpngjs@0.4.0(transitive)
Updatedpngjs@2.3.1