[Service] Integrate DeviceHome and SignalingServer
[platform/framework/web/wrtjs.git] / device_home / node_modules / pngjs / lib / bitmapper.js
1 'use strict';
2
3 var interlaceUtils = require('./interlace');
4
5 var pixelBppMapper = [
6   // 0 - dummy entry
7   function() {},
8
9   // 1 - L
10   // 0: 0, 1: 0, 2: 0, 3: 0xff
11   function(pxData, data, pxPos, rawPos) {
12     if (rawPos === data.length) {
13       throw new Error('Ran out of data');
14     }
15
16     var pixel = data[rawPos];
17     pxData[pxPos] = pixel;
18     pxData[pxPos + 1] = pixel;
19     pxData[pxPos + 2] = pixel;
20     pxData[pxPos + 3] = 0xff;
21   },
22
23   // 2 - LA
24   // 0: 0, 1: 0, 2: 0, 3: 1
25   function(pxData, data, pxPos, rawPos) {
26     if (rawPos + 1 >= data.length) {
27       throw new Error('Ran out of data');
28     }
29
30     var pixel = data[rawPos];
31     pxData[pxPos] = pixel;
32     pxData[pxPos + 1] = pixel;
33     pxData[pxPos + 2] = pixel;
34     pxData[pxPos + 3] = data[rawPos + 1];
35   },
36
37   // 3 - RGB
38   // 0: 0, 1: 1, 2: 2, 3: 0xff
39   function(pxData, data, pxPos, rawPos) {
40     if (rawPos + 2 >= data.length) {
41       throw new Error('Ran out of data');
42     }
43
44     pxData[pxPos] = data[rawPos];
45     pxData[pxPos + 1] = data[rawPos + 1];
46     pxData[pxPos + 2] = data[rawPos + 2];
47     pxData[pxPos + 3] = 0xff;
48   },
49
50   // 4 - RGBA
51   // 0: 0, 1: 1, 2: 2, 3: 3
52   function(pxData, data, pxPos, rawPos) {
53     if (rawPos + 3 >= data.length) {
54       throw new Error('Ran out of data');
55     }
56
57     pxData[pxPos] = data[rawPos];
58     pxData[pxPos + 1] = data[rawPos + 1];
59     pxData[pxPos + 2] = data[rawPos + 2];
60     pxData[pxPos + 3] = data[rawPos + 3];
61   }
62 ];
63
64 var pixelBppCustomMapper = [
65   // 0 - dummy entry
66   function() {},
67
68   // 1 - L
69   // 0: 0, 1: 0, 2: 0, 3: 0xff
70   function(pxData, pixelData, pxPos, maxBit) {
71     var pixel = pixelData[0];
72     pxData[pxPos] = pixel;
73     pxData[pxPos + 1] = pixel;
74     pxData[pxPos + 2] = pixel;
75     pxData[pxPos + 3] = maxBit;
76   },
77
78   // 2 - LA
79   // 0: 0, 1: 0, 2: 0, 3: 1
80   function(pxData, pixelData, pxPos) {
81     var pixel = pixelData[0];
82     pxData[pxPos] = pixel;
83     pxData[pxPos + 1] = pixel;
84     pxData[pxPos + 2] = pixel;
85     pxData[pxPos + 3] = pixelData[1];
86   },
87
88   // 3 - RGB
89   // 0: 0, 1: 1, 2: 2, 3: 0xff
90   function(pxData, pixelData, pxPos, maxBit) {
91     pxData[pxPos] = pixelData[0];
92     pxData[pxPos + 1] = pixelData[1];
93     pxData[pxPos + 2] = pixelData[2];
94     pxData[pxPos + 3] = maxBit;
95   },
96
97   // 4 - RGBA
98   // 0: 0, 1: 1, 2: 2, 3: 3
99   function(pxData, pixelData, pxPos) {
100     pxData[pxPos] = pixelData[0];
101     pxData[pxPos + 1] = pixelData[1];
102     pxData[pxPos + 2] = pixelData[2];
103     pxData[pxPos + 3] = pixelData[3];
104   }
105 ];
106
107 function bitRetriever(data, depth) {
108
109   var leftOver = [];
110   var i = 0;
111
112   function split() {
113     if (i === data.length) {
114       throw new Error('Ran out of data');
115     }
116     var byte = data[i];
117     i++;
118     var byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
119     switch (depth) {
120       default:
121         throw new Error('unrecognised depth');
122       case 16:
123         byte2 = data[i];
124         i++;
125         leftOver.push(((byte << 8) + byte2));
126         break;
127       case 4:
128         byte2 = byte & 0x0f;
129         byte1 = byte >> 4;
130         leftOver.push(byte1, byte2);
131         break;
132       case 2:
133         byte4 = byte & 3;
134         byte3 = byte >> 2 & 3;
135         byte2 = byte >> 4 & 3;
136         byte1 = byte >> 6 & 3;
137         leftOver.push(byte1, byte2, byte3, byte4);
138         break;
139       case 1:
140         byte8 = byte & 1;
141         byte7 = byte >> 1 & 1;
142         byte6 = byte >> 2 & 1;
143         byte5 = byte >> 3 & 1;
144         byte4 = byte >> 4 & 1;
145         byte3 = byte >> 5 & 1;
146         byte2 = byte >> 6 & 1;
147         byte1 = byte >> 7 & 1;
148         leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
149         break;
150     }
151   }
152
153   return {
154     get: function(count) {
155       while (leftOver.length < count) {
156         split();
157       }
158       var returner = leftOver.slice(0, count);
159       leftOver = leftOver.slice(count);
160       return returner;
161     },
162     resetAfterLine: function() {
163       leftOver.length = 0;
164     },
165     end: function() {
166       if (i !== data.length) {
167         throw new Error('extra data found');
168       }
169     }
170   };
171 }
172
173 function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { // eslint-disable-line max-params
174   var imageWidth = image.width;
175   var imageHeight = image.height;
176   var imagePass = image.index;
177   for (var y = 0; y < imageHeight; y++) {
178     for (var x = 0; x < imageWidth; x++) {
179       var pxPos = getPxPos(x, y, imagePass);
180       pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
181       rawPos += bpp; //eslint-disable-line no-param-reassign
182     }
183   }
184   return rawPos;
185 }
186
187 function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) { // eslint-disable-line max-params
188   var imageWidth = image.width;
189   var imageHeight = image.height;
190   var imagePass = image.index;
191   for (var y = 0; y < imageHeight; y++) {
192     for (var x = 0; x < imageWidth; x++) {
193       var pixelData = bits.get(bpp);
194       var pxPos = getPxPos(x, y, imagePass);
195       pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
196     }
197     bits.resetAfterLine();
198   }
199 }
200
201 exports.dataToBitMap = function(data, bitmapInfo) {
202
203   var width = bitmapInfo.width;
204   var height = bitmapInfo.height;
205   var depth = bitmapInfo.depth;
206   var bpp = bitmapInfo.bpp;
207   var interlace = bitmapInfo.interlace;
208
209   if (depth !== 8) {
210     var bits = bitRetriever(data, depth);
211   }
212   var pxData;
213   if (depth <= 8) {
214     pxData = new Buffer(width * height * 4);
215   }
216   else {
217     pxData = new Uint16Array(width * height * 4);
218   }
219   var maxBit = Math.pow(2, depth) - 1;
220   var rawPos = 0;
221   var images;
222   var getPxPos;
223
224   if (interlace) {
225     images = interlaceUtils.getImagePasses(width, height);
226     getPxPos = interlaceUtils.getInterlaceIterator(width, height);
227   }
228   else {
229     var nonInterlacedPxPos = 0;
230     getPxPos = function() {
231       var returner = nonInterlacedPxPos;
232       nonInterlacedPxPos += 4;
233       return returner;
234     };
235     images = [{ width: width, height: height }];
236   }
237
238   for (var imageIndex = 0; imageIndex < images.length; imageIndex++) {
239     if (depth === 8) {
240       rawPos = mapImage8Bit(images[imageIndex], pxData, getPxPos, bpp, data, rawPos);
241     }
242     else {
243       mapImageCustomBit(images[imageIndex], pxData, getPxPos, bpp, bits, maxBit);
244     }
245   }
246   if (depth === 8) {
247     if (rawPos !== data.length) {
248       throw new Error('extra data found');
249     }
250   }
251   else {
252     bits.end();
253   }
254
255   return pxData;
256 };