123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- 'use strict';
- var constants = require('./constants');
- module.exports = function(dataIn, width, height, options) {
- var outHasAlpha = [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(options.colorType) !== -1;
- if (options.colorType === options.inputColorType) {
- var bigEndian = (function() {
- var buffer = new ArrayBuffer(2);
- new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
- // Int16Array uses the platform's endianness.
- return new Int16Array(buffer)[0] !== 256;
- })();
- // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
- if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
- return dataIn;
- }
- }
- // map to a UInt16 array if data is 16bit, fix endianness below
- var data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
- var maxValue = 255;
- var inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
- if (inBpp === 4 && !options.inputHasAlpha) {
- inBpp = 3;
- }
- var outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
- if (options.bitDepth === 16) {
- maxValue = 65535;
- outBpp *= 2;
- }
- var outData = new Buffer(width * height * outBpp);
- var inIndex = 0;
- var outIndex = 0;
- var bgColor = options.bgColor || {};
- if (bgColor.red === undefined) {
- bgColor.red = maxValue;
- }
- if (bgColor.green === undefined) {
- bgColor.green = maxValue;
- }
- if (bgColor.blue === undefined) {
- bgColor.blue = maxValue;
- }
- function getRGBA() {
- var red;
- var green;
- var blue;
- var alpha = maxValue;
- switch (options.inputColorType) {
- case constants.COLORTYPE_COLOR_ALPHA:
- alpha = data[inIndex + 3];
- red = data[inIndex];
- green = data[inIndex + 1];
- blue = data[inIndex + 2];
- break;
- case constants.COLORTYPE_COLOR:
- red = data[inIndex];
- green = data[inIndex + 1];
- blue = data[inIndex + 2];
- break;
- case constants.COLORTYPE_ALPHA:
- alpha = data[inIndex + 1];
- red = data[inIndex];
- green = red;
- blue = red;
- break;
- case constants.COLORTYPE_GRAYSCALE:
- red = data[inIndex];
- green = red;
- blue = red;
- break;
- default:
- throw new Error('input color type:' + options.inputColorType + ' is not supported at present');
- }
- if (options.inputHasAlpha) {
- if (!outHasAlpha) {
- alpha /= maxValue;
- red = Math.min(Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0), maxValue);
- green = Math.min(Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0), maxValue);
- blue = Math.min(Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0), maxValue);
- }
- }
- return { red: red, green: green, blue: blue, alpha: alpha };
- }
- for (var y = 0; y < height; y++) {
- for (var x = 0; x < width; x++) {
- var rgba = getRGBA(data, inIndex);
- switch (options.colorType) {
- case constants.COLORTYPE_COLOR_ALPHA:
- case constants.COLORTYPE_COLOR:
- if (options.bitDepth === 8) {
- outData[outIndex] = rgba.red;
- outData[outIndex + 1] = rgba.green;
- outData[outIndex + 2] = rgba.blue;
- if (outHasAlpha) {
- outData[outIndex + 3] = rgba.alpha;
- }
- }
- else {
- outData.writeUInt16BE(rgba.red, outIndex);
- outData.writeUInt16BE(rgba.green, outIndex + 2);
- outData.writeUInt16BE(rgba.blue, outIndex + 4);
- if (outHasAlpha) {
- outData.writeUInt16BE(rgba.alpha, outIndex + 6);
- }
- }
- break;
- case constants.COLORTYPE_ALPHA:
- case constants.COLORTYPE_GRAYSCALE:
- // Convert to grayscale and alpha
- var grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
- if (options.bitDepth === 8) {
- outData[outIndex] = grayscale;
- if (outHasAlpha) {
- outData[outIndex + 1] = rgba.alpha;
- }
- }
- else {
- outData.writeUInt16BE(grayscale, outIndex);
- if (outHasAlpha) {
- outData.writeUInt16BE(rgba.alpha, outIndex + 2);
- }
- }
- break;
- default:
- throw new Error('unrecognised color Type ' + options.colorType);
- }
- inIndex += inBpp;
- outIndex += outBpp;
- }
- }
- return outData;
- };
|