Instrument Neutral Distributed Interface INDI  1.9.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.
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 i;
558  long int row;
559  long int col;
560  long int width=WIDTH;
561  int RED = 0;
562  int GREEN = 1;
563  int BLUE = 2;
564  for (row = 0; row < HEIGHT; row++) {
565  for (col = 0; col < WIDTH; col++) {
566  i=(row*WIDTH+col)*3; //Output is in 3 bytes RGB, so convert a single pixel (3 bytes) each time. (USE RED, GREEN, BLUE as offsets 0, 1, 2 respectively)
567  //General case:
568  if(row % 2 == 0) { //GRGRGR Row
569  if(col % 2 == 0) {//Over Green
570  //TODO: Double check 1st/last row
571  if (col != 0 && col != WIDTH -1) { // NORMAL
572  dst[(row*width+col)*3+RED]=(src[row*width+col+1]+src[row*width+col-1])/2; // Reds are to L/R
573  } else { //EDGE
574  if (col == 0) { dst[(row*width+col)*3+RED]=src[row*width+col+1];}
575  if (col == WIDTH -1 ) { dst[(row*width+col)*3+RED]=src[row*width+col-1]; }
576  }
577  dst[(row*width+col)*3+GREEN]=src[row*width+col];
578  if (row !=0 && row !=HEIGHT-1) { // NORMAL
579  dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col]+src[(row-1)*width+col])/2; //Blues are above and below.
580  } else { // EDGE
581  if (row == 0) {dst[(row*width+col)*3+BLUE]=src[(row+1)*width+col];}
582  if (row == WIDTH -1) {dst[(row*width+col)*3+BLUE]=src[(row-1)*width+col];}
583  }
584  } else { // Over RED
585  dst[(row*width+col)*3+RED]=src[row*width+col];
586  if (col != WIDTH -1 && row !=0 ) { // NORMAL (Left side and bottom count as normal
587  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
588  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.
589  } else { // EDGE
590  if (col != WIDTH -1 && row == 0) {
591  //Corner && Side:
592  //
593  //,G*G.
594  //,BGB.
595  //,....
596  dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row)*width+col+1]+src[(row)*width+col+1])/3;
597  dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col+1]+src[(row+1)*width+col-1])/2;
598  }
599 
600  if (col == WIDTH -1 && row !=0 ) {
601  //Side
602  //...
603  //.BG
604  //.GR
605  //.BG
606  //...
607  dst[(row*width+col)*3+GREEN]=(src[(row+1)*width+col]+src[(row-1)*width+col]+src[(row)*width+col-1])/3;
608  dst[(row*width+col)*3+BLUE]=(src[(row+1)*width+col-1]+src[(row-1)*width+col-1])/2;
609 
610  }
611  if (col == WIDTH -1 && row ==0) {
612  //Corner (col=max, row=0)
613  //
614  //.G*
615  //.BG
616  //...
617  dst[(row*width+col)*3+GREEN]=(src[(row-1)*width+col]+src[(row+0)*width+col-1]+src[(row+1)*width+col])/3;
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 
723 int 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 <darc@projectmayo.com>
784  *
785  ************************************************************************/
786 
787 int 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  {
800  InitLookupTable();
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 
896 int 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  {
909  InitLookupTable();
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 
1076 RGBBGR_BODY32(bgr24, bgr32)
1077 RGBBGR_BODY32(bgr24, rgb32)
1078 RGBBGR_BODY32(rgb24, bgr32)
1079 RGBBGR_BODY32(rgb24, rgb32)
1080 
1081 RGBBGR_BODY24(bgr32, bgr24)
1082 RGBBGR_BODY24(bgr32, rgb24)
1083 RGBBGR_BODY24(rgb32, bgr24)
1084 RGBBGR_BODY24(rgb32, rgb24)
RGBBGR_BODY32
#define RGBBGR_BODY32(TIN, TOUT)
Definition: ccvt_misc.c:1051
bayer16_2_rgb24
void bayer16_2_rgb24(unsigned short *dst, unsigned short *src, long int WIDTH, long int HEIGHT)
Definition: ccvt_misc.c:357
PIXTYPE_rgb24::b
unsigned char b
Definition: ccvt_types.h:52
PIXTYPE_rgb24::r
unsigned char r
Definition: ccvt_types.h:50
PIXTYPE_bgr32::r
unsigned char r
Definition: ccvt_types.h:29
mjpegtoyuv420p
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
bayer_rggb_2rgb24
void bayer_rggb_2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
Definition: ccvt_misc.c:451
InitLookupTable
void InitLookupTable(void)
Definition: ccvt_misc.c:1005
ccvt_yuyv_bgr24
void ccvt_yuyv_bgr24(int width, int height, const void *src, void *dst)
Definition: ccvt_misc.c:127
ccvt_yuyv_420p
void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv)
Definition: ccvt_misc.c:219
PIXTYPE_rgb24
Definition: ccvt_types.h:48
decode_jpeg_raw
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
PIXTYPE_bgr24::r
unsigned char r
Definition: ccvt_types.h:37
SAT
#define SAT(c)
Definition: ccvt_types.h:55
RGBBGR_BODY24
#define RGBBGR_BODY24(TIN, TOUT)
Definition: ccvt_misc.c:1027
bayer2rgb24
void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
Definition: ccvt_misc.c:263
PIXTYPE_bgr32::g
unsigned char g
Definition: ccvt_types.h:28
PIXTYPE_bgr32::b
unsigned char b
Definition: ccvt_types.h:27
jpegutils.h
PIXTYPE_bgr32
Definition: ccvt_types.h:25
bayer_grbg_to_rgb24
void bayer_grbg_to_rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
Definition: ccvt_misc.c:545
RGB2YUV
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
ccvt_yuyv_rgb24
void ccvt_yuyv_rgb24(int width, int height, const void *src, void *dst)
Definition: ccvt_misc.c:173
ccvt_yuyv_bgr32
void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst)
Definition: ccvt_misc.c:81
PIXTYPE_bgr24
Definition: ccvt_types.h:33
BGR2YUV
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
PIXTYPE_bgr24::b
unsigned char b
Definition: ccvt_types.h:35
PIXTYPE_bgr24::g
unsigned char g
Definition: ccvt_types.h:36
PIXTYPE_rgb24::g
unsigned char g
Definition: ccvt_types.h:51
ccvt.h
ccvt_types.h