| 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;};
 |