You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
5.7 KiB
271 lines
5.7 KiB
// Copyright 2015 Yahoo! Inc.
|
|
// Copyrights licensed under the Mit License. See the accompanying LICENSE file for terms.
|
|
|
|
var BufferedStream = require('../utils/bufferedStream');
|
|
|
|
/**
|
|
* @class Normalizer
|
|
* @module PNG
|
|
* @submodule PNGCore
|
|
* @param {Chunk} headerChunk Header chunk of data stream
|
|
* @param {object} [options] Options for the compressor
|
|
* @constructor
|
|
*/
|
|
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;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the header chunk
|
|
*
|
|
* @method getHeaderChunk
|
|
* @return {Chunk}
|
|
*/
|
|
Normalizer.prototype.getHeaderChunk = function () {
|
|
return this._headerChunk;
|
|
};
|
|
|
|
|
|
/**
|
|
* Encodes color values of an image
|
|
*
|
|
* @method encode
|
|
* @param {Buffer} image
|
|
*/
|
|
Normalizer.prototype.encode = function (image) {
|
|
return image;
|
|
//TODO: Writing is currently only 8-bit
|
|
};
|
|
|
|
|
|
/**
|
|
* Determines the max number for a bit-depth
|
|
*
|
|
* @method _determineMaxValue
|
|
* @return {int}
|
|
* @private
|
|
*/
|
|
Normalizer.prototype._determineMaxValue = function () {
|
|
|
|
var headerChunk = this.getHeaderChunk(),
|
|
result;
|
|
|
|
if (headerChunk.isColorTypeIndexedColor()) {
|
|
result = 255;
|
|
|
|
} else {
|
|
switch (headerChunk.getBitDepth()) {
|
|
|
|
case 1:
|
|
result = 1;
|
|
break;
|
|
|
|
case 2:
|
|
result = 3;
|
|
break;
|
|
|
|
case 4:
|
|
result = 15;
|
|
break;
|
|
|
|
case 8:
|
|
result = 255;
|
|
break;
|
|
|
|
case 16:
|
|
result = 65535;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Determines the writer according to header data
|
|
*
|
|
* @method _determineWriter
|
|
* @return {object}
|
|
* @private
|
|
*/
|
|
Normalizer.prototype._determineWriter = function () {
|
|
|
|
var headerChunk = this.getHeaderChunk(),
|
|
isColor, hasAlpha, isIndexed,
|
|
result = null;
|
|
|
|
isColor = headerChunk.isColor();
|
|
hasAlpha = headerChunk.hasAlphaChannel();
|
|
isIndexed = headerChunk.isColorTypeIndexedColor();
|
|
|
|
if (isIndexed) {
|
|
result = {
|
|
valuesNeeded: 1,
|
|
writer: '_writeInIndexedBytes'
|
|
};
|
|
|
|
} else {
|
|
|
|
if (isColor) {
|
|
if (hasAlpha) {
|
|
result = {
|
|
valuesNeeded: 4,
|
|
writer: '_writeInColorAlphaBytes'
|
|
};
|
|
} else {
|
|
result = {
|
|
valuesNeeded: 3,
|
|
writer: '_writeInColorNoAlphaBytes'
|
|
};
|
|
}
|
|
} else {
|
|
if (hasAlpha) {
|
|
result = {
|
|
valuesNeeded: 2,
|
|
writer: '_writeInNoColorAlphaBytes'
|
|
};
|
|
} else {
|
|
result = {
|
|
valuesNeeded: 1,
|
|
writer: '_writeInNoColorNoAlphaBytes'
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Decodes color values
|
|
*
|
|
* @method decode
|
|
* @param {Buffer} image
|
|
* @return {Buffer}
|
|
*/
|
|
Normalizer.prototype.decode = function (image) {
|
|
|
|
var writerInfo,
|
|
maxValue,
|
|
offset = 0,
|
|
len = image.length,
|
|
internalImageSize = this.getHeaderChunk().getImageSizeInBytes() * 2, // 16-bit
|
|
|
|
imageStream, outputStream;
|
|
|
|
writerInfo = this._determineWriter();
|
|
|
|
// Skip normalization since nothing needs to be done here.
|
|
if (writerInfo.valuesNeeded === 4) {
|
|
return image;
|
|
}
|
|
|
|
maxValue = this._determineMaxValue();
|
|
|
|
imageStream = new BufferedStream(image, false);
|
|
outputStream = new BufferedStream(null, null, internalImageSize);
|
|
|
|
while (len > offset) {
|
|
this[writerInfo.writer](imageStream, outputStream, maxValue);
|
|
offset += writerInfo.valuesNeeded * 2;
|
|
}
|
|
|
|
return outputStream.toBuffer();
|
|
};
|
|
|
|
|
|
/**
|
|
* Write bytes when image is color and has already an alpha-channel
|
|
*
|
|
* @method _writeInColorAlphaBytes
|
|
* @param {BufferedStream} input Input stream
|
|
* @param {BufferedStream} output Output stream
|
|
* @private
|
|
*/
|
|
Normalizer.prototype._writeInColorAlphaBytes = function (input, output) {
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
};
|
|
|
|
/**
|
|
* Write bytes when image is color and has no alpha-channel
|
|
*
|
|
* @method _writeInColorNoAlphaBytes
|
|
* @param {BufferedStream} input Input stream
|
|
* @param {BufferedStream} output Output stream
|
|
* @param {int} maxValue Max value for bit-depth
|
|
* @private
|
|
*/
|
|
Normalizer.prototype._writeInColorNoAlphaBytes = function (input, output, maxValue) {
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
output.writeUInt16BE(maxValue);
|
|
};
|
|
|
|
/**
|
|
* Write bytes when image is grayNormalizer and has already an alpha-channel
|
|
*
|
|
* @method _writeInNoColorAlphaBytes
|
|
* @param {BufferedStream} input Input stream
|
|
* @param {BufferedStream} output Output stream
|
|
* @private
|
|
*/
|
|
Normalizer.prototype._writeInNoColorAlphaBytes = function (input, output) {
|
|
var value = input.readUInt16BE();
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(input.readUInt16BE());
|
|
};
|
|
|
|
/**
|
|
* Write bytes when image is grayNormalizer and has no alpha-channel
|
|
*
|
|
* @method _writeInNoColorNoAlphaBytes
|
|
* @param {BufferedStream} input Input stream
|
|
* @param {BufferedStream} output Output stream
|
|
* @param {int} maxValue Max value for bit-depth
|
|
* @private
|
|
*/
|
|
Normalizer.prototype._writeInNoColorNoAlphaBytes = function (input, output, maxValue) {
|
|
var value = input.readUInt16BE();
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(maxValue);
|
|
};
|
|
|
|
/**
|
|
* Write bytes when image is indexed on a palette
|
|
*
|
|
* @method _writeInIndexedBytes
|
|
* @param {BufferedStream} input Input stream
|
|
* @param {BufferedStream} output Output stream
|
|
* @param {int} maxValue Max value for bit-depth
|
|
* @private
|
|
*/
|
|
Normalizer.prototype._writeInIndexedBytes = function (input, output, maxValue) {
|
|
var value = input.readUInt16BE();
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(value);
|
|
output.writeUInt16BE(maxValue);
|
|
};
|
|
|
|
module.exports = Normalizer;
|