1 | "use strict";
|
2 |
|
3 | let constants = require("./constants");
|
4 |
|
5 | module.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 );
|
14 |
|
15 | return new Int16Array(buffer)[0] !== 256;
|
16 | })();
|
17 |
|
18 | if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
|
19 | return dataIn;
|
20 | }
|
21 | }
|
22 |
|
23 |
|
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 |
|
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 | };
|