1 /*
2 * colorspace conversion functions
3 * -- translate RGB using lookup tables
4 *
5 * (c) 1998-2001 Gerd Knorr <kraxel@bytesex.org>
6 *
7 */
8
9 #define NG_PRIVATE
10 #include "config.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <pthread.h>
16 #include <inttypes.h>
17 #include <sys/time.h>
18 #include <sys/types.h>
19
20 #include "grab-ng.h"
21 #include "byteswap.h"
22
23 unsigned long ng_lut_red[256];
24 unsigned long ng_lut_green[256];
25 unsigned long ng_lut_blue[256];
26
27 /* ------------------------------------------------------------------- */
28
29 void
ng_rgb24_to_lut2(unsigned char * restrict dest,unsigned char * restrict src,int p)30 ng_rgb24_to_lut2(unsigned char* restrict dest, unsigned char* restrict src,
31 int p)
32 {
33 uint16_t* restrict d = (uint16_t*)dest;
34
35 while (p-- > 0) {
36 *(d++) = ng_lut_red[src[0]] | ng_lut_green[src[1]] |
37 ng_lut_blue[src[2]];
38 src += 3;
39 }
40 }
41
42 static void
bgr24_to_lut2(unsigned char * restrict dest,unsigned char * restrict src,int p)43 bgr24_to_lut2(unsigned char* restrict dest, unsigned char* restrict src,
44 int p)
45 {
46 uint16_t* restrict d = (uint16_t*)dest;
47
48 while (p-- > 0) {
49 *(d++) = ng_lut_red[src[2]] | ng_lut_green[src[1]] |
50 ng_lut_blue[src[0]];
51 src += 3;
52 }
53 }
54
55 static void
rgb32_to_lut2(unsigned char * restrict dest,unsigned char * restrict src,int p)56 rgb32_to_lut2(unsigned char* restrict dest, unsigned char* restrict src,
57 int p)
58 {
59 uint16_t* restrict d = (uint16_t*)dest;
60
61 while (p-- > 0) {
62 *(d++) = ng_lut_red[src[1]] | ng_lut_green[src[2]] |
63 ng_lut_blue[src[3]];
64 src += 4;
65 }
66 }
67
68 static void
bgr32_to_lut2(unsigned char * restrict dest,unsigned char * restrict src,int p)69 bgr32_to_lut2(unsigned char* restrict dest, unsigned char* restrict src,
70 int p)
71 {
72 uint16_t* restrict d = (uint16_t*)dest;
73
74 while (p-- > 0) {
75 *(d++) = ng_lut_red[src[2]] | ng_lut_green[src[1]] |
76 ng_lut_blue[src[0]];
77 src += 4;
78 }
79 }
80
81 static void
gray_to_lut2(unsigned char * restrict dest,unsigned char * restrict src,int p)82 gray_to_lut2(unsigned char* restrict dest, unsigned char* restrict src,
83 int p)
84 {
85 uint16_t* restrict d = (uint16_t*)dest;
86
87 while (p-- > 0) {
88 *(d++) = ng_lut_red[*src] | ng_lut_green[*src] | ng_lut_blue[*src];
89 src++;
90 }
91 }
92
93 /* ------------------------------------------------------------------- */
94
95 void
ng_rgb24_to_lut4(unsigned char * restrict dest,unsigned char * restrict src,int p)96 ng_rgb24_to_lut4(unsigned char* restrict dest, unsigned char* restrict src,
97 int p)
98 {
99 unsigned int* restrict d = (unsigned int*)dest;
100
101 while (p-- > 0) {
102 *(d++) = ng_lut_red[src[0]] | ng_lut_green[src[1]] |
103 ng_lut_blue[src[2]];
104 src += 3;
105 }
106 }
107
108 static void
bgr24_to_lut4(unsigned char * restrict dest,unsigned char * restrict src,int p)109 bgr24_to_lut4(unsigned char* restrict dest, unsigned char* restrict src,
110 int p)
111 {
112 unsigned int* restrict d = (unsigned int*)dest;
113
114 while (p-- > 0) {
115 *(d++) = ng_lut_red[src[2]] | ng_lut_green[src[1]] |
116 ng_lut_blue[src[0]];
117 src += 3;
118 }
119 }
120
121 static void
rgb32_to_lut4(unsigned char * restrict dest,unsigned char * restrict src,int p)122 rgb32_to_lut4(unsigned char* restrict dest, unsigned char* restrict src,
123 int p)
124 {
125 unsigned int* restrict d = (unsigned int*)dest;
126
127 while (p-- > 0) {
128 *(d++) = ng_lut_red[src[1]] | ng_lut_green[src[2]] |
129 ng_lut_blue[src[3]];
130 src += 4;
131 }
132 }
133
134 static void
bgr32_to_lut4(unsigned char * restrict dest,unsigned char * restrict src,int p)135 bgr32_to_lut4(unsigned char* restrict dest, unsigned char* restrict src,
136 int p)
137 {
138 unsigned int* restrict d = (unsigned int*)dest;
139
140 while (p-- > 0) {
141 *(d++) = ng_lut_red[src[2]] | ng_lut_green[src[1]] |
142 ng_lut_blue[src[0]];
143 src += 4;
144 }
145 }
146
147 static void
gray_to_lut4(unsigned char * restrict dest,unsigned char * restrict src,int p)148 gray_to_lut4(unsigned char* restrict dest, unsigned char* restrict src,
149 int p)
150 {
151 unsigned int* restrict d = (unsigned int*)dest;
152
153 while (p-- > 0) {
154 *(d++) = ng_lut_red[*src] | ng_lut_green[*src] | ng_lut_blue[*src];
155 src++;
156 }
157 }
158
159 /* ------------------------------------------------------------------- */
160
161 static struct ng_video_conv lut2_list[] = {
162 {
163 NG_GENERIC_PACKED,
164 .fmtid_in = VIDEO_RGB24,
165 .priv = ng_rgb24_to_lut2,
166 }, {
167 NG_GENERIC_PACKED,
168 .fmtid_in = VIDEO_BGR24,
169 .priv = bgr24_to_lut2,
170 }, {
171 NG_GENERIC_PACKED,
172 .fmtid_in = VIDEO_RGB32,
173 .priv = rgb32_to_lut2,
174 }, {
175 NG_GENERIC_PACKED,
176 .fmtid_in = VIDEO_BGR32,
177 .priv = bgr32_to_lut2,
178 }, {
179 NG_GENERIC_PACKED,
180 .fmtid_in = VIDEO_GRAY,
181 .priv = gray_to_lut2,
182 }, {
183 NG_GENERIC_PACKED,
184 .fmtid_in = VIDEO_YUYV,
185 .priv = ng_yuv422_to_lut2,
186 },{
187 .init = ng_conv_nop_init,
188 .fini = ng_conv_nop_fini,
189 .frame = ng_yuv422p_to_lut2,
190 .fmtid_in = VIDEO_YUV422P,
191 },{
192 .init = ng_conv_nop_init,
193 .fini = ng_conv_nop_fini,
194 .frame = ng_yuv420p_to_lut2,
195 .fmtid_in = VIDEO_YUV420P,
196 }
197 };
198
199 static struct ng_video_conv lut4_list[] = {
200 {
201 NG_GENERIC_PACKED,
202 .fmtid_in = VIDEO_RGB24,
203 .priv = ng_rgb24_to_lut4,
204 }, {
205 NG_GENERIC_PACKED,
206 .fmtid_in = VIDEO_BGR24,
207 .priv = bgr24_to_lut4,
208 }, {
209 NG_GENERIC_PACKED,
210 .fmtid_in = VIDEO_RGB32,
211 .priv = rgb32_to_lut4,
212 }, {
213 NG_GENERIC_PACKED,
214 .fmtid_in = VIDEO_BGR32,
215 .priv = bgr32_to_lut4,
216 }, {
217 NG_GENERIC_PACKED,
218 .fmtid_in = VIDEO_GRAY,
219 .priv = gray_to_lut4,
220 }, {
221 NG_GENERIC_PACKED,
222 .fmtid_in = VIDEO_YUYV,
223 .priv = ng_yuv422_to_lut4,
224 },{
225 .init = ng_conv_nop_init,
226 .fini = ng_conv_nop_fini,
227 .frame = ng_yuv422p_to_lut4,
228 .fmtid_in = VIDEO_YUV422P,
229 },{
230 .init = ng_conv_nop_init,
231 .fini = ng_conv_nop_fini,
232 .frame = ng_yuv420p_to_lut4,
233 .fmtid_in = VIDEO_YUV420P,
234 }
235 };
236
237 static const unsigned int nconv2 = sizeof(lut2_list)/sizeof(lut2_list[0]);
238 static const unsigned int nconv4 = sizeof(lut4_list)/sizeof(lut4_list[0]);
239
240 void
ng_lut_init(unsigned long red_mask,unsigned long green_mask,unsigned long blue_mask,unsigned int fmtid,int swap)241 ng_lut_init(unsigned long red_mask, unsigned long green_mask,
242 unsigned long blue_mask, unsigned int fmtid, int swap)
243 {
244 static int once=0;
245 int rgb_red_bits = 0;
246 int rgb_red_shift = 0;
247 int rgb_green_bits = 0;
248 int rgb_green_shift = 0;
249 int rgb_blue_bits = 0;
250 int rgb_blue_shift = 0;
251 unsigned int i;
252 unsigned int mask;
253
254 if (once++) {
255 fprintf(stderr,"panic: ng_lut_init called twice\n");
256 exit(1);
257 }
258
259 for (i = 0; i < 32; i++) {
260 mask = (1 << i);
261 if (red_mask & mask)
262 rgb_red_bits++;
263 else if (!rgb_red_bits)
264 rgb_red_shift++;
265 if (green_mask & mask)
266 rgb_green_bits++;
267 else if (!rgb_green_bits)
268 rgb_green_shift++;
269 if (blue_mask & mask)
270 rgb_blue_bits++;
271 else if (!rgb_blue_bits)
272 rgb_blue_shift++;
273 }
274 #if 0
275 printf("color: bits shift\n");
276 printf("red : %04i %05i\n", rgb_red_bits, rgb_red_shift);
277 printf("green: %04i %05i\n", rgb_green_bits, rgb_green_shift);
278 printf("blue : %04i %05i\n", rgb_blue_bits, rgb_blue_shift);
279 #endif
280
281 if (rgb_red_bits > 8)
282 for (i = 0; i < 256; i++)
283 ng_lut_red[i] = (i << (rgb_red_bits + rgb_red_shift - 8));
284 else
285 for (i = 0; i < 256; i++)
286 ng_lut_red[i] = (i >> (8 - rgb_red_bits)) << rgb_red_shift;
287
288 if (rgb_green_bits > 8)
289 for (i = 0; i < 256; i++)
290 ng_lut_green[i] = (i << (rgb_green_bits + rgb_green_shift - 8));
291 else
292 for (i = 0; i < 256; i++)
293 ng_lut_green[i] = (i >> (8 - rgb_green_bits)) << rgb_green_shift;
294
295 if (rgb_blue_bits > 8)
296 for (i = 0; i < 256; i++)
297 ng_lut_blue[i] = (i << (rgb_blue_bits + rgb_blue_shift - 8));
298 else
299 for (i = 0; i < 256; i++)
300 ng_lut_blue[i] = (i >> (8 - rgb_blue_bits)) << rgb_blue_shift;
301
302 switch (ng_vfmt_to_depth[fmtid]) {
303 case 16:
304 if (swap) {
305 for (i = 0; i < 256; i++) {
306 ng_lut_red[i] = SWAP2(ng_lut_red[i]);
307 ng_lut_green[i] = SWAP2(ng_lut_green[i]);
308 ng_lut_blue[i] = SWAP2(ng_lut_blue[i]);
309 }
310 }
311 for (i = 0; i < nconv2; i++)
312 lut2_list[i].fmtid_out = fmtid;
313 ng_conv_register(NG_PLUGIN_MAGIC,"built-in",lut2_list,nconv2);
314 break;
315 case 32:
316 if (swap) {
317 for (i = 0; i < 256; i++) {
318 ng_lut_red[i] = SWAP4(ng_lut_red[i]);
319 ng_lut_green[i] = SWAP4(ng_lut_green[i]);
320 ng_lut_blue[i] = SWAP4(ng_lut_blue[i]);
321 }
322 }
323 for (i = 0; i < nconv4; i++)
324 lut4_list[i].fmtid_out = fmtid;
325 ng_conv_register(NG_PLUGIN_MAGIC,"built-in",lut4_list,nconv4);
326 break;
327 }
328 }
329