moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / indi / webcam / ccvt_misc.c
blob5b9ca9920ef5139ef61c790dc5ed9b012d377b1c
1 /* CCVT: ColourConVerT: simple library for converting colourspaces
2 Copyright (C) 2002 Nemosoft Unv.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 For questions, remarks, patches, etc. for this program, the author can be
19 reached at nemosoft@smcc.demon.nl.
22 /* This file contains CCVT functions that aren't available in assembly yet
23 (or are not worth programming)
26 /*
27 * $Log$
28 * Revision 1.2 2005/04/29 16:51:20 mutlaqja
29 * 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 * CCMAIL: kstars-devel@kde.org
33 * Revision 1.1 2004/06/26 23:12:03 mutlaqja
34 * 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 * Anyone who has problems compiling this, please report the problem to kstars-devel@kde.org
38 * 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 * CCMAIL: kstars-devel@kde.org
42 * Revision 1.7 2003/01/02 04:10:19 nemosoft
43 * Adding ''upside down" conversion to rgb/bgr routines
45 * Revision 1.6 2002/12/03 23:29:11 nemosoft
46 * *** empty log message ***
48 * Revision 1.5 2002/12/03 23:27:41 nemosoft
49 * fixing log messages (gcc 3.2 complaining)
51 Revision 1.4 2002/12/03 22:29:07 nemosoft
52 Fixing up FTP stuff and some video
54 Revision 1.3 2002/11/03 22:46:25 nemosoft
55 Adding various RGB to RGB functions.
56 Adding proper copyright header too.
60 #include "ccvt.h"
61 #include "ccvt_types.h"
62 #include <stdlib.h>
64 static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
65 static float RGBYUV01684[256], RGBYUV03316[256];
66 static float RGBYUV04187[256], RGBYUV00813[256];
68 void InitLookupTable(void);
71 /* YUYV: two Y's and one U/V */
72 void ccvt_yuyv_rgb32(int width, int height, const void *src, void *dst)
74 width=width; height=height; src=src; dst=dst;
79 void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst)
81 const unsigned char *s;
82 PIXTYPE_bgr32 *d;
83 int l, c;
84 int r, g, b, cr, cg, cb, y1, y2;
86 l = height;
87 s = src;
88 d = dst;
89 while (l--) {
90 c = width >> 2;
91 while (c--) {
92 y1 = *s++;
93 cb = ((*s - 128) * 454) >> 8;
94 cg = (*s++ - 128) * 88;
95 y2 = *s++;
96 cr = ((*s - 128) * 359) >> 8;
97 cg = (cg + (*s++ - 128) * 183) >> 8;
99 r = y1 + cr;
100 b = y1 + cb;
101 g = y1 - cg;
102 SAT(r);
103 SAT(g);
104 SAT(b);
105 d->b = b;
106 d->g = g;
107 d->r = r;
108 d++;
109 r = y2 + cr;
110 b = y2 + cb;
111 g = y2 - cg;
112 SAT(r);
113 SAT(g);
114 SAT(b);
115 d->b = b;
116 d->g = g;
117 d->r = r;
118 d++;
124 void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv)
126 int n, l, j;
127 const unsigned char *s1, *s2;
128 unsigned char *dy, *du, *dv;
130 dy = (unsigned char *)dsty;
131 du = (unsigned char *)dstu;
132 dv = (unsigned char *)dstv;
133 s1 = (unsigned char *)src;
134 s2 = s1; /* keep pointer */
135 n = width * height;
136 for (; n > 0; n--) {
137 *dy = *s1;
138 dy++;
139 s1 += 2;
142 /* Two options here: average U/V values, or skip every second row */
143 s1 = s2; /* restore pointer */
144 s1++; /* point to U */
145 for (l = 0; l < height; l += 2) {
146 s2 = s1 + width * 2; /* odd line */
147 for (j = 0; j < width; j += 2) {
148 *du = (*s1 + *s2) / 2;
149 du++;
150 s1 += 2;
151 s2 += 2;
152 *dv = (*s1 + *s2) / 2;
153 dv++;
154 s1 += 2;
155 s2 += 2;
157 s1 = s2;
161 void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
163 long int i;
164 unsigned char *rawpt, *scanpt;
165 long int size;
167 rawpt = src;
168 scanpt = dst;
169 size = WIDTH*HEIGHT;
171 for ( i = 0; i < size; i++ ) {
172 if ( (i/WIDTH) % 2 == 0 ) {
173 if ( (i % 2) == 0 ) {
174 /* B */
175 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
176 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
177 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
178 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
179 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
180 *scanpt++ = *rawpt; /* B */
181 } else {
182 /* first line or left column */
183 *scanpt++ = *(rawpt+WIDTH+1); /* R */
184 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
185 *scanpt++ = *rawpt; /* B */
187 } else {
188 /* (B)G */
189 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
190 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
191 *scanpt++ = *rawpt; /* G */
192 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
193 } else {
194 /* first line or right column */
195 *scanpt++ = *(rawpt+WIDTH); /* R */
196 *scanpt++ = *rawpt; /* G */
197 *scanpt++ = *(rawpt-1); /* B */
200 } else {
201 if ( (i % 2) == 0 ) {
202 /* G(R) */
203 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
204 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
205 *scanpt++ = *rawpt; /* G */
206 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
207 } else {
208 /* bottom line or left column */
209 *scanpt++ = *(rawpt+1); /* R */
210 *scanpt++ = *rawpt; /* G */
211 *scanpt++ = *(rawpt-WIDTH); /* B */
213 } else {
214 /* R */
215 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
216 *scanpt++ = *rawpt; /* R */
217 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
218 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
219 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
220 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
221 } else {
222 /* bottom line or right column */
223 *scanpt++ = *rawpt; /* R */
224 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
225 *scanpt++ = *(rawpt-WIDTH-1); /* B */
229 rawpt++;
234 /************************************************************************
236 * int RGB2YUV (int x_dim, int y_dim, void *bmp, YUV *yuv)
238 * Purpose : It takes a 24-bit RGB bitmap and convert it into
239 * YUV (4:2:0) format
241 * Input : x_dim the x dimension of the bitmap
242 * y_dim the y dimension of the bitmap
243 * bmp pointer to the buffer of the bitmap
244 * yuv pointer to the YUV structure
246 * Output : 0 OK
247 * 1 wrong dimension
248 * 2 memory allocation error
250 * Side Effect :
251 * None
253 * Date : 09/28/2000
255 * Contacts:
257 * Adam Li
259 * DivX Advance Research Center <darc@projectmayo.com>
261 ************************************************************************/
263 int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
265 static int init_done = 0;
267 long i, j, size;
268 unsigned char *r, *g, *b;
269 unsigned char *y, *u, *v;
270 unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
271 unsigned char *y_buffer, *u_buffer, *v_buffer;
272 unsigned char *sub_u_buf, *sub_v_buf;
274 if (init_done == 0)
276 InitLookupTable();
277 init_done = 1;
280 /* check to see if x_dim and y_dim are divisible by 2*/
281 if ((x_dim % 2) || (y_dim % 2)) return 1;
282 size = x_dim * y_dim;
284 /* allocate memory*/
285 y_buffer = (unsigned char *)y_out;
286 sub_u_buf = (unsigned char *)u_out;
287 sub_v_buf = (unsigned char *)v_out;
288 u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
289 v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
290 if (!(u_buffer && v_buffer))
292 if (u_buffer) free(u_buffer);
293 if (v_buffer) free(v_buffer);
294 return 2;
297 b = (unsigned char *)bmp;
298 y = y_buffer;
299 u = u_buffer;
300 v = v_buffer;
302 /* convert RGB to YUV*/
303 if (!flip) {
304 for (j = 0; j < y_dim; j ++)
306 y = y_buffer + (y_dim - j - 1) * x_dim;
307 u = u_buffer + (y_dim - j - 1) * x_dim;
308 v = v_buffer + (y_dim - j - 1) * x_dim;
310 for (i = 0; i < x_dim; i ++) {
311 g = b + 1;
312 r = b + 2;
313 *y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
314 *u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128);
315 *v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
316 b += 3;
317 y ++;
318 u ++;
319 v ++;
322 } else {
323 for (i = 0; i < size; i++)
325 g = b + 1;
326 r = b + 2;
327 *y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
328 *u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128);
329 *v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
330 b += 3;
331 y ++;
332 u ++;
333 v ++;
337 /* subsample UV*/
338 for (j = 0; j < y_dim/2; j ++)
340 psu = sub_u_buf + j * x_dim / 2;
341 psv = sub_v_buf + j * x_dim / 2;
342 pu1 = u_buffer + 2 * j * x_dim;
343 pu2 = u_buffer + (2 * j + 1) * x_dim;
344 pv1 = v_buffer + 2 * j * x_dim;
345 pv2 = v_buffer + (2 * j + 1) * x_dim;
346 for (i = 0; i < x_dim/2; i ++)
348 *psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;
349 *psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;
350 psu ++;
351 psv ++;
352 pu1 += 2;
353 pu2 += 2;
354 pv1 += 2;
355 pv2 += 2;
359 free(u_buffer);
360 free(v_buffer);
362 return 0;
366 void InitLookupTable()
368 int i;
370 for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
371 for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
372 for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
373 for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
374 for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
375 for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
376 for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
380 /* RGB/BGR to RGB/BGR */
382 #define RGBBGR_BODY24(TIN, TOUT) \
383 void ccvt_ ## TIN ## _ ## TOUT (int width, int height, const void *const src, void *const dst) \
385 const PIXTYPE_ ## TIN *in = src; \
386 PIXTYPE_ ## TOUT *out = dst; \
387 int l, c, stride = 0; \
389 if (height < 0) { stride = width; height = -height; } \
390 out += ((height - 1) * width); \
391 stride *= 2; \
392 for (l = 0; l < height; l++) { \
393 for (c = 0; c < width; c++) { \
394 out->r = in->r; \
395 out->g = in->g; \
396 out->b = in->b; \
397 in++; \
398 out++; \
400 out -= stride; \
404 #define RGBBGR_BODY32(TIN, TOUT) \
405 void ccvt_ ## TIN ## _ ## TOUT (int width, int height, const void *const src, void *const dst) \
407 const PIXTYPE_ ## TIN *in = src; \
408 PIXTYPE_ ## TOUT *out = dst; \
409 int l, c, stride = 0; \
411 if (height < 0) { stride = width; height = -height; } \
412 out += ((height - 1) * width); \
413 stride *= 2; \
414 for (l = 0; l < height; l++) { \
415 for (c = 0; c < width; c++) { \
416 out->r = in->r; \
417 out->g = in->g; \
418 out->b = in->b; \
419 out->z = 0; \
420 in++; \
421 out++; \
423 out -= stride; \
427 RGBBGR_BODY32(bgr24, bgr32)
428 RGBBGR_BODY32(bgr24, rgb32)
429 RGBBGR_BODY32(rgb24, bgr32)
430 RGBBGR_BODY32(rgb24, rgb32)
432 RGBBGR_BODY24(bgr32, bgr24)
433 RGBBGR_BODY24(bgr32, rgb24)
434 RGBBGR_BODY24(rgb32, bgr24)
435 RGBBGR_BODY24(rgb32, rgb24)