Instrument Neutral Distributed Interface INDI 2.2.5
ccvt_misc.c
Go to the documentation of this file.
1/* CCVT: ColourConVerT: simple library for converting colourspaces
2 Copyright (C) 2002 Nemosoft Unv.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19 For questions, remarks, patches, etc. for this program, the author can be
20 reached at [email protected].
21*/
22
23/* This file contains CCVT functions that aren't available in assembly yet
24 (or are not worth programming)
25 */
26
27/*
28 * $Log$
29 * Revision 1.2 2005/04/29 16:51:20 mutlaqja
30 * Adding initial support for Video 4 Linux 2 drivers. This mean that KStars can probably control Meade Lunar Planetary Imager (LPI). V4L2 requires a fairly recent kernel (> 2.6.9) and many drivers don't fully support it yet. It will take sometime. KStars still supports V4L1 and will continue so until V4L1 is obsolete. Please test KStars video drivers if you can. Any comments welcomed.
31 *
32 * CCMAIL: [email protected]
33 *
34 * Revision 1.1 2004/06/26 23:12:03 mutlaqja
35 * Hopefully this will fix compile issues on 64bit archs, and FreeBSD, among others. The assembly code is replaced with a more portable, albeit slower C implementation. I imported the videodev.h header after cleaning it for user space.
36 *
37 * Anyone who has problems compiling this, please report the problem to [email protected]
38 *
39 * I noticed one odd thing after updating my kdelibs, the LEDs don't change color when state is changed. Try that by starting any INDI device, and hit connect, if the LED turns to yellow and back to grey then it works fine, otherwise, we've got a problem.
40 *
41 * CCMAIL: [email protected]
42 *
43 * Revision 1.7 2003/01/02 04:10:19 nemosoft
44 * Adding ''upside down" conversion to rgb/bgr routines
45 *
46 * Revision 1.6 2002/12/03 23:29:11 nemosoft
47 * *** empty log message ***
48 *
49 * Revision 1.5 2002/12/03 23:27:41 nemosoft
50 * fixing log messages (gcc 3.2 complaining)
51 *
52 Revision 1.4 2002/12/03 22:29:07 nemosoft
53 Fixing up FTP stuff and some video
54
55 Revision 1.3 2002/11/03 22:46:25 nemosoft
56 Adding various RGB to RGB functions.
57 Adding proper copyright header too.
58 */
59
60#include "ccvt.h"
61#include "ccvt_types.h"
62//#include "indidevapi.h"
63#include "jpegutils.h"
64
65#include <stdlib.h>
66#include <string.h>
67
68static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
69static float RGBYUV01684[256], RGBYUV03316[256];
70static float RGBYUV04187[256], RGBYUV00813[256];
71
72void InitLookupTable(void);
73
74/* YUYV: two Y's and one U/V */
75#if 0
76void ccvt_yuyv_rgb32(int width, int height, const void *src, void *dst)
77{
78}
79#endif
80
81void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst)
82{
83 const unsigned char *s;
85 int l, c;
86 int r, g, b, cr, cg, cb, y1, y2;
87
88 l = height;
89 s = src;
90 d = dst;
91 while (l--)
92 {
93 c = width >> 1;
94 while (c--)
95 {
96 y1 = *s++;
97 cb = ((*s - 128) * 454) >> 8;
98 cg = (*s++ - 128) * 88;
99 y2 = *s++;
100 cr = ((*s - 128) * 359) >> 8;
101 cg = (cg + (*s++ - 128) * 183) >> 8;
102
103 r = y1 + cr;
104 b = y1 + cb;
105 g = y1 - cg;
106 SAT(r);
107 SAT(g);
108 SAT(b);
109 d->b = b;
110 d->g = g;
111 d->r = r;
112 d++;
113 r = y2 + cr;
114 b = y2 + cb;
115 g = y2 - cg;
116 SAT(r);
117 SAT(g);
118 SAT(b);
119 d->b = b;
120 d->g = g;
121 d->r = r;
122 d++;
123 }
124 }
125}
126
127void ccvt_yuyv_bgr24(int width, int height, const void *src, void *dst)
128{
129 const unsigned char *s;
130 PIXTYPE_bgr24 *d;
131 int l, c;
132 int r, g, b, cr, cg, cb, y1, y2;
133
134 l = height;
135 s = src;
136 d = dst;
137 while (l--)
138 {
139 c = width >> 1;
140 while (c--)
141 {
142 y1 = *s++;
143 cb = ((*s - 128) * 454) >> 8;
144 cg = (*s++ - 128) * 88;
145 y2 = *s++;
146 cr = ((*s - 128) * 359) >> 8;
147 cg = (cg + (*s++ - 128) * 183) >> 8;
148
149 r = y1 + cr;
150 b = y1 + cb;
151 g = y1 - cg;
152 SAT(r);
153 SAT(g);
154 SAT(b);
155 d->b = b;
156 d->g = g;
157 d->r = r;
158 d++;
159 r = y2 + cr;
160 b = y2 + cb;
161 g = y2 - cg;
162 SAT(r);
163 SAT(g);
164 SAT(b);
165 d->b = b;
166 d->g = g;
167 d->r = r;
168 d++;
169 }
170 }
171}
172
173void ccvt_yuyv_rgb24(int width, int height, const void *src, void *dst)
174{
175 const unsigned char *s;
176 PIXTYPE_rgb24 *d;
177 int l, c;
178 int r, g, b, cr, cg, cb, y1, y2;
179
180 l = height;
181 s = src;
182 d = dst;
183 while (l--)
184 {
185 c = width >> 1;
186 while (c--)
187 {
188 y1 = *s++;
189 cb = ((*s - 128) * 454) >> 8;
190 cg = (*s++ - 128) * 88;
191 y2 = *s++;
192 cr = ((*s - 128) * 359) >> 8;
193 cg = (cg + (*s++ - 128) * 183) >> 8;
194
195 r = y1 + cr;
196 b = y1 + cb;
197 g = y1 - cg;
198 SAT(r);
199 SAT(g);
200 SAT(b);
201 d->r = r;
202 d->g = g;
203 d->b = b;
204 d++;
205 r = y2 + cr;
206 b = y2 + cb;
207 g = y2 - cg;
208 SAT(r);
209 SAT(g);
210 SAT(b);
211 d->r = r;
212 d->g = g;
213 d->b = b;
214 d++;
215 }
216 }
217}
218
219void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv)
220{
221 int n, l, j;
222 const unsigned char *s1, *s2;
223 unsigned char *dy, *du, *dv;
224
225 /* Disregard last column/line if width/height is odd */
226 width -= width % 2;
227 height -= height %2;
228
229 dy = (unsigned char *)dsty;
230 du = (unsigned char *)dstu;
231 dv = (unsigned char *)dstv;
232 s1 = (unsigned char *)src;
233 s2 = s1; /* keep pointer */
234 n = width * height;
235 for (; n > 0; n--)
236 {
237 *dy = *s1;
238 dy++;
239 s1 += 2;
240 }
241
242 /* Two options here: average U/V values, or skip every second row */
243 s1 = s2; /* restore pointer */
244 s1++; /* point to U */
245 for (l = 0; l < height; l += 2)
246 {
247 s2 = s1 + width * 2; /* odd line */
248 for (j = 0; j < width; j += 2)
249 {
250 *du = (*s1 + *s2) / 2;
251 du++;
252 s1 += 2;
253 s2 += 2;
254 *dv = (*s1 + *s2) / 2;
255 dv++;
256 s1 += 2;
257 s2 += 2;
258 }
259 s1 = s2;
260 }
261}
262
263void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
264{
265 long int i;
266 unsigned char *rawpt, *scanpt;
267 long int size;
268
269 rawpt = src;
270 scanpt = dst;
271 size = WIDTH * HEIGHT;
272
273 for (i = 0; i < size; i++)
274 {
275 if ((i / WIDTH) % 2 == 0)
276 {
277 if ((i % 2) == 0)
278 {
279 /* B */
280 if ((i > WIDTH) && ((i % WIDTH) > 0))
281 {
282 *scanpt++ =
283 (*(rawpt - WIDTH - 1) + *(rawpt - WIDTH + 1) + *(rawpt + WIDTH - 1) + *(rawpt + WIDTH + 1)) /
284 4; /* R */
285 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt + WIDTH) + *(rawpt - WIDTH)) / 4; /* G */
286 *scanpt++ = *rawpt; /* B */
287 }
288 else
289 {
290 /* first line or left column */
291 *scanpt++ = *(rawpt + WIDTH + 1); /* R */
292 *scanpt++ = (*(rawpt + 1) + *(rawpt + WIDTH)) / 2; /* G */
293 *scanpt++ = *rawpt; /* B */
294 }
295 }
296 else
297 {
298 /* (B)G */
299 if ((i > WIDTH) && ((i % WIDTH) < (WIDTH - 1)))
300 {
301 *scanpt++ = (*(rawpt + WIDTH) + *(rawpt - WIDTH)) / 2; /* R */
302 *scanpt++ = *rawpt; /* G */
303 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2; /* B */
304 }
305 else
306 {
307 /* first line or right column */
308 *scanpt++ = *(rawpt + WIDTH); /* R */
309 *scanpt++ = *rawpt; /* G */
310 *scanpt++ = *(rawpt - 1); /* B */
311 }
312 }
313 }
314 else
315 {
316 if ((i % 2) == 0)
317 {
318 /* G(R) */
319 if ((i < (WIDTH * (HEIGHT - 1))) && ((i % WIDTH) > 0))
320 {
321 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2; /* R */
322 *scanpt++ = *rawpt; /* G */
323 *scanpt++ = (*(rawpt + WIDTH) + *(rawpt - WIDTH)) / 2; /* B */
324 }
325 else
326 {
327 /* bottom line or left column */
328 *scanpt++ = *(rawpt + 1); /* R */
329 *scanpt++ = *rawpt; /* G */
330 *scanpt++ = *(rawpt - WIDTH); /* B */
331 }
332 }
333 else
334 {
335 /* R */
336 if (i < (WIDTH * (HEIGHT - 1)) && ((i % WIDTH) < (WIDTH - 1)))
337 {
338 *scanpt++ = *rawpt; /* R */
339 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt - WIDTH) + *(rawpt + WIDTH)) / 4; /* G */
340 *scanpt++ =
341 (*(rawpt - WIDTH - 1) + *(rawpt - WIDTH + 1) + *(rawpt + WIDTH - 1) + *(rawpt + WIDTH + 1)) /
342 4; /* B */
343 }
344 else
345 {
346 /* bottom line or right column */
347 *scanpt++ = *rawpt; /* R */
348 *scanpt++ = (*(rawpt - 1) + *(rawpt - WIDTH)) / 2; /* G */
349 *scanpt++ = *(rawpt - WIDTH - 1); /* B */
350 }
351 }
352 }
353 rawpt++;
354 }
355}
356
357void bayer16_2_rgb24(unsigned short *dst, unsigned short *src, long int WIDTH, long int HEIGHT)
358{
359 long int i;
360 unsigned short *rawpt, *scanpt;
361 long int size;
362
363 rawpt = src;
364 scanpt = dst;
365 size = WIDTH * HEIGHT;
366
367 for (i = 0; i < size; i++)
368 {
369 if ((i / WIDTH) % 2 == 0)
370 {
371 if ((i % 2) == 0)
372 {
373 /* B */
374 if ((i > WIDTH) && ((i % WIDTH) > 0))
375 {
376 *scanpt++ =
377 (*(rawpt - WIDTH - 1) + *(rawpt - WIDTH + 1) + *(rawpt + WIDTH - 1) + *(rawpt + WIDTH + 1)) /
378 4; /* R */
379 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt + WIDTH) + *(rawpt - WIDTH)) / 4; /* G */
380 *scanpt++ = *rawpt; /* B */
381 }
382 else
383 {
384 /* first line or left column */
385 *scanpt++ = *(rawpt + WIDTH + 1); /* R */
386 *scanpt++ = (*(rawpt + 1) + *(rawpt + WIDTH)) / 2; /* G */
387 *scanpt++ = *rawpt; /* B */
388 }
389 }
390 else
391 {
392 /* (B)G */
393 if ((i > WIDTH) && ((i % WIDTH) < (WIDTH - 1)))
394 {
395 *scanpt++ = (*(rawpt + WIDTH) + *(rawpt - WIDTH)) / 2; /* R */
396 *scanpt++ = *rawpt; /* G */
397 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2; /* B */
398 }
399 else
400 {
401 /* first line or right column */
402 *scanpt++ = *(rawpt + WIDTH); /* R */
403 *scanpt++ = *rawpt; /* G */
404 *scanpt++ = *(rawpt - 1); /* B */
405 }
406 }
407 }
408 else
409 {
410 if ((i % 2) == 0)
411 {
412 /* G(R) */
413 if ((i < (WIDTH * (HEIGHT - 1))) && ((i % WIDTH) > 0))
414 {
415 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2; /* R */
416 *scanpt++ = *rawpt; /* G */
417 *scanpt++ = (*(rawpt + WIDTH) + *(rawpt - WIDTH)) / 2; /* B */
418 }
419 else
420 {
421 /* bottom line or left column */
422 *scanpt++ = *(rawpt + 1); /* R */
423 *scanpt++ = *rawpt; /* G */
424 *scanpt++ = *(rawpt - WIDTH); /* B */
425 }
426 }
427 else
428 {
429 /* R */
430 if (i < (WIDTH * (HEIGHT - 1)) && ((i % WIDTH) < (WIDTH - 1)))
431 {
432 *scanpt++ = *rawpt; /* R */
433 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt - WIDTH) + *(rawpt + WIDTH)) / 4; /* G */
434 *scanpt++ =
435 (*(rawpt - WIDTH - 1) + *(rawpt - WIDTH + 1) + *(rawpt + WIDTH - 1) + *(rawpt + WIDTH + 1)) /
436 4; /* B */
437 }
438 else
439 {
440 /* bottom line or right column */
441 *scanpt++ = *rawpt; /* R */
442 *scanpt++ = (*(rawpt - 1) + *(rawpt - WIDTH)) / 2; /* G */
443 *scanpt++ = *(rawpt - WIDTH - 1); /* B */
444 }
445 }
446 }
447 rawpt++;
448 }
449}
450
451void bayer_rggb_2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
452{
453 long int i;
454 unsigned char *rawpt, *scanpt;
455 long int size;
456
457 rawpt = src;
458 scanpt = dst;
459 size = WIDTH * HEIGHT;
460
461 for (i = 0; i < size; i++)
462 {
463 if ((i / WIDTH) % 2 == 0) //wenn zeile grade
464 {
465 if ((i % 2) == 0) //spalte gerade
466 {
467 /* B */
468 if ((i > WIDTH) && ((i % WIDTH) > 0)) // wenn nicht erste zeile oder linke spalte
469 {
470 *scanpt++ = *rawpt; /* R */
471 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt + WIDTH) + *(rawpt - WIDTH)) / 4; /* G */
472 *scanpt++ =
473 (*(rawpt - WIDTH - 1) + *(rawpt - WIDTH + 1) + *(rawpt + WIDTH - 1) + *(rawpt + WIDTH + 1)) /
474 4; /* B */
475 }
476 else
477 {
478 /* first line or left column */
479 *scanpt++ = *rawpt; /* R */
480 *scanpt++ = (*(rawpt + 1) + *(rawpt + WIDTH)) / 2; /* G */
481 *scanpt++ = *(rawpt + WIDTH + 1); /* B */
482 }
483 }
484 else
485 {
486 /* (B)G */
487 if ((i > WIDTH) && ((i % WIDTH) < (WIDTH - 1)))
488 {
489 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2; /* R */
490 *scanpt++ = *rawpt; /* G */
491 *scanpt++ = (*(rawpt + WIDTH) + *(rawpt - WIDTH)) / 2; /* B */
492 }
493 else
494 {
495 /* first line or right column */
496 *scanpt++ = *(rawpt - 1); /* R */
497 *scanpt++ = *rawpt; /* G */
498 *scanpt++ = *(rawpt + WIDTH); /* B */
499 }
500 }
501 }
502 else
503 {
504 if ((i % 2) == 0)
505 {
506 /* G(R) */
507 if ((i < (WIDTH * (HEIGHT - 1))) && ((i % WIDTH) > 0))
508 {
509 *scanpt++ = (*(rawpt + WIDTH) + *(rawpt - WIDTH)) / 2; /* R */
510 *scanpt++ = *rawpt; /* G */
511 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2; /* B */
512 }
513 else
514 {
515 /* bottom line or left column */
516 *scanpt++ = *(rawpt - WIDTH); /* R */
517 *scanpt++ = *rawpt; /* G */
518 *scanpt++ = *(rawpt + 1); /* B */
519 }
520 }
521 else
522 {
523 /* R */
524 if (i < (WIDTH * (HEIGHT - 1)) && ((i % WIDTH) < (WIDTH - 1)))
525 {
526 *scanpt++ =
527 (*(rawpt - WIDTH - 1) + *(rawpt - WIDTH + 1) + *(rawpt + WIDTH - 1) + *(rawpt + WIDTH + 1)) /
528 4; /* R */
529 *scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt - WIDTH) + *(rawpt + WIDTH)) / 4; /* G */
530 *scanpt++ = *rawpt; /* B */
531 }
532 else
533 {
534 /* bottom line or right column */
535 *scanpt++ = *(rawpt - WIDTH - 1); /* R */
536 *scanpt++ = (*(rawpt - 1) + *(rawpt - WIDTH)) / 2; /* G */
537 *scanpt++ = *rawpt; /* B */
538 }
539 }
540 }
541 rawpt++;
542 }
543}
544
545void bayer_grbg_to_rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
546{
547 //Format is
548 // GRGRGRGRGR row width = width,
549 // BGBGBGBGBG this interpolates it as simply as possible
550 // GRGRGRGRGR
551 // BGBGBGBGBG
552
553 // Output is
554 // RGBRGBRGBRGBRGB row width = 3x width
555 // RGBRGBRGBRGBRGB each pixel = 3 bytes
556
557 long int row;
558 long int col;
559 long int width=WIDTH;
560 int RED = 0;
561 int GREEN = 1;
562 int BLUE = 2;
563 for (row = 0; row < HEIGHT; row++) {
564 for (col = 0; col < WIDTH; col++) {
565 //General case:
566 if(row % 2 == 0) { //GRGRGR Row
567 if(col % 2 == 0) {//Over Green
568 //TODO: Double check 1st/last row
569 if (col != 0 && col != WIDTH -1) { // NORMAL
570 dst[(row*width+col)*3+RED]=(src[row*width+col+1]+src[row*width+col-1])/2; // Reds are to L/R
571 } else { //EDGE
572 if (col == 0) { dst[(row*width+col)*3+RED]=src[row*width+col+1];}
573 if (col == WIDTH -1 ) { dst[(row*width+col)*3+RED]=src[row*width+col-1]; }
574 }
575 dst[(row*width+col)*3+GREEN]=src[row*width+col];
576 if (row !=0 && row !=HEIGHT-1) { // NORMAL
577 dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col]+src[(row-1)*width+col])/2; //Blues are above and below.
578 } else { // EDGE
579 if (row == 0) {dst[(row*width+col)*3+BLUE]=src[(row+1)*width+col];}
580 if (row == HEIGHT -1) {dst[(row*width+col)*3+BLUE]=src[(row-1)*width+col];}
581 }
582 } else { // Over RED
583 dst[(row*width+col)*3+RED]=src[row*width+col];
584 if (col != WIDTH -1 && row !=0 ) { // NORMAL (Left side and bottom count as normal
585 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/4; //GREENS are in all 4 directions
586 dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col+1]+src[(row-1)*width+col+1]+src[(row+1)*width+col-1]+src[(row-1)*width+col-1])/4; //Blues are caddy corner and below.
587 } else { // EDGE
588 if (col != WIDTH -1 && row == 0) {
589 //Corner && Side:
590 //
591 //,G*G.
592 //,BGB.
593 //,....
594 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row)*width+col+1]+src[(row)*width+col+1])/3;
595 dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col+1]+src[(row+1)*width+col-1])/2;
596 }
597
598 if (col == WIDTH -1 && row !=0 ) {
599 //Side
600 //...
601 //.BG
602 //.GR
603 //.BG
604 //...
605 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row)*width+col-1])/3;
606 dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col-1]+src[(row-1)*width+col-1])/2;
607
608 }
609 if (col == WIDTH -1 && row ==0) {
610 //Corner (col=max, row=0)
611 //
612 //.G*
613 //.BG
614 //...
615 // Only two valid green neighbors: left (row,col-1) and below (row+1,col).
616 // There is no row above (row-1 would be out-of-bounds).
617 dst[(row*width+col)*3+GREEN]=(src[(row+0)*width+col-1]+src[(row+1)*width+col])/2;
618 dst[(row*width+col)*3+BLUE]=src[(row+1)*width+col-1];
619 }
620 if (col == 1 && row !=0) { //Unnecessary Left here to explain why
621 //Side && Corner (col=1, row=max)
622 // .....
623 // BGBG..
624 // G*GR
625 // BGBG..
626 // ,,,,,,
627 // NORMAL
628 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/4; //GREENS are in all 4 directions
629 dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col+1]+src[(row-1)*width+col+1]+src[(row+1)*width+col-1]+src[(row-1)*width+col-1])/4; //Blues are caddy corner and below.
630 }
631 if (row == HEIGHT -1) {//Unnecessary Left here to explain why
632 //Bottom row (would actually be HEIGHT -2 it still looks like a normal pixel for us
633 // ,.....
634 // ,.BGBG..
635 // ,.G*RG..
636 // ,.BGBG..
637 //
638 // NORMAL
639 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/4; //GREENS are in all 4 directions
640 dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col+1]+src[(row-1)*width+col+1]+src[(row+1)*width+col-1]+src[(row-1)*width+col-1])/4; //Blues are caddy corner and below.
641
642 }
643 }
644 }
645 } else { //BRBRBR Row
646 //if (col != 0 && col != WIDTH -1 && row != 0 && row != HEIGHT-1) {
647 if (col % 2 == 0) {//Over Blue
648 dst[(row*width+col)*3+BLUE]=src[row*width+col];
649 if ( col != 0 && row != HEIGHT -1) { //Normal
650 // Enough clearance to use this:
651 // RGR
652 // G*G
653 // RGR
654 dst[(row*width+col)*3+RED]=(src[(row+1)*width+col+1]+src[(row-1)*width+col+1]+src[(row+1)*width+col-1]+src[(row-1)*width+col-1])/4;//Reds are caddy corner and below.
655 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/4; //GREENS are in all 4 directions
656 } else { // EDGE CASES over blue
657 if (col == 0 && row != HEIGHT -1) {
658 // ,,,,,,,
659 // GRGRGR.
660 // *GBGBG.
661 // GRGRGR.
662 // .......
663 dst[(row*width+col)*3+RED]=(src[(row+1)*width+col+1]+src[(row-1)*width+col+1])/2;
664 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/3;
665 }
666 if (row == HEIGHT -1 && col !=0) {
667 // ........
668 // .GRGRGR.
669 // .BG*GBG.
670 dst[(row*width+col)*3+RED]=(src[(row-1)*width+col+1]+src[(row-1)*width+col-1])/2;
671 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/3;
672 }
673 if (row == HEIGHT -1 && col ==0) {
674 // .....
675 // GRGR.
676 // *GBG.
677 dst[(row*width+col)*3+RED]=(src[(row-1)*width+col+1]+src[(row-1)*width+col-1])/2;
678 dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/3;
679 }
680
681 }
682 } else { // Over Green
683 dst[(row*width+col)*3+GREEN]=src[row*width+col]; // Over Green Pixel
684 if (col != WIDTH -1 && row != HEIGHT -1) { //NORMAL
685 // Enough clearance to use this:
686 // GRG
687 // B*B
688 // GRG
689
690 dst[(row*width+col)*3+RED]=(src[(row+1)*width+col]+src[(row-1)*width+col])/2; // Reds are above/below
691 dst[(row*width+col)*3+BLUE]=(src[row*width+col+1]+src[row*width+col-1])/2; //Blues are left/right
692 } else {
693 if (col == WIDTH -1 && row != HEIGHT -1) {
694 // ,,,,,
695 // .GRGR
696 // .BGB*
697 // .GRGR
698 // .....
699 dst[(row*width+col)*3+RED]=(src[(row+1)*width+col]+src[(row-1)*width+col])/2; // Reds are above/below
700 dst[(row*width+col)*3+BLUE]=src[row*width+col-1]; //Blue is left
701 }
702 if (row == HEIGHT -1 && col != WIDTH -1) {
703 // .....
704 // .GRGR
705 // .B*BG
706 dst[(row*width+col)*3+RED]=src[(row-1)*width+col]; // Red is above
707 dst[(row*width+col)*3+BLUE]=(src[row*width+col+1]+src[row*width+col-1])/2; //Blues are left/right
708 }
709 if (row == HEIGHT -1 && col == WIDTH -1) {
710 // ...
711 // .GR
712 // .B*
713 dst[(row*width+col)*3+RED]=src[(row-1)*width+col]; // Red is above
714 dst[(row*width+col)*3+BLUE]=src[row*width+col-1]; //Blue is left
715 }
716 }
717 }
718 }
719 }
720 }
721}
722
723int mjpegtoyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height, unsigned int size)
724{
725 unsigned char *yuv[3];
726 unsigned char *y, *u, *v;
727 int loop, ret;
728
729 yuv[0] = malloc(width * height * sizeof(yuv[0][0]));
730 yuv[1] = malloc(width * height / 4 * sizeof(yuv[1][0]));
731 yuv[2] = malloc(width * height / 4 * sizeof(yuv[2][0]));
732
733 ret = decode_jpeg_raw(cap_map, size, 0, 420, width, height, yuv[0], yuv[1], yuv[2]);
734
735 y = map;
736 u = y + width * height;
737 v = u + (width * height) / 4;
738 memset(y, 0, width * height);
739 memset(u, 0, width * height / 4);
740 memset(v, 0, width * height / 4);
741
742 for (loop = 0; loop < width * height; loop++)
743 *map++ = yuv[0][loop];
744
745 for (loop = 0; loop < width * height / 4; loop++)
746 *map++ = yuv[1][loop];
747
748 for (loop = 0; loop < width * height / 4; loop++)
749 *map++ = yuv[2][loop];
750
751 free(yuv[0]);
752 free(yuv[1]);
753 free(yuv[2]);
754
755 return ret;
756}
757
758/************************************************************************
759 *
760 * int RGB2YUV (int x_dim, int y_dim, void *bmp, YUV *yuv)
761 *
762 * Purpose : It takes a 24-bit RGB bitmap and convert it into
763 * YUV (4:2:0) format
764 *
765 * Input : x_dim the x dimension of the bitmap
766 * y_dim the y dimension of the bitmap
767 * bmp pointer to the buffer of the bitmap
768 * yuv pointer to the YUV structure
769 *
770 * Output : 0 OK
771 * 1 wrong dimension
772 * 2 memory allocation error
773 *
774 * Side Effect :
775 * None
776 *
777 * Date : 09/28/2000
778 *
779 * Contacts:
780 *
781 * Adam Li
782 *
783 * DivX Advance Research Center <[email protected]>
784 *
785 ************************************************************************/
786
787int RGB2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
788{
789 static int init_done = 0;
790
791 long i, j, size;
792 unsigned char *r, *g, *b;
793 unsigned char *y, *u, *v;
794 unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
795 unsigned char *y_buffer, *u_buffer, *v_buffer;
796 unsigned char *sub_u_buf, *sub_v_buf;
797
798 if (init_done == 0)
799 {
801 init_done = 1;
802 }
803
804 /* check to see if x_dim and y_dim are divisible by 2*/
805 if ((x_dim % 2) || (y_dim % 2))
806 return 1;
807 size = x_dim * y_dim;
808
809 /* allocate memory*/
810 y_buffer = (unsigned char *)y_out;
811 sub_u_buf = (unsigned char *)u_out;
812 sub_v_buf = (unsigned char *)v_out;
813 u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
814 v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
815 if (!(u_buffer && v_buffer))
816 {
817 if (u_buffer)
818 free(u_buffer);
819 if (v_buffer)
820 free(v_buffer);
821 return 2;
822 }
823
824 b = (unsigned char *)bmp;
825 y = y_buffer;
826 u = u_buffer;
827 v = v_buffer;
828
829 /* convert RGB to YUV*/
830 if (!flip)
831 {
832 for (j = 0; j < y_dim; j++)
833 {
834 y = y_buffer + (y_dim - j - 1) * x_dim;
835 u = u_buffer + (y_dim - j - 1) * x_dim;
836 v = v_buffer + (y_dim - j - 1) * x_dim;
837
838 for (i = 0; i < x_dim; i++)
839 {
840 g = b + 1;
841 r = b + 2;
842 *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
843 *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
844 *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
845 b += 3;
846 y++;
847 u++;
848 v++;
849 }
850 }
851 }
852 else
853 {
854 for (i = 0; i < size; i++)
855 {
856 g = b + 1;
857 r = b + 2;
858 *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
859 *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
860 *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
861 b += 3;
862 y++;
863 u++;
864 v++;
865 }
866 }
867
868 /* subsample UV*/
869 for (j = 0; j < y_dim / 2; j++)
870 {
871 psu = sub_u_buf + j * x_dim / 2;
872 psv = sub_v_buf + j * x_dim / 2;
873 pu1 = u_buffer + 2 * j * x_dim;
874 pu2 = u_buffer + (2 * j + 1) * x_dim;
875 pv1 = v_buffer + 2 * j * x_dim;
876 pv2 = v_buffer + (2 * j + 1) * x_dim;
877 for (i = 0; i < x_dim / 2; i++)
878 {
879 *psu = (*pu1 + *(pu1 + 1) + *pu2 + *(pu2 + 1)) / 4;
880 *psv = (*pv1 + *(pv1 + 1) + *pv2 + *(pv2 + 1)) / 4;
881 psu++;
882 psv++;
883 pu1 += 2;
884 pu2 += 2;
885 pv1 += 2;
886 pv2 += 2;
887 }
888 }
889
890 free(u_buffer);
891 free(v_buffer);
892
893 return 0;
894}
895
896int BGR2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
897{
898 static int init_done = 0;
899
900 long i, j, size;
901 unsigned char *r, *g, *b;
902 unsigned char *y, *u, *v;
903 unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
904 unsigned char *y_buffer, *u_buffer, *v_buffer;
905 unsigned char *sub_u_buf, *sub_v_buf;
906
907 if (init_done == 0)
908 {
910 init_done = 1;
911 }
912
913 /* check to see if x_dim and y_dim are divisible by 2*/
914 if ((x_dim % 2) || (y_dim % 2))
915 return 1;
916 size = x_dim * y_dim;
917
918 /* allocate memory*/
919 y_buffer = (unsigned char *)y_out;
920 sub_u_buf = (unsigned char *)u_out;
921 sub_v_buf = (unsigned char *)v_out;
922 u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
923 v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
924 if (!(u_buffer && v_buffer))
925 {
926 if (u_buffer)
927 free(u_buffer);
928 if (v_buffer)
929 free(v_buffer);
930 return 2;
931 }
932
933 r = (unsigned char *)bmp;
934 y = y_buffer;
935 u = u_buffer;
936 v = v_buffer;
937
938 /* convert RGB to YUV*/
939 if (!flip)
940 {
941 for (j = 0; j < y_dim; j++)
942 {
943 y = y_buffer + (y_dim - j - 1) * x_dim;
944 u = u_buffer + (y_dim - j - 1) * x_dim;
945 v = v_buffer + (y_dim - j - 1) * x_dim;
946
947 for (i = 0; i < x_dim; i++)
948 {
949 g = r + 1;
950 b = r + 2;
951 *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
952 *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
953 *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
954 r += 3;
955 y++;
956 u++;
957 v++;
958 }
959 }
960 }
961 else
962 {
963 for (i = 0; i < size; i++)
964 {
965 g = r + 1;
966 b = r + 2;
967 *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
968 *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
969 *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
970 r += 3;
971 y++;
972 u++;
973 v++;
974 }
975 }
976
977 /* subsample UV*/
978 for (j = 0; j < y_dim / 2; j++)
979 {
980 psu = sub_u_buf + j * x_dim / 2;
981 psv = sub_v_buf + j * x_dim / 2;
982 pu1 = u_buffer + 2 * j * x_dim;
983 pu2 = u_buffer + (2 * j + 1) * x_dim;
984 pv1 = v_buffer + 2 * j * x_dim;
985 pv2 = v_buffer + (2 * j + 1) * x_dim;
986 for (i = 0; i < x_dim / 2; i++)
987 {
988 *psu = (*pu1 + *(pu1 + 1) + *pu2 + *(pu2 + 1)) / 4;
989 *psv = (*pv1 + *(pv1 + 1) + *pv2 + *(pv2 + 1)) / 4;
990 psu++;
991 psv++;
992 pu1 += 2;
993 pu2 += 2;
994 pv1 += 2;
995 pv2 += 2;
996 }
997 }
998
999 free(u_buffer);
1000 free(v_buffer);
1001
1002 return 0;
1003}
1004
1006{
1007 int i;
1008
1009 for (i = 0; i < 256; i++)
1010 RGBYUV02990[i] = (float)0.2990 * i;
1011 for (i = 0; i < 256; i++)
1012 RGBYUV05870[i] = (float)0.5870 * i;
1013 for (i = 0; i < 256; i++)
1014 RGBYUV01140[i] = (float)0.1140 * i;
1015 for (i = 0; i < 256; i++)
1016 RGBYUV01684[i] = (float)0.1684 * i;
1017 for (i = 0; i < 256; i++)
1018 RGBYUV03316[i] = (float)0.3316 * i;
1019 for (i = 0; i < 256; i++)
1020 RGBYUV04187[i] = (float)0.4187 * i;
1021 for (i = 0; i < 256; i++)
1022 RGBYUV00813[i] = (float)0.0813 * i;
1023}
1024
1025/* RGB/BGR to RGB/BGR */
1026
1027#define RGBBGR_BODY24(TIN, TOUT) \
1028 void ccvt_##TIN##_##TOUT(int width, int height, const void *const src, void *dst) \
1029 { \
1030 const PIXTYPE_##TIN *in = src; \
1031 PIXTYPE_##TOUT *out = dst; \
1032 int l, c, stride = 0; \
1033 \
1034 stride = width; \
1035 out += ((height - 1) * width); \
1036 stride *= 2; \
1037 for (l = 0; l < height; l++) \
1038 { \
1039 for (c = 0; c < width; c++) \
1040 { \
1041 out->r = in->r; \
1042 out->g = in->g; \
1043 out->b = in->b; \
1044 in++; \
1045 out++; \
1046 } \
1047 out -= stride; \
1048 } \
1049 }
1050
1051#define RGBBGR_BODY32(TIN, TOUT) \
1052 void ccvt_##TIN##_##TOUT(int width, int height, const void *const src, void *dst) \
1053 { \
1054 const PIXTYPE_##TIN *in = src; \
1055 PIXTYPE_##TOUT *out = dst; \
1056 int l, c, stride = 0; \
1057 \
1058 stride = width; \
1059 out += ((height - 1) * width); \
1060 stride *= 2; \
1061 for (l = 0; l < height; l++) \
1062 { \
1063 for (c = 0; c < width; c++) \
1064 { \
1065 out->r = in->r; \
1066 out->g = in->g; \
1067 out->b = in->b; \
1068 out->z = 0; \
1069 in++; \
1070 out++; \
1071 } \
1072 out -= stride; \
1073 } \
1074 }
1075
1076RGBBGR_BODY32(bgr24, bgr32)
1077RGBBGR_BODY32(bgr24, rgb32)
1078RGBBGR_BODY32(rgb24, bgr32)
1079RGBBGR_BODY32(rgb24, rgb32)
1080
1081RGBBGR_BODY24(bgr32, bgr24)
1082RGBBGR_BODY24(bgr32, rgb24)
1083RGBBGR_BODY24(rgb32, bgr24)
1084RGBBGR_BODY24(rgb32, rgb24)
int BGR2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
Definition ccvt_misc.c:896
void InitLookupTable(void)
Definition ccvt_misc.c:1005
void bayer16_2_rgb24(unsigned short *dst, unsigned short *src, long int WIDTH, long int HEIGHT)
Definition ccvt_misc.c:357
void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst)
Definition ccvt_misc.c:81
#define RGBBGR_BODY24(TIN, TOUT)
Definition ccvt_misc.c:1027
void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
Definition ccvt_misc.c:263
int mjpegtoyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height, unsigned int size)
mjpegtoyuv420p MPEG to YUV 420 P
Definition ccvt_misc.c:723
void bayer_grbg_to_rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
Definition ccvt_misc.c:545
void ccvt_yuyv_rgb24(int width, int height, const void *src, void *dst)
Definition ccvt_misc.c:173
void ccvt_yuyv_bgr24(int width, int height, const void *src, void *dst)
Definition ccvt_misc.c:127
#define RGBBGR_BODY32(TIN, TOUT)
Definition ccvt_misc.c:1051
void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv)
Definition ccvt_misc.c:219
void bayer_rggb_2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
Definition ccvt_misc.c:451
int RGB2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
Definition ccvt_misc.c:787
#define SAT(c)
Definition ccvt_types.h:55
int decode_jpeg_raw(unsigned char *jpeg_data, int len, int itype, int ctype, unsigned int width, unsigned int height, unsigned char *raw0, unsigned char *raw1, unsigned char *raw2)
decode JPEG buffer
Definition jpegutils.c:461
unsigned char b
Definition ccvt_types.h:35
unsigned char r
Definition ccvt_types.h:37
unsigned char g
Definition ccvt_types.h:36
unsigned char r
Definition ccvt_types.h:29
unsigned char b
Definition ccvt_types.h:27
unsigned char g
Definition ccvt_types.h:28
unsigned char b
Definition ccvt_types.h:52
unsigned char g
Definition ccvt_types.h:51
unsigned char r
Definition ccvt_types.h:50