UNPKG

4.67 kBJavaScriptView Raw
1"use strict";
2
3let constants = require("./constants");
4
5module.exports = function (dataIn, width, height, options) {
6 let outHasAlpha =
7 [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(
8 options.colorType
9 ) !== -1;
10 if (options.colorType === options.inputColorType) {
11 let bigEndian = (function () {
12 let buffer = new ArrayBuffer(2);
13 new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
14 // Int16Array uses the platform's endianness.
15 return new Int16Array(buffer)[0] !== 256;
16 })();
17 // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
18 if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
19 return dataIn;
20 }
21 }
22
23 // map to a UInt16 array if data is 16bit, fix endianness below
24 let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
25
26 let maxValue = 255;
27 let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
28 if (inBpp === 4 && !options.inputHasAlpha) {
29 inBpp = 3;
30 }
31 let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
32 if (options.bitDepth === 16) {
33 maxValue = 65535;
34 outBpp *= 2;
35 }
36 let outData = Buffer.alloc(width * height * outBpp);
37
38 let inIndex = 0;
39 let outIndex = 0;
40
41 let bgColor = options.bgColor || {};
42 if (bgColor.red === undefined) {
43 bgColor.red = maxValue;
44 }
45 if (bgColor.green === undefined) {
46 bgColor.green = maxValue;
47 }
48 if (bgColor.blue === undefined) {
49 bgColor.blue = maxValue;
50 }
51
52 function getRGBA() {
53 let red;
54 let green;
55 let blue;
56 let alpha = maxValue;
57 switch (options.inputColorType) {
58 case constants.COLORTYPE_COLOR_ALPHA:
59 alpha = data[inIndex + 3];
60 red = data[inIndex];
61 green = data[inIndex + 1];
62 blue = data[inIndex + 2];
63 break;
64 case constants.COLORTYPE_COLOR:
65 red = data[inIndex];
66 green = data[inIndex + 1];
67 blue = data[inIndex + 2];
68 break;
69 case constants.COLORTYPE_ALPHA:
70 alpha = data[inIndex + 1];
71 red = data[inIndex];
72 green = red;
73 blue = red;
74 break;
75 case constants.COLORTYPE_GRAYSCALE:
76 red = data[inIndex];
77 green = red;
78 blue = red;
79 break;
80 default:
81 throw new Error(
82 "input color type:" +
83 options.inputColorType +
84 " is not supported at present"
85 );
86 }
87
88 if (options.inputHasAlpha) {
89 if (!outHasAlpha) {
90 alpha /= maxValue;
91 red = Math.min(
92 Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0),
93 maxValue
94 );
95 green = Math.min(
96 Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0),
97 maxValue
98 );
99 blue = Math.min(
100 Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0),
101 maxValue
102 );
103 }
104 }
105 return { red: red, green: green, blue: blue, alpha: alpha };
106 }
107
108 for (let y = 0; y < height; y++) {
109 for (let x = 0; x < width; x++) {
110 let rgba = getRGBA(data, inIndex);
111
112 switch (options.colorType) {
113 case constants.COLORTYPE_COLOR_ALPHA:
114 case constants.COLORTYPE_COLOR:
115 if (options.bitDepth === 8) {
116 outData[outIndex] = rgba.red;
117 outData[outIndex + 1] = rgba.green;
118 outData[outIndex + 2] = rgba.blue;
119 if (outHasAlpha) {
120 outData[outIndex + 3] = rgba.alpha;
121 }
122 } else {
123 outData.writeUInt16BE(rgba.red, outIndex);
124 outData.writeUInt16BE(rgba.green, outIndex + 2);
125 outData.writeUInt16BE(rgba.blue, outIndex + 4);
126 if (outHasAlpha) {
127 outData.writeUInt16BE(rgba.alpha, outIndex + 6);
128 }
129 }
130 break;
131 case constants.COLORTYPE_ALPHA:
132 case constants.COLORTYPE_GRAYSCALE: {
133 // Convert to grayscale and alpha
134 let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
135 if (options.bitDepth === 8) {
136 outData[outIndex] = grayscale;
137 if (outHasAlpha) {
138 outData[outIndex + 1] = rgba.alpha;
139 }
140 } else {
141 outData.writeUInt16BE(grayscale, outIndex);
142 if (outHasAlpha) {
143 outData.writeUInt16BE(rgba.alpha, outIndex + 2);
144 }
145 }
146 break;
147 }
148 default:
149 throw new Error("unrecognised color Type " + options.colorType);
150 }
151
152 inIndex += inBpp;
153 outIndex += outBpp;
154 }
155 }
156
157 return outData;
158};