3 var constants = require('./constants');
5 module.exports = function(dataIn, width, height, options) {
6 var outHasAlpha = [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(options.colorType) !== -1;
7 if (options.colorType === options.inputColorType) {
8 var bigEndian = (function() {
9 var buffer = new ArrayBuffer(2);
10 new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
11 // Int16Array uses the platform's endianness.
12 return new Int16Array(buffer)[0] !== 256;
14 // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
15 if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
20 // map to a UInt16 array if data is 16bit, fix endianness below
21 var data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
24 var inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
25 if (inBpp === 4 && !options.inputHasAlpha) {
28 var outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
29 if (options.bitDepth === 16) {
33 var outData = new Buffer(width * height * outBpp);
38 var bgColor = options.bgColor || {};
39 if (bgColor.red === undefined) {
40 bgColor.red = maxValue;
42 if (bgColor.green === undefined) {
43 bgColor.green = maxValue;
45 if (bgColor.blue === undefined) {
46 bgColor.blue = maxValue;
54 switch (options.inputColorType) {
55 case constants.COLORTYPE_COLOR_ALPHA:
56 alpha = data[inIndex + 3];
58 green = data[inIndex + 1];
59 blue = data[inIndex + 2];
61 case constants.COLORTYPE_COLOR:
63 green = data[inIndex + 1];
64 blue = data[inIndex + 2];
66 case constants.COLORTYPE_ALPHA:
67 alpha = data[inIndex + 1];
72 case constants.COLORTYPE_GRAYSCALE:
78 throw new Error('input color type:' + options.inputColorType + ' is not supported at present');
81 if (options.inputHasAlpha) {
84 red = Math.min(Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0), maxValue);
85 green = Math.min(Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0), maxValue);
86 blue = Math.min(Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0), maxValue);
89 return { red: red, green: green, blue: blue, alpha: alpha };
92 for (var y = 0; y < height; y++) {
93 for (var x = 0; x < width; x++) {
94 var rgba = getRGBA(data, inIndex);
96 switch (options.colorType) {
97 case constants.COLORTYPE_COLOR_ALPHA:
98 case constants.COLORTYPE_COLOR:
99 if (options.bitDepth === 8) {
100 outData[outIndex] = rgba.red;
101 outData[outIndex + 1] = rgba.green;
102 outData[outIndex + 2] = rgba.blue;
104 outData[outIndex + 3] = rgba.alpha;
108 outData.writeUInt16BE(rgba.red, outIndex);
109 outData.writeUInt16BE(rgba.green, outIndex + 2);
110 outData.writeUInt16BE(rgba.blue, outIndex + 4);
112 outData.writeUInt16BE(rgba.alpha, outIndex + 6);
116 case constants.COLORTYPE_ALPHA:
117 case constants.COLORTYPE_GRAYSCALE:
118 // Convert to grayscale and alpha
119 var grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
120 if (options.bitDepth === 8) {
121 outData[outIndex] = grayscale;
123 outData[outIndex + 1] = rgba.alpha;
127 outData.writeUInt16BE(grayscale, outIndex);
129 outData.writeUInt16BE(rgba.alpha, outIndex + 2);
134 throw new Error('unrecognised color Type ' + options.colorType);