Instrument Neutral Distributed Interface INDI  2.0.2
ccvt_misc.c
Go to the documentation of this file.
1 /* CCVT: ColourConVerT: simple library for converting colourspaces
2  Copyright (C) 2002 Nemosoft Unv.
3  Email:athomas@nemsoft.co.uk
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 nemosoft@smcc.demon.nl.
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 obselete. Please test KStars video drivers if you can. Any comments welcomed.
31  *
32  * CCMAIL: kstars-devel@kde.org
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 kstars-devel@kde.org
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: kstars-devel@kde.org
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 
68 static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
69 static float RGBYUV01684[256], RGBYUV03316[256];
70 static float RGBYUV04187[256], RGBYUV00813[256];
71 
72 void InitLookupTable(void);
73 
74 /* YUYV: two Y's and one U/V */
75 #if 0
76 void ccvt_yuyv_rgb32(int width, int height, const void *src, void *dst)
77 {
78 }
79 #endif
80 
81 void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst)
82 {
83  const unsigned char *s;
84  PIXTYPE_bgr32 *d;
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 
127 void 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 
173 void 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 
219 void 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 
263 void 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 
357 void 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 
451 void 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 
545 void 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 == WIDTH -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  dst[(row*width+col)*3+GREEN]=(src[(row-1)*width+col]+src[(row+0)*width+col-1]+src[(row+1)*width+col])/3;
616  dst[(row*width+col)*3+BLUE]=src[(row+1)*width+col-1];
617  }
618  if (col == 1 && row !=0) { //Unnecessary Left here to explain why
619  //Side && Corner (col=1, row=max)
620  // .....
621  // BGBG..
622  // G*GR
623  // BGBG..
624  // ,,,,,,
625  // NORMAL
626  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
627  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.
628  }
629  if (row == HEIGHT -1) {//Unnecessary Left here to explain why
630  //Bottom row (would actually be HEIGHT -2 it still looks like a normal pixel for us
631  // ,.....
632  // ,.BGBG..
633  // ,.G*RG..
634  // ,.BGBG..
635  //
636  // NORMAL
637  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
638  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.
639 
640  }
641  }
642  }
643  } else { //BRBRBR Row
644  //if (col != 0 && col != WIDTH -1 && row != 0 && row != HEIGHT-1) {
645  if (col % 2 == 0) {//Over Blue
646  dst[(row*width+col)*3+BLUE]=src[row*width+col];
647  if ( col != 0 && row != HEIGHT -1) { //Normal
648  // Enough clearance to use this:
649  // RGR
650  // G*G
651  // RGR
652  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.
653  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
654  } else { // EDGE CASES over blue
655  if (col == 0 && row != HEIGHT -1) {
656  // ,,,,,,,
657  // GRGRGR.
658  // *GBGBG.
659  // GRGRGR.
660  // .......
661  dst[(row*width+col)*3+RED]=(src[(row+1)*width+col+1]+src[(row-1)*width+col+1])/2;
662  dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row+0)*width+col+1]+src[(row+0)*width+col-1])/3;
663  }
664  if (row == HEIGHT -1 && col !=0) {
665  // ........
666  // .GRGRGR.
667  // .BG*GBG.
668  dst[(row*width+col)*3+RED]=(src[(row-1)*width+col+1]+src[(row-1)*width+col-1])/2;
669  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;
670  }
671  if (row == HEIGHT -1 && col ==0) {
672  // .....
673  // GRGR.
674  // *GBG.
675  dst[(row*width+col)*3+RED]=(src[(row-1)*width+col+1]+src[(row-1)*width+col-1])/2;
676  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;
677  }
678 
679  }
680  } else { // Over Green
681  dst[(row*width+col)*3+GREEN]=src[row*width+col]; // Over Green Pixel
682  if (col != WIDTH -1 && row != HEIGHT -1) { //NORMAL
683  // Enough clearance to use this:
684  // GRG
685  // B*B
686  // GRG
687 
688  dst[(row*width+col)*3+RED]=(src[(row+1)*width+col]+src[(row-1)*width+col])/2; // Reds are above/below
689  dst[(row*width+col)*3+BLUE]=(src[row*width+col+1]+src[row*width+col-1])/2; //Blues are left/right
690  } else {
691  if (col == WIDTH -1 && row != HEIGHT -1) {
692  // ,,,,,
693  // .GRGR
694  // .BGB*
695  // .GRGR
696  // .....
697  dst[(row*width+col)*3+RED]=(src[(row+1)*width+col]+src[(row-1)*width+col])/2; // Reds are above/below
698  dst[(row*width+col)*3+BLUE]=src[row*width+col-1]; //Blue is left
699  }
700  if (row == HEIGHT -1 && col != WIDTH -1) {
701  // .....
702  // .GRGR
703  // .B*BG
704  dst[(row*width+col)*3+RED]=src[(row-1)*width+col]; // Red is above
705  dst[(row*width+col)*3+BLUE]=(src[row*width+col+1]+src[row*width+col-1])/2; //Blues are left/right
706  }
707  if (row == HEIGHT -1 && col == WIDTH -1) {
708  // ...
709  // .GR
710  // .B*
711  dst[(row*width+col)*3+RED]=src[(row-1)*width+col]; // Red is above
712  dst[(row*width+col)*3+BLUE]=src[row*width+col-1]; //Blue is left
713  }
714  }
715  }
716  }
717  }
718  }
719 }
720 
721 int mjpegtoyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height, unsigned int size)
722 {
723  unsigned char *yuv[3];
724  unsigned char *y, *u, *v;
725  int loop, ret;
726 
727  yuv[0] = malloc(width * height * sizeof(yuv[0][0]));
728  yuv[1] = malloc(width * height / 4 * sizeof(yuv[1][0]));
729  yuv[2] = malloc(width * height / 4 * sizeof(yuv[2][0]));
730 
731  ret = decode_jpeg_raw(cap_map, size, 0, 420, width, height, yuv[0], yuv[1], yuv[2]);
732 
733  y = map;
734  u = y + width * height;
735  v = u + (width * height) / 4;
736  memset(y, 0, width * height);
737  memset(u, 0, width * height / 4);
738  memset(v, 0, width * height / 4);
739 
740  for (loop = 0; loop < width * height; loop++)
741  *map++ = yuv[0][loop];
742 
743  for (loop = 0; loop < width * height / 4; loop++)
744  *map++ = yuv[1][loop];
745 
746  for (loop = 0; loop < width * height / 4; loop++)
747  *map++ = yuv[2][loop];
748 
749  free(yuv[0]);
750  free(yuv[1]);
751  free(yuv[2]);
752 
753  return ret;
754 }
755 
756 /************************************************************************
757  *
758  * int RGB2YUV (int x_dim, int y_dim, void *bmp, YUV *yuv)
759  *
760  * Purpose : It takes a 24-bit RGB bitmap and convert it into
761  * YUV (4:2:0) format
762  *
763  * Input : x_dim the x dimension of the bitmap
764  * y_dim the y dimension of the bitmap
765  * bmp pointer to the buffer of the bitmap
766  * yuv pointer to the YUV structure
767  *
768  * Output : 0 OK
769  * 1 wrong dimension
770  * 2 memory allocation error
771  *
772  * Side Effect :
773  * None
774  *
775  * Date : 09/28/2000
776  *
777  * Contacts:
778  *
779  * Adam Li
780  *
781  * DivX Advance Research Center <darc@projectmayo.com>
782  *
783  ************************************************************************/
784 
785 int RGB2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
786 {
787  static int init_done = 0;
788 
789  long i, j, size;
790  unsigned char *r, *g, *b;
791  unsigned char *y, *u, *v;
792  unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
793  unsigned char *y_buffer, *u_buffer, *v_buffer;
794  unsigned char *sub_u_buf, *sub_v_buf;
795 
796  if (init_done == 0)
797  {
798  InitLookupTable();
799  init_done = 1;
800  }
801 
802  /* check to see if x_dim and y_dim are divisible by 2*/
803  if ((x_dim % 2) || (y_dim % 2))
804  return 1;
805  size = x_dim * y_dim;
806 
807  /* allocate memory*/
808  y_buffer = (unsigned char *)y_out;
809  sub_u_buf = (unsigned char *)u_out;
810  sub_v_buf = (unsigned char *)v_out;
811  u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
812  v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
813  if (!(u_buffer && v_buffer))
814  {
815  if (u_buffer)
816  free(u_buffer);
817  if (v_buffer)
818  free(v_buffer);
819  return 2;
820  }
821 
822  b = (unsigned char *)bmp;
823  y = y_buffer;
824  u = u_buffer;
825  v = v_buffer;
826 
827  /* convert RGB to YUV*/
828  if (!flip)
829  {
830  for (j = 0; j < y_dim; j++)
831  {
832  y = y_buffer + (y_dim - j - 1) * x_dim;
833  u = u_buffer + (y_dim - j - 1) * x_dim;
834  v = v_buffer + (y_dim - j - 1) * x_dim;
835 
836  for (i = 0; i < x_dim; i++)
837  {
838  g = b + 1;
839  r = b + 2;
840  *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
841  *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
842  *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
843  b += 3;
844  y++;
845  u++;
846  v++;
847  }
848  }
849  }
850  else
851  {
852  for (i = 0; i < size; i++)
853  {
854  g = b + 1;
855  r = b + 2;
856  *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
857  *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
858  *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
859  b += 3;
860  y++;
861  u++;
862  v++;
863  }
864  }
865 
866  /* subsample UV*/
867  for (j = 0; j < y_dim / 2; j++)
868  {
869  psu = sub_u_buf + j * x_dim / 2;
870  psv = sub_v_buf + j * x_dim / 2;
871  pu1 = u_buffer + 2 * j * x_dim;
872  pu2 = u_buffer + (2 * j + 1) * x_dim;
873  pv1 = v_buffer + 2 * j * x_dim;
874  pv2 = v_buffer + (2 * j + 1) * x_dim;
875  for (i = 0; i < x_dim / 2; i++)
876  {
877  *psu = (*pu1 + *(pu1 + 1) + *pu2 + *(pu2 + 1)) / 4;
878  *psv = (*pv1 + *(pv1 + 1) + *pv2 + *(pv2 + 1)) / 4;
879  psu++;
880  psv++;
881  pu1 += 2;
882  pu2 += 2;
883  pv1 += 2;
884  pv2 += 2;
885  }
886  }
887 
888  free(u_buffer);
889  free(v_buffer);
890 
891  return 0;
892 }
893 
894 int BGR2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
895 {
896  static int init_done = 0;
897 
898  long i, j, size;
899  unsigned char *r, *g, *b;
900  unsigned char *y, *u, *v;
901  unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
902  unsigned char *y_buffer, *u_buffer, *v_buffer;
903  unsigned char *sub_u_buf, *sub_v_buf;
904 
905  if (init_done == 0)
906  {
907  InitLookupTable();
908  init_done = 1;
909  }
910 
911  /* check to see if x_dim and y_dim are divisible by 2*/
912  if ((x_dim % 2) || (y_dim % 2))
913  return 1;
914  size = x_dim * y_dim;
915 
916  /* allocate memory*/
917  y_buffer = (unsigned char *)y_out;
918  sub_u_buf = (unsigned char *)u_out;
919  sub_v_buf = (unsigned char *)v_out;
920  u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
921  v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
922  if (!(u_buffer && v_buffer))
923  {
924  if (u_buffer)
925  free(u_buffer);
926  if (v_buffer)
927  free(v_buffer);
928  return 2;
929  }
930 
931  r = (unsigned char *)bmp;
932  y = y_buffer;
933  u = u_buffer;
934  v = v_buffer;
935 
936  /* convert RGB to YUV*/
937  if (!flip)
938  {
939  for (j = 0; j < y_dim; j++)
940  {
941  y = y_buffer + (y_dim - j - 1) * x_dim;
942  u = u_buffer + (y_dim - j - 1) * x_dim;
943  v = v_buffer + (y_dim - j - 1) * x_dim;
944 
945  for (i = 0; i < x_dim; i++)
946  {
947  g = r + 1;
948  b = r + 2;
949  *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
950  *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
951  *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
952  r += 3;
953  y++;
954  u++;
955  v++;
956  }
957  }
958  }
959  else
960  {
961  for (i = 0; i < size; i++)
962  {
963  g = r + 1;
964  b = r + 2;
965  *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
966  *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
967  *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
968  r += 3;
969  y++;
970  u++;
971  v++;
972  }
973  }
974 
975  /* subsample UV*/
976  for (j = 0; j < y_dim / 2; j++)
977  {
978  psu = sub_u_buf + j * x_dim / 2;
979  psv = sub_v_buf + j * x_dim / 2;
980  pu1 = u_buffer + 2 * j * x_dim;
981  pu2 = u_buffer + (2 * j + 1) * x_dim;
982  pv1 = v_buffer + 2 * j * x_dim;
983  pv2 = v_buffer + (2 * j + 1) * x_dim;
984  for (i = 0; i < x_dim / 2; i++)
985  {
986  *psu = (*pu1 + *(pu1 + 1) + *pu2 + *(pu2 + 1)) / 4;
987  *psv = (*pv1 + *(pv1 + 1) + *pv2 + *(pv2 + 1)) / 4;
988  psu++;
989  psv++;
990  pu1 += 2;
991  pu2 += 2;
992  pv1 += 2;
993  pv2 += 2;
994  }
995  }
996 
997  free(u_buffer);
998  free(v_buffer);
999 
1000  return 0;
1001 }
1002 
1004 {
1005  int i;
1006 
1007  for (i = 0; i < 256; i++)
1008  RGBYUV02990[i] = (float)0.2990 * i;
1009  for (i = 0; i < 256; i++)
1010  RGBYUV05870[i] = (float)0.5870 * i;
1011  for (i = 0; i < 256; i++)
1012  RGBYUV01140[i] = (float)0.1140 * i;
1013  for (i = 0; i < 256; i++)
1014  RGBYUV01684[i] = (float)0.1684 * i;
1015  for (i = 0; i < 256; i++)
1016  RGBYUV03316[i] = (float)0.3316 * i;
1017  for (i = 0; i < 256; i++)
1018  RGBYUV04187[i] = (float)0.4187 * i;
1019  for (i = 0; i < 256; i++)
1020  RGBYUV00813[i] = (float)0.0813 * i;
1021 }
1022 
1023 /* RGB/BGR to RGB/BGR */
1024 
1025 #define RGBBGR_BODY24(TIN, TOUT) \
1026  void ccvt_##TIN##_##TOUT(int width, int height, const void *const src, void *dst) \
1027  { \
1028  const PIXTYPE_##TIN *in = src; \
1029  PIXTYPE_##TOUT *out = dst; \
1030  int l, c, stride = 0; \
1031  \
1032  stride = width; \
1033  out += ((height - 1) * width); \
1034  stride *= 2; \
1035  for (l = 0; l < height; l++) \
1036  { \
1037  for (c = 0; c < width; c++) \
1038  { \
1039  out->r = in->r; \
1040  out->g = in->g; \
1041  out->b = in->b; \
1042  in++; \
1043  out++; \
1044  } \
1045  out -= stride; \
1046  } \
1047  }
1048 
1049 #define RGBBGR_BODY32(TIN, TOUT) \
1050  void ccvt_##TIN##_##TOUT(int width, int height, const void *const src, void *dst) \
1051  { \
1052  const PIXTYPE_##TIN *in = src; \
1053  PIXTYPE_##TOUT *out = dst; \
1054  int l, c, stride = 0; \
1055  \
1056  stride = width; \
1057  out += ((height - 1) * width); \
1058  stride *= 2; \
1059  for (l = 0; l < height; l++) \
1060  { \
1061  for (c = 0; c < width; c++) \
1062  { \
1063  out->r = in->r; \
1064  out->g = in->g; \
1065  out->b = in->b; \
1066  out->z = 0; \
1067  in++; \
1068  out++; \
1069  } \
1070  out -= stride; \
1071  } \
1072  }
1073 
1074 RGBBGR_BODY32(bgr24, bgr32)
1075 RGBBGR_BODY32(bgr24, rgb32)
1076 RGBBGR_BODY32(rgb24, bgr32)
1077 RGBBGR_BODY32(rgb24, rgb32)
1078 
1079 RGBBGR_BODY24(bgr32, bgr24)
1080 RGBBGR_BODY24(bgr32, rgb24)
1081 RGBBGR_BODY24(rgb32, bgr24)
1082 RGBBGR_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:894
void InitLookupTable(void)
Definition: ccvt_misc.c:1003
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:1025
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:721
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:1049
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:785
#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