1 /*
2   pygame - Python Game Library
3 
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Library General Public
6   License as published by the Free Software Foundation; either
7   version 2 of the License, or (at your option) any later version.
8 
9   This library 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 GNU
12   Library General Public License for more details.
13 
14   You should have received a copy of the GNU Library General Public
15   License along with this library; if not, write to the Free
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 
18 */
19 
20 /*
21  * Camera - webcam support for pygame
22  * Author: Nirav Patel
23  *
24  * This module allows for use of v4l2 webcams in pygame.  The code is written
25  * such that adding support for vfw cameras should be possible without
26  * much modification of existing functions.  v4l2 functions are kept seperate
27  * from functions available to pygame users and generic functions like
28  * colorspace conversion.
29  *
30  * There is currently support for cameras that support MMAP and use
31  * pixelformats of RGB24, RGB444, YUYV, SBGGR8, and YUV420.  To add support for
32  * additional pixelformats, add them to v4l2_init_device and
33  * v4l2_process_image, and add functions to convert the format to packed RGB,
34  * YUV, and HSV.
35  */
36 
37 #include "camera.h"
38 #include "pgcompat.h"
39 
40 /*
41 #if defined(__unix__) || !defined(__APPLE__)
42 #else
43     #define V4L2_PIX_FMT_RGB24 1
44     #define V4L2_PIX_FMT_RGB444 1
45 #endif
46 */
47 
48 /* functions available to pygame users */
49 PyObject *
50 surf_colorspace(PyObject *self, PyObject *arg);
51 PyObject *
52 list_cameras(PyObject *self, PyObject *arg);
53 PyObject *
54 camera_start(pgCameraObject *self, PyObject *args);
55 PyObject *
56 camera_stop(pgCameraObject *self, PyObject *args);
57 PyObject *
58 camera_get_controls(pgCameraObject *self, PyObject *args);
59 PyObject *
60 camera_set_controls(pgCameraObject *self, PyObject *arg, PyObject *kwds);
61 PyObject *
62 camera_get_size(pgCameraObject *self, PyObject *args);
63 PyObject *
64 camera_query_image(pgCameraObject *self, PyObject *args);
65 PyObject *
66 camera_get_image(pgCameraObject *self, PyObject *arg);
67 PyObject *
68 camera_get_raw(pgCameraObject *self, PyObject *args);
69 
70 /*
71  * Functions available to pygame users.  The idea is to make these as simple as
72  * possible, and merely have them call functions specific to the type of
73  * camera being used to do all the real work.  It currently just calls v4l2_*
74  * functions, but it could check something like self->cameratype and depending
75  * on the result, call v4l, v4l2, vfw, or other functions.
76  */
77 
78 /* colorspace() - Surface colorspace conversion */
79 PyObject *
surf_colorspace(PyObject * self,PyObject * arg)80 surf_colorspace(PyObject *self, PyObject *arg)
81 {
82     pgSurfaceObject *surfobj, *surfobj2;
83     SDL_Surface *surf, *newsurf;
84     char *color;
85     int cspace;
86     surfobj2 = NULL;
87 
88     /*get all the arguments*/
89     if (!PyArg_ParseTuple(arg, "O!s|O!", &pgSurface_Type, &surfobj, &color,
90                           &pgSurface_Type, &surfobj2))
91         return NULL;
92 
93     if (!strcmp(color, "YUV")) {
94         cspace = YUV_OUT;
95     }
96     else if (!strcmp(color, "HSV")) {
97         cspace = HSV_OUT;
98     }
99     else {
100         return RAISE(PyExc_ValueError, "Incorrect colorspace value");
101     }
102 
103     surf = pgSurface_AsSurface(surfobj);
104 
105     if (!surfobj2) {
106         newsurf = SDL_CreateRGBSurface(
107             0, surf->w, surf->h, surf->format->BitsPerPixel,
108             surf->format->Rmask, surf->format->Gmask, surf->format->Bmask,
109             surf->format->Amask);
110         if (!newsurf) {
111             return NULL;
112         }
113     }
114     else {
115         newsurf = pgSurface_AsSurface(surfobj2);
116     }
117 
118     /* check to see if the size is the same. */
119     if (newsurf->w != surf->w || newsurf->h != surf->h)
120         return RAISE(PyExc_ValueError,
121                      "Surfaces not the same width and height.");
122 
123     /* check to see if the format of the surface is the same. */
124     if (surf->format->BitsPerPixel != newsurf->format->BitsPerPixel)
125         return RAISE(PyExc_ValueError, "Surfaces not the same depth");
126 
127     SDL_LockSurface(newsurf);
128     pgSurface_Lock(surfobj);
129 
130     Py_BEGIN_ALLOW_THREADS;
131     colorspace(surf, newsurf, cspace);
132     Py_END_ALLOW_THREADS;
133 
134     pgSurface_Unlock(surfobj);
135     SDL_UnlockSurface(newsurf);
136 
137     if (surfobj2) {
138         Py_INCREF(surfobj2);
139         return (PyObject *)surfobj2;
140     }
141     else
142         return (PyObject *)pgSurface_New(newsurf);
143 }
144 
145 /* list_cameras() - lists cameras available on the computer */
146 PyObject *
list_cameras(PyObject * self,PyObject * arg)147 list_cameras(PyObject *self, PyObject *arg)
148 {
149 #if defined(__unix__) || defined(PYGAME_WINDOWS_CAMERA)
150     PyObject *ret_list;
151     PyObject *string;
152 #if !defined(PYGAME_WINDOWS_CAMERA)
153     char **devices;
154 #else
155     WCHAR **devices;
156 #endif
157     int num_devices, i;
158 
159     num_devices = 0;
160     ret_list = NULL;
161     ret_list = PyList_New(0);
162     if (!ret_list)
163         return NULL;
164 
165 #if defined(__unix__)
166     devices = v4l2_list_cameras(&num_devices);
167 #elif defined(PYGAME_WINDOWS_CAMERA)
168     devices = windows_list_cameras(&num_devices);
169 #endif
170     for (i = 0; i < num_devices; i++) {
171 #if defined(PYGAME_WINDOWS_CAMERA)
172         string = PyUnicode_FromWideChar(devices[i], -1);
173 #else
174         string = Text_FromUTF8(devices[i]);
175 #endif
176         if (0 != PyList_Append(ret_list, string)) {
177             /* Append failed; clean up and return */
178             Py_DECREF(ret_list);
179             Py_DECREF(string);
180             for (; i < num_devices; i++) {
181                 free(devices[i]);
182             }
183             free(devices);
184             return NULL; /* Exception already set. */
185         }
186         Py_DECREF(string);
187         free(devices[i]);
188     }
189     free(devices);
190 
191     return ret_list;
192 #else
193     Py_RETURN_NONE;
194 #endif
195 }
196 
197 /* start() - opens, inits, and starts capturing on the camera */
198 PyObject *
camera_start(pgCameraObject * self,PyObject * args)199 camera_start(pgCameraObject *self, PyObject *args)
200 {
201 #if defined(__unix__)
202     if (v4l2_open_device(self) == 0) {
203         v4l2_close_device(self);
204         return NULL;
205     }
206     else {
207         self->camera_type = CAM_V4L2;
208         if (v4l2_init_device(self) == 0) {
209             v4l2_close_device(self);
210             return NULL;
211         }
212         if (v4l2_start_capturing(self) == 0) {
213             v4l2_close_device(self);
214             return NULL;
215         }
216     }
217 #elif defined(PYGAME_WINDOWS_CAMERA)
218     if (self->open) { /* camera already started */
219         Py_RETURN_NONE;
220     }
221 
222     if (!windows_open_device(self)) {
223         windows_close_device(self);
224         return NULL;
225     }
226 #endif
227     Py_RETURN_NONE;
228 }
229 
230 /* stop() - stops capturing, uninits, and closes the camera */
231 PyObject *
camera_stop(pgCameraObject * self,PyObject * args)232 camera_stop(pgCameraObject *self, PyObject *args)
233 {
234 #if defined(__unix__)
235     if (v4l2_stop_capturing(self) == 0)
236         return NULL;
237     if (v4l2_uninit_device(self) == 0)
238         return NULL;
239     if (v4l2_close_device(self) == 0)
240         return NULL;
241 #elif defined(PYGAME_WINDOWS_CAMERA)
242     if (self->open) { /* camera started */
243         if (!windows_close_device(self))
244             return NULL;
245     }
246 #endif
247     Py_RETURN_NONE;
248 }
249 
250 /* get_controls() - gets current values of user controls */
251 /* TODO: Support brightness, contrast, and other common controls */
252 PyObject *
camera_get_controls(pgCameraObject * self,PyObject * args)253 camera_get_controls(pgCameraObject *self, PyObject *args)
254 {
255 #if defined(__unix__)
256     int value;
257     if (v4l2_get_control(self->fd, V4L2_CID_HFLIP, &value))
258         self->hflip = value;
259 
260     if (v4l2_get_control(self->fd, V4L2_CID_VFLIP, &value))
261         self->vflip = value;
262 
263     if (v4l2_get_control(self->fd, V4L2_CID_BRIGHTNESS, &value))
264         self->brightness = value;
265 
266     return Py_BuildValue("(NNN)", PyBool_FromLong(self->hflip),
267                          PyBool_FromLong(self->vflip),
268                          PyInt_FromLong(self->brightness));
269 #elif defined(PYGAME_WINDOWS_CAMERA)
270     return Py_BuildValue("(NNN)", PyBool_FromLong(self->hflip),
271                          PyBool_FromLong(self->vflip), PyInt_FromLong(-1));
272 #endif
273     Py_RETURN_NONE;
274 }
275 
276 /* set_controls() - changes camera settings if supported by the camera */
277 PyObject *
camera_set_controls(pgCameraObject * self,PyObject * arg,PyObject * kwds)278 camera_set_controls(pgCameraObject *self, PyObject *arg, PyObject *kwds)
279 {
280 #if defined(__unix__)
281     int hflip = 0, vflip = 0, brightness = 0;
282     char *kwids[] = {"hflip", "vflip", "brightness", NULL};
283 
284     camera_get_controls(self, NULL);
285     hflip = self->hflip;
286     vflip = self->vflip;
287     brightness = self->brightness;
288 
289     if (!PyArg_ParseTupleAndKeywords(arg, kwds, "|iii", kwids, &hflip, &vflip,
290                                      &brightness))
291         return NULL;
292 
293     /* #if defined(__unix__)         */
294     if (v4l2_set_control(self->fd, V4L2_CID_HFLIP, hflip))
295         self->hflip = hflip;
296 
297     if (v4l2_set_control(self->fd, V4L2_CID_VFLIP, vflip))
298         self->vflip = vflip;
299 
300     if (v4l2_set_control(self->fd, V4L2_CID_BRIGHTNESS, brightness))
301         self->brightness = brightness;
302 
303     return Py_BuildValue("(NNN)", PyBool_FromLong(self->hflip),
304                          PyBool_FromLong(self->vflip),
305                          PyInt_FromLong(self->brightness));
306 
307 #elif defined(PYGAME_WINDOWS_CAMERA)
308     int hflip = 0, vflip = 0, brightness = 0;
309     char *kwids[] = {"hflip", "vflip", "brightness", NULL};
310 
311     hflip = self->hflip;
312     vflip = self->vflip;
313     brightness = -1;
314 
315     if (!PyArg_ParseTupleAndKeywords(arg, kwds, "|iii", kwids, &hflip, &vflip,
316                                      &brightness))
317         return NULL;
318 
319     self->hflip = hflip;
320     self->vflip = vflip;
321 
322     return Py_BuildValue("(NNN)", PyBool_FromLong(self->hflip),
323                          PyBool_FromLong(self->vflip), PyInt_FromLong(-1));
324 #endif
325     Py_RETURN_NONE;
326 }
327 
328 /* get_size() - returns the dimensions of the images being recorded */
329 PyObject *
camera_get_size(pgCameraObject * self,PyObject * args)330 camera_get_size(pgCameraObject *self, PyObject *args)
331 {
332 #if defined(__unix__) || defined(PYGAME_WINDOWS_CAMERA)
333     return Py_BuildValue("(ii)", self->width, self->height);
334 #endif
335     Py_RETURN_NONE;
336 }
337 
338 /* query_image() - checks if a frame is ready */
339 PyObject *
camera_query_image(pgCameraObject * self,PyObject * args)340 camera_query_image(pgCameraObject *self, PyObject *args)
341 {
342 #if defined(__unix__)
343     return PyBool_FromLong(v4l2_query_buffer(self));
344 #elif defined(PYGAME_WINDOWS_CAMERA)
345     int ready;
346     if (!windows_frame_ready(self, &ready))
347         return NULL;
348 
349     return PyBool_FromLong(ready);
350 #endif
351     Py_RETURN_TRUE;
352 }
353 
354 /* get_image() - returns an RGB Surface */
355 /* code to reuse Surface from René Dudfield */
356 PyObject *
camera_get_image(pgCameraObject * self,PyObject * arg)357 camera_get_image(pgCameraObject *self, PyObject *arg)
358 {
359 #if defined(__unix__)
360     SDL_Surface *surf = NULL;
361     pgSurfaceObject *surfobj = NULL;
362 
363     if (!PyArg_ParseTuple(arg, "|O!", &pgSurface_Type, &surfobj))
364         return NULL;
365 
366     if (!surfobj) {
367         surf = SDL_CreateRGBSurface(0, self->width, self->height, 24,
368                                     0xFF << 16, 0xFF << 8, 0xFF, 0);
369     }
370     else {
371         surf = pgSurface_AsSurface(surfobj);
372     }
373 
374     if (!surf)
375         return NULL;
376 
377     if (surf->w != self->width || surf->h != self->height) {
378         return RAISE(PyExc_ValueError,
379                      "Destination surface not the correct width or height.");
380     }
381 
382     Py_BEGIN_ALLOW_THREADS;
383     if (!v4l2_read_frame(self, surf))
384         return NULL;
385     Py_END_ALLOW_THREADS;
386 
387     if (!surf)
388         return NULL;
389 
390     if (surfobj) {
391         Py_INCREF(surfobj);
392         return (PyObject *)surfobj;
393     }
394     else {
395         return (PyObject *)pgSurface_New(surf);
396     }
397 #elif defined(PYGAME_WINDOWS_CAMERA)
398     SDL_Surface *surf = NULL;
399     pgSurfaceObject *surfobj = NULL;
400 
401     int width = self->width;
402     int height = self->height;
403 
404     if (!PyArg_ParseTuple(arg, "|O!", &pgSurface_Type, &surfobj))
405         return NULL;
406 
407     if (!surfobj) {
408         surf = SDL_CreateRGBSurface(0, width, height, 32,  // 24?
409                                     0xFF << 16, 0xFF << 8, 0xFF, 0);
410     }
411     else {
412         surf = pgSurface_AsSurface(surfobj);
413     }
414 
415     if (!surf)
416         return NULL;
417 
418     if (surf->w != self->width || surf->h != self->height) {
419         return RAISE(PyExc_ValueError,
420                      "Destination surface not the correct width or height.");
421     }
422 
423     if (!windows_read_frame(self, surf))
424         return NULL;
425 
426     if (!surf)
427         return NULL;
428 
429     if (surfobj) {
430         Py_INCREF(surfobj);
431         return (PyObject *)surfobj;
432     }
433     else {
434         return (PyObject *)pgSurface_New(surf);
435     }
436 
437 #endif
438     Py_RETURN_NONE;
439 }
440 
441 /* get_raw() - returns an unmodified image as a string from the buffer */
442 PyObject *
camera_get_raw(pgCameraObject * self,PyObject * args)443 camera_get_raw(pgCameraObject *self, PyObject *args)
444 {
445 #if defined(__unix__)
446     return v4l2_read_raw(self);
447 #elif defined(PYGAME_WINDOWS_CAMERA)
448     return windows_read_raw(self);
449 #endif
450     Py_RETURN_NONE;
451 }
452 
453 /*
454  * Pixelformat conversion functions
455  */
456 
457 /* converts from rgb Surface to yuv or hsv */
458 /* TODO: Allow for conversion from yuv and hsv to all */
459 void
colorspace(SDL_Surface * src,SDL_Surface * dst,int cspace)460 colorspace(SDL_Surface *src, SDL_Surface *dst, int cspace)
461 {
462     switch (cspace) {
463         case YUV_OUT:
464             rgb_to_yuv(src->pixels, dst->pixels, src->h * src->w, 0,
465                        src->format);
466             break;
467         case HSV_OUT:
468             rgb_to_hsv(src->pixels, dst->pixels, src->h * src->w, 0,
469                        src->format);
470             break;
471     }
472 }
473 
474 /* converts pretty directly if its already RGB24 */
475 void
rgb24_to_rgb(const void * src,void * dst,int length,SDL_PixelFormat * format)476 rgb24_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format)
477 {
478     Uint8 *s = (Uint8 *)src;
479     Uint8 *d8;
480     Uint16 *d16;
481     Uint32 *d32;
482     Uint8 r, g, b;
483     int rshift, gshift, bshift, rloss, gloss, bloss;
484 
485     rshift = format->Rshift;
486     gshift = format->Gshift;
487     bshift = format->Bshift;
488     rloss = format->Rloss;
489     gloss = format->Gloss;
490     bloss = format->Bloss;
491 
492     switch (format->BytesPerPixel) {
493         case 1:
494             d8 = (Uint8 *)dst;
495             while (length--) {
496                 r = *s++;
497                 g = *s++;
498                 b = *s++;
499                 *d8++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
500                         ((b >> bloss) << bshift);
501             }
502             break;
503         case 2:
504             d16 = (Uint16 *)dst;
505             while (length--) {
506                 r = *s++;
507                 g = *s++;
508                 b = *s++;
509                 *d16++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
510                          ((b >> bloss) << bshift);
511             }
512             break;
513         case 3:
514             d8 = (Uint8 *)dst;
515             while (length--) {
516                 *d8++ = *(s + 2); /* blue */
517                 *d8++ = *(s + 1); /* green */
518                 *d8++ = *s;       /* red */
519                 s += 3;
520             }
521             break;
522         default:
523             d32 = (Uint32 *)dst;
524             while (length--) {
525                 r = *s++;
526                 g = *s++;
527                 b = *s++;
528                 *d32++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
529                          ((b >> bloss) << bshift);
530             }
531             break;
532     }
533 }
534 
535 /* slight variation on rgb24_to_rgb, just drops the 4th byte of each pixel,
536  * changes the R, G, B ordering. */
537 void
bgr32_to_rgb(const void * src,void * dst,int length,SDL_PixelFormat * format)538 bgr32_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format)
539 {
540     Uint8 *s = (Uint8 *)src;
541     Uint8 *d8;
542     Uint16 *d16;
543     Uint32 *d32;
544     Uint8 r, g, b;
545     int rshift, gshift, bshift, rloss, gloss, bloss;
546 
547     rshift = format->Rshift;
548     gshift = format->Gshift;
549     bshift = format->Bshift;
550     rloss = format->Rloss;
551     gloss = format->Gloss;
552     bloss = format->Bloss;
553 
554     switch (format->BytesPerPixel) {
555         case 1:
556             d8 = (Uint8 *)dst;
557             while (length--) {
558                 b = *s++;
559                 g = *s++;
560                 r = *s++;
561                 s++;
562                 *d8++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
563                         ((b >> bloss) << bshift);
564             }
565             break;
566         case 2:
567             d16 = (Uint16 *)dst;
568             while (length--) {
569                 b = *s++;
570                 g = *s++;
571                 r = *s++;
572                 s++;
573                 *d16++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
574                          ((b >> bloss) << bshift);
575             }
576             break;
577         case 3:
578             d8 = (Uint8 *)dst;
579             while (length--) {
580                 *d8++ = *s;       /* red */
581                 *d8++ = *(s + 1); /* green */
582                 *d8++ = *(s + 2); /* blue */
583                 s += 4;
584             }
585             break;
586         default:
587             d32 = (Uint32 *)dst;
588             while (length--) {
589                 b = *s++;
590                 g = *s++;
591                 r = *s++;
592                 *s++;
593                 *d32++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
594                          ((b >> bloss) << bshift);
595             }
596             break;
597     }
598 }
599 
600 /* converts packed rgb to packed hsv. formulas modified from wikipedia */
601 void
rgb_to_hsv(const void * src,void * dst,int length,unsigned long source,SDL_PixelFormat * format)602 rgb_to_hsv(const void *src, void *dst, int length, unsigned long source,
603            SDL_PixelFormat *format)
604 {
605     Uint8 *s8, *d8;
606     Uint16 *s16, *d16;
607     Uint32 *s32, *d32;
608     Uint8 r, g, b, p1, p2, h, s, v, max, min, delta;
609     int rshift, gshift, bshift, rloss, gloss, bloss;
610 
611     s8 = (Uint8 *)src;
612     s16 = (Uint16 *)src;
613     s32 = (Uint32 *)src;
614     d8 = (Uint8 *)dst;
615     d16 = (Uint16 *)dst;
616     d32 = (Uint32 *)dst;
617     rshift = format->Rshift;
618     gshift = format->Gshift;
619     bshift = format->Bshift;
620     rloss = format->Rloss;
621     gloss = format->Gloss;
622     bloss = format->Bloss;
623 
624     /* you could stick the if statement inside the loop, but I'm sacrificing a
625        a few hundred bytes for a little performance */
626     /* 10 yrs later... about that... */
627     if (source == V4L2_PIX_FMT_RGB444 || source == V4L2_PIX_FMT_RGB24 ||
628         source == V4L2_PIX_FMT_XBGR32) {
629         while (length--) {
630             if (source == V4L2_PIX_FMT_RGB444) {
631                 p1 = *s8++;
632                 p2 = *s8++;
633                 b = p2 << 4;
634                 g = p1 & 0xF0;
635                 r = p1 << 4;
636             }
637             else if (source == V4L2_PIX_FMT_RGB24) {
638                 r = *s8++;
639                 g = *s8++;
640                 b = *s8++;
641             }
642             else {
643                 b = *s8++;
644                 g = *s8++;
645                 r = *s8++;
646                 s8++;
647             }
648             max = MAX(MAX(r, g), b);
649             min = MIN(MIN(r, g), b);
650             delta = max - min;
651             v = max;      /* value (similar to luminosity) */
652             if (!delta) { /* grey, zero hue and saturation */
653                 s = 0;
654                 h = 0;
655             }
656             else {
657                 s = 255 * delta / max; /* saturation */
658                 if (r == max) {        /* set hue based on max color */
659                     h = 43 * (g - b) / delta;
660                 }
661                 else if (g == max) {
662                     h = 85 + 43 * (b - r) / delta;
663                 }
664                 else {
665                     h = 170 + 43 * (r - g) / delta;
666                 }
667             }
668             switch (format->BytesPerPixel) {
669                 case 1:
670                     *d8++ = ((h >> rloss) << rshift) |
671                             ((s >> gloss) << gshift) |
672                             ((v >> bloss) << bshift);
673                     break;
674                 case 2:
675                     *d16++ = ((h >> rloss) << rshift) |
676                              ((s >> gloss) << gshift) |
677                              ((v >> bloss) << bshift);
678                     break;
679                 case 3:
680                     *d8++ = v;
681                     *d8++ = s;
682                     *d8++ = h;
683                     break;
684                 default:
685                     *d32++ = ((h >> rloss) << rshift) |
686                              ((s >> gloss) << gshift) |
687                              ((v >> bloss) << bshift);
688                     break;
689             }
690         }
691     }
692     else { /* for use as stage 2 in yuv or bayer to hsv, r and b switched */
693         while (length--) {
694             switch (format->BytesPerPixel) {
695                 case 1:
696                     r = *s8 >> rshift << rloss;
697                     g = *s8 >> gshift << gloss;
698                     b = *s8++ >> bshift << bloss;
699                     break;
700                 case 2:
701                     r = *s16 >> rshift << rloss;
702                     g = *s16 >> gshift << gloss;
703                     b = *s16++ >> bshift << bloss;
704                     break;
705                 case 3:
706                     b = *s8++;
707                     g = *s8++;
708                     r = *s8++;
709                     break;
710                 default:
711                     r = *s32 >> rshift << rloss;
712                     g = *s32 >> gshift << gloss;
713                     b = *s32++ >> bshift << bloss;
714                     break;
715             }
716             max = MAX(MAX(r, g), b);
717             min = MIN(MIN(r, g), b);
718             delta = max - min;
719             v = max;      /* value (similar to luminosity) */
720             if (!delta) { /* grey, zero hue and saturation */
721                 s = 0;
722                 h = 0;
723             }
724             else {
725                 s = 255 * delta / max; /* saturation */
726                 if (r == max) {        /* set hue based on max color */
727                     h = 43 * (g - b) / delta;
728                 }
729                 else if (g == max) {
730                     h = 85 + 43 * (b - r) / delta;
731                 }
732                 else {
733                     h = 170 + 43 * (r - g) / delta;
734                 }
735             }
736             switch (format->BytesPerPixel) {
737                 case 1:
738                     *d8++ = ((h >> rloss) << rshift) |
739                             ((s >> gloss) << gshift) |
740                             ((v >> bloss) << bshift);
741                     break;
742                 case 2:
743                     *d16++ = ((h >> rloss) << rshift) +
744                              ((s >> gloss) << gshift) +
745                              ((v >> bloss) << bshift);
746                     break;
747                 case 3:
748                     *d8++ = v;
749                     *d8++ = s;
750                     *d8++ = h;
751                     break;
752                 default:
753                     *d32++ = ((h >> rloss) << rshift) |
754                              ((s >> gloss) << gshift) |
755                              ((v >> bloss) << bshift);
756                     break;
757             }
758         }
759     }
760 }
761 
762 /* convert packed rgb to yuv. Note that unlike many implementations of YUV,
763    this has a full range of 0-255 for Y, not 16-235. Formulas from wikipedia */
764 void
rgb_to_yuv(const void * src,void * dst,int length,unsigned long source,SDL_PixelFormat * format)765 rgb_to_yuv(const void *src, void *dst, int length, unsigned long source,
766            SDL_PixelFormat *format)
767 {
768     Uint8 *s8, *d8;
769     Uint16 *s16, *d16;
770     Uint32 *s32, *d32;
771     Uint8 r, g, b, y, u, v;
772     Uint8 p1, p2;
773     int rshift, gshift, bshift, rloss, gloss, bloss;
774 
775     s8 = (Uint8 *)src;
776     s16 = (Uint16 *)src;
777     s32 = (Uint32 *)src;
778     d8 = (Uint8 *)dst;
779     d16 = (Uint16 *)dst;
780     d32 = (Uint32 *)dst;
781     rshift = format->Rshift;
782     gshift = format->Gshift;
783     bshift = format->Bshift;
784     rloss = format->Rloss;
785     gloss = format->Gloss;
786     bloss = format->Bloss;
787 
788     if (source == V4L2_PIX_FMT_RGB444 || source == V4L2_PIX_FMT_RGB24 ||
789         source == V4L2_PIX_FMT_XBGR32) {
790         while (length--) {
791             if (source == V4L2_PIX_FMT_RGB444) {
792                 p1 = *s8++;
793                 p2 = *s8++;
794                 b = p2 << 4;
795                 g = p1 & 0xF0;
796                 r = p1 << 4;
797             }
798             else if (source == V4L2_PIX_FMT_RGB24) {
799                 r = *s8++;
800                 g = *s8++;
801                 b = *s8++;
802             }
803             else {
804                 b = *s8++;
805                 g = *s8++;
806                 r = *s8++;
807                 s8++;
808             }
809 
810             v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;  /* V */
811             u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; /* U */
812             y = (77 * r + 150 * g + 29 * b + 128) >> 8;          /* Y */
813             switch (format->BytesPerPixel) {
814                 case 1:
815                     *d8++ = ((y >> rloss) << rshift) |
816                             ((u >> gloss) << gshift) |
817                             ((v >> bloss) << bshift);
818                     break;
819                 case 2:
820                     *d16++ = ((y >> rloss) << rshift) |
821                              ((u >> gloss) << gshift) |
822                              ((v >> bloss) << bshift);
823                     break;
824                 case 3:
825                     *d8++ = v;
826                     *d8++ = u;
827                     *d8++ = y;
828                     break;
829                 default:
830                     *d32++ = ((y >> rloss) << rshift) |
831                              ((u >> gloss) << gshift) |
832                              ((v >> bloss) << bshift);
833                     break;
834             }
835         }
836     }
837     else { /* for use as stage 2 in bayer to yuv, r and b switched */
838         switch (format->BytesPerPixel) {
839             case 1:
840                 while (length--) {
841                     r = *s8 >> rshift << rloss;
842                     g = *s8 >> gshift << gloss;
843                     b = *s8++ >> bshift << bloss;
844                     *d8++ =
845                         ((((77 * r + 150 * g + 29 * b + 128) >> 8) >> rloss)
846                          << rshift) |
847                         (((((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128) >>
848                           gloss)
849                          << gshift) |
850                         (((((112 * r - 94 * g - 18 * b + 128) >> 8) + 128) >>
851                           bloss)
852                          << bshift);
853                 }
854                 break;
855             case 2:
856                 while (length--) {
857                     r = *s16 >> rshift << rloss;
858                     g = *s16 >> gshift << gloss;
859                     b = *s16++ >> bshift << bloss;
860                     *d16++ =
861                         ((((77 * r + 150 * g + 29 * b + 128) >> 8) >> rloss)
862                          << rshift) |
863                         (((((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128) >>
864                           gloss)
865                          << gshift) |
866                         (((((112 * r - 94 * g - 18 * b + 128) >> 8) + 128) >>
867                           bloss)
868                          << bshift);
869                 }
870                 break;
871             case 3:
872                 while (length--) {
873                     b = *s8++;
874                     g = *s8++;
875                     r = *s8++;
876                     *d8++ = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
877                     *d8++ = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
878                     *d8++ = (77 * r + 150 * g + 29 * b + 128) >> 8;
879                 }
880                 break;
881             default:
882                 while (length--) {
883                     r = *s32 >> rshift << rloss;
884                     g = *s32 >> gshift << gloss;
885                     b = *s32++ >> bshift << bloss;
886                     *d32++ =
887                         ((((77 * r + 150 * g + 29 * b + 128) >> 8) >> rloss)
888                          << rshift) |
889                         (((((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128) >>
890                           gloss)
891                          << gshift) |
892                         (((((112 * r - 94 * g - 18 * b + 128) >> 8) + 128) >>
893                           bloss)
894                          << bshift);
895                 }
896                 break;
897         }
898     }
899 }
900 
901 /* Converts from rgb444 (R444) to rgb24 (RGB3) */
902 void
rgb444_to_rgb(const void * src,void * dst,int length,SDL_PixelFormat * format)903 rgb444_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format)
904 {
905     Uint8 *s, *d8;
906     Uint16 *d16;
907     Uint32 *d32;
908     Uint8 p1, p2, r, g, b;
909     int rshift, gshift, bshift, rloss, gloss, bloss;
910 
911     s = (Uint8 *)src;
912     rshift = format->Rshift;
913     gshift = format->Gshift;
914     bshift = format->Bshift;
915     rloss = format->Rloss;
916     gloss = format->Gloss;
917     bloss = format->Bloss;
918 
919     switch (format->BytesPerPixel) {
920         case 1:
921             d8 = (Uint8 *)dst;
922             while (length--) {
923                 r = *s << 4;
924                 g = *s++ & 0xF0;
925                 b = *s++ << 4;
926                 *d8++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
927                         ((b >> bloss) << bshift);
928             }
929             break;
930         case 2:
931             d16 = (Uint16 *)dst;
932             while (length--) {
933                 r = *s << 4;
934                 g = *s++ & 0xF0;
935                 b = *s++ << 4;
936                 *d16++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
937                          ((b >> bloss) << bshift);
938             }
939             break;
940         case 3:
941             d8 = (Uint8 *)dst;
942             while (length--) {
943                 p1 = *s++;
944                 p2 = *s++;
945                 *d8++ = p2 << 4;   /* blue */
946                 *d8++ = p1 & 0xF0; /* green */
947                 *d8++ = p1 << 4;   /* red */
948             }
949             break;
950         default:
951             d32 = (Uint32 *)dst;
952             while (length--) {
953                 r = *s << 4;
954                 g = *s++ & 0xF0;
955                 b = *s++ << 4;
956                 *d32++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
957                          ((b >> bloss) << bshift);
958             }
959             break;
960     }
961 }
962 
963 /* convert from 4:2:2 YUYV interlaced to RGB */
964 /* colorspace conversion routine from libv4l. Licensed LGPL 2.1
965    (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl> */
966 void
yuyv_to_rgb(const void * src,void * dst,int length,SDL_PixelFormat * format)967 yuyv_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format)
968 {
969     Uint8 *s, *d8;
970     Uint16 *d16;
971     Uint32 *d32;
972     int i;
973     int r1, g1, b1, r2, b2, g2;
974     int rshift, gshift, bshift, rloss, gloss, bloss, y1, y2, u, v, u1, rg, v1;
975 
976     rshift = format->Rshift;
977     gshift = format->Gshift;
978     bshift = format->Bshift;
979     rloss = format->Rloss;
980     gloss = format->Gloss;
981     bloss = format->Bloss;
982 
983     d8 = (Uint8 *)dst;
984     d16 = (Uint16 *)dst;
985     d32 = (Uint32 *)dst;
986     i = length >> 1;
987     s = (Uint8 *)src;
988 
989     /* yuyv packs 2 pixels into every 4 bytes, sharing the u and v color
990        terms between the 2, with each pixel having a unique y luminance term.
991        Thus, we will operate on 2 pixels at a time. */
992     while (i--) {
993         y1 = *s++;
994         u = *s++;
995         y2 = *s++;
996         v = *s++;
997         /* The lines from here to the switch statement are from libv4l */
998         u1 = (((u - 128) << 7) + (u - 128)) >> 6;
999         rg = (((u - 128) << 1) + (u - 128) + ((v - 128) << 2) +
1000               ((v - 128) << 1)) >>
1001              3;
1002         v1 = (((v - 128) << 1) + (v - 128)) >> 1;
1003 
1004         r1 = SAT2(y1 + v1);
1005         g1 = SAT2(y1 - rg);
1006         b1 = SAT2(y1 + u1);
1007 
1008         r2 = SAT2(y2 + v1);
1009         g2 = SAT2(y2 - rg);
1010         b2 = SAT2(y2 + u1);
1011 
1012         /* choose the right pixel packing for the destination surface depth */
1013         switch (format->BytesPerPixel) {
1014             case 1:
1015                 *d8++ = ((r1 >> rloss) << rshift) | ((g1 >> gloss) << gshift) |
1016                         ((b1 >> bloss) << bshift);
1017                 *d8++ = ((r2 >> rloss) << rshift) | ((g2 >> gloss) << gshift) |
1018                         ((b2 >> bloss) << bshift);
1019                 break;
1020             case 2:
1021                 *d16++ = ((r1 >> rloss) << rshift) |
1022                          ((g1 >> gloss) << gshift) | ((b1 >> bloss) << bshift);
1023                 *d16++ = ((r2 >> rloss) << rshift) |
1024                          ((g2 >> gloss) << gshift) | ((b2 >> bloss) << bshift);
1025                 break;
1026             case 3:
1027                 *d8++ = b1;
1028                 *d8++ = g1;
1029                 *d8++ = r1;
1030                 *d8++ = b2;
1031                 *d8++ = g2;
1032                 *d8++ = r2;
1033                 break;
1034             default:
1035                 *d32++ = ((r1 >> rloss) << rshift) |
1036                          ((g1 >> gloss) << gshift) | ((b1 >> bloss) << bshift);
1037                 *d32++ = ((r2 >> rloss) << rshift) |
1038                          ((g2 >> gloss) << gshift) | ((b2 >> bloss) << bshift);
1039                 break;
1040         }
1041     }
1042 }
1043 
1044 /* turn yuyv into packed yuv. */
1045 void
yuyv_to_yuv(const void * src,void * dst,int length,SDL_PixelFormat * format)1046 yuyv_to_yuv(const void *src, void *dst, int length, SDL_PixelFormat *format)
1047 {
1048     Uint8 *s, *d8;
1049     Uint8 y1, u, y2, v;
1050     Uint16 *d16;
1051     Uint32 *d32;
1052     int i = length >> 1;
1053     int rshift, gshift, bshift, rloss, gloss, bloss;
1054 
1055     rshift = format->Rshift;
1056     gshift = format->Gshift;
1057     bshift = format->Bshift;
1058     rloss = format->Rloss;
1059     gloss = format->Gloss;
1060     bloss = format->Bloss;
1061     s = (Uint8 *)src;
1062 
1063     switch (format->BytesPerPixel) {
1064         case 1:
1065             d8 = (Uint8 *)dst;
1066             while (i--) {
1067                 y1 = *s++;
1068                 u = *s++;
1069                 y2 = *s++;
1070                 v = *s++;
1071                 *d8++ = ((y1 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1072                         ((v >> bloss) << bshift);
1073                 *d8++ = ((y2 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1074                         ((v >> bloss) << bshift);
1075             }
1076             break;
1077         case 2:
1078             d16 = (Uint16 *)dst;
1079             while (i--) {
1080                 y1 = *s++;
1081                 u = *s++;
1082                 y2 = *s++;
1083                 v = *s++;
1084                 *d16++ = ((y1 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1085                          ((v >> bloss) << bshift);
1086                 *d16++ = ((y2 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1087                          ((v >> bloss) << bshift);
1088             }
1089             break;
1090         case 3:
1091             d8 = (Uint8 *)dst;
1092             while (i--) {
1093                 *d8++ = *(s + 3); /* v */
1094                 *d8++ = *(s + 1); /* u */
1095                 *d8++ = *s;       /* y1 */
1096                 *d8++ = *(s + 3); /* v */
1097                 *d8++ = *(s + 1); /* u */
1098                 *d8++ = *(s + 2); /* y2 */
1099                 s += 4;
1100             }
1101             break;
1102         default:
1103             d32 = (Uint32 *)dst;
1104             while (i--) {
1105                 y1 = *s++;
1106                 u = *s++;
1107                 y2 = *s++;
1108                 v = *s++;
1109                 *d32++ = ((y1 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1110                          ((v >> bloss) << bshift);
1111                 *d32++ = ((y2 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1112                          ((v >> bloss) << bshift);
1113             }
1114             break;
1115     }
1116 }
1117 
1118 /* cribbed from above, but modified for uyvy ordering */
1119 void
uyvy_to_rgb(const void * src,void * dst,int length,SDL_PixelFormat * format)1120 uyvy_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format)
1121 {
1122     Uint8 *s, *d8;
1123     Uint16 *d16;
1124     Uint32 *d32;
1125     int i;
1126     int r1, g1, b1, r2, b2, g2;
1127     int rshift, gshift, bshift, rloss, gloss, bloss, y1, y2, u, v, u1, rg, v1;
1128 
1129     rshift = format->Rshift;
1130     gshift = format->Gshift;
1131     bshift = format->Bshift;
1132     rloss = format->Rloss;
1133     gloss = format->Gloss;
1134     bloss = format->Bloss;
1135 
1136     d8 = (Uint8 *)dst;
1137     d16 = (Uint16 *)dst;
1138     d32 = (Uint32 *)dst;
1139     i = length >> 1;
1140     s = (Uint8 *)src;
1141 
1142     /* yuyv packs 2 pixels into every 4 bytes, sharing the u and v color
1143        terms between the 2, with each pixel having a unique y luminance term.
1144        Thus, we will operate on 2 pixels at a time. */
1145     while (i--) {
1146         u = *s++;
1147         y1 = *s++;
1148         v = *s++;
1149         y2 = *s++;
1150 
1151         /* The lines from here to the switch statement are from libv4l */
1152         u1 = (((u - 128) << 7) + (u - 128)) >> 6;
1153         rg = (((u - 128) << 1) + (u - 128) + ((v - 128) << 2) +
1154               ((v - 128) << 1)) >>
1155              3;
1156         v1 = (((v - 128) << 1) + (v - 128)) >> 1;
1157 
1158         r1 = SAT2(y1 + v1);
1159         g1 = SAT2(y1 - rg);
1160         b1 = SAT2(y1 + u1);
1161 
1162         r2 = SAT2(y2 + v1);
1163         g2 = SAT2(y2 - rg);
1164         b2 = SAT2(y2 + u1);
1165 
1166         /* choose the right pixel packing for the destination surface depth */
1167         switch (format->BytesPerPixel) {
1168             case 1:
1169                 *d8++ = ((r1 >> rloss) << rshift) | ((g1 >> gloss) << gshift) |
1170                         ((b1 >> bloss) << bshift);
1171                 *d8++ = ((r2 >> rloss) << rshift) | ((g2 >> gloss) << gshift) |
1172                         ((b2 >> bloss) << bshift);
1173                 break;
1174             case 2:
1175                 *d16++ = ((r1 >> rloss) << rshift) |
1176                          ((g1 >> gloss) << gshift) | ((b1 >> bloss) << bshift);
1177                 *d16++ = ((r2 >> rloss) << rshift) |
1178                          ((g2 >> gloss) << gshift) | ((b2 >> bloss) << bshift);
1179                 break;
1180             case 3:
1181                 *d8++ = b1;
1182                 *d8++ = g1;
1183                 *d8++ = r1;
1184                 *d8++ = b2;
1185                 *d8++ = g2;
1186                 *d8++ = r2;
1187                 break;
1188             default:
1189                 *d32++ = ((r1 >> rloss) << rshift) |
1190                          ((g1 >> gloss) << gshift) | ((b1 >> bloss) << bshift);
1191                 *d32++ = ((r2 >> rloss) << rshift) |
1192                          ((g2 >> gloss) << gshift) | ((b2 >> bloss) << bshift);
1193                 break;
1194         }
1195     }
1196 }
1197 /* turn uyvy into packed yuv. */
1198 void
uyvy_to_yuv(const void * src,void * dst,int length,SDL_PixelFormat * format)1199 uyvy_to_yuv(const void *src, void *dst, int length, SDL_PixelFormat *format)
1200 {
1201     Uint8 *s, *d8;
1202     Uint8 y1, u, y2, v;
1203     Uint16 *d16;
1204     Uint32 *d32;
1205     int i = length >> 1;
1206     int rshift, gshift, bshift, rloss, gloss, bloss;
1207 
1208     rshift = format->Rshift;
1209     gshift = format->Gshift;
1210     bshift = format->Bshift;
1211     rloss = format->Rloss;
1212     gloss = format->Gloss;
1213     bloss = format->Bloss;
1214     s = (Uint8 *)src;
1215 
1216     switch (format->BytesPerPixel) {
1217         case 1:
1218             d8 = (Uint8 *)dst;
1219             while (i--) {
1220                 u = *s++;
1221                 y1 = *s++;
1222                 v = *s++;
1223                 y2 = *s++;
1224                 *d8++ = ((y1 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1225                         ((v >> bloss) << bshift);
1226                 *d8++ = ((y2 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1227                         ((v >> bloss) << bshift);
1228             }
1229             break;
1230         case 2:
1231             d16 = (Uint16 *)dst;
1232             while (i--) {
1233                 u = *s++;
1234                 y1 = *s++;
1235                 v = *s++;
1236                 y2 = *s++;
1237                 *d16++ = ((y1 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1238                          ((v >> bloss) << bshift);
1239                 *d16++ = ((y2 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1240                          ((v >> bloss) << bshift);
1241             }
1242             break;
1243         case 3:
1244             d8 = (Uint8 *)dst;
1245             while (i--) {
1246                 *d8++ = *(s + 2); /* v */
1247                 *d8++ = *s;       /* u */
1248                 *d8++ = *(s + 1); /* y1 */
1249                 *d8++ = *(s + 2); /* v */
1250                 *d8++ = *s;       /* u */
1251                 *d8++ = *(s + 3); /* y2 */
1252                 s += 4;
1253             }
1254             break;
1255         default:
1256             d32 = (Uint32 *)dst;
1257             while (i--) {
1258                 y1 = *s++;
1259                 u = *s++;
1260                 y2 = *s++;
1261                 v = *s++;
1262                 *d32++ = ((y1 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1263                          ((v >> bloss) << bshift);
1264                 *d32++ = ((y2 >> rloss) << rshift) | ((u >> gloss) << gshift) |
1265                          ((v >> bloss) << bshift);
1266             }
1267             break;
1268     }
1269 }
1270 
1271 /* Converts from 8 bit Bayer (BA81) to rgb24 (RGB3), based on:
1272  * Sonix SN9C101 based webcam basic I/F routines
1273  * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
1274  *
1275  * Redistribution and use in source and binary forms, with or without
1276  * modification, are permitted provided that the following conditions
1277  * are met:
1278  * 1. Redistributions of source code must retain the above copyright
1279  *    notice, this list of conditions and the following disclaimer.
1280  * 2. Redistributions in binary form must reproduce the above copyright
1281  *    notice, this list of conditions and the following disclaimer in the
1282  *    documentation and/or other materials provided with the distribution.
1283  *
1284  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1285  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1286  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1287  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1288  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1289  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1290  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1291  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1292  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1293  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1294  * SUCH DAMAGE.
1295  */
1296 /* TODO: Certainly not the most efficient way of doing this conversion. */
1297 void
sbggr8_to_rgb(const void * src,void * dst,int width,int height,SDL_PixelFormat * format)1298 sbggr8_to_rgb(const void *src, void *dst, int width, int height,
1299               SDL_PixelFormat *format)
1300 {
1301     Uint8 *rawpt, *d8;
1302     Uint16 *d16;
1303     Uint32 *d32;
1304     Uint8 r, g, b;
1305     int rshift, gshift, bshift, rloss, gloss, bloss;
1306     int i = width * height;
1307     rawpt = (Uint8 *)src;
1308     rshift = format->Rshift;
1309     gshift = format->Gshift;
1310     bshift = format->Bshift;
1311     rloss = format->Rloss;
1312     gloss = format->Gloss;
1313     bloss = format->Bloss;
1314 
1315     d8 = (Uint8 *)dst;
1316     d16 = (Uint16 *)dst;
1317     d32 = (Uint32 *)dst;
1318 
1319     while (i--) {
1320         if ((i / width) % 2 == 0) {
1321             /* even row (BGBGBGBG)*/
1322             if ((i % 2) == 0) {
1323                 /* B */
1324                 if ((i > width) && ((i % width) > 0)) {
1325                     b = *rawpt; /* B */
1326                     g = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt + width) +
1327                          *(rawpt - width)) /
1328                         4; /* G */
1329                     r = (*(rawpt - width - 1) + *(rawpt - width + 1) +
1330                          *(rawpt + width - 1) + *(rawpt + width + 1)) /
1331                         4; /* R */
1332                 }
1333                 else {
1334                     /* first line or left column */
1335                     b = *rawpt;                                /* B */
1336                     g = (*(rawpt + 1) + *(rawpt + width)) / 2; /* G */
1337                     r = *(rawpt + width + 1);                  /* R */
1338                 }
1339             }
1340             else {
1341                 /* (B)G */
1342                 if ((i > width) && ((i % width) < (width - 1))) {
1343                     b = (*(rawpt - 1) + *(rawpt + 1)) / 2;         /* B */
1344                     g = *rawpt;                                    /* G */
1345                     r = (*(rawpt + width) + *(rawpt - width)) / 2; /* R */
1346                 }
1347                 else {
1348                     /* first line or right column */
1349                     b = *(rawpt - 1);     /* B */
1350                     g = *rawpt;           /* G */
1351                     r = *(rawpt + width); /* R */
1352                 }
1353             }
1354         }
1355         else {
1356             /* odd row (GRGRGRGR) */
1357             if ((i % 2) == 0) {
1358                 /* G(R) */
1359                 if ((i < (width * (height - 1))) && ((i % width) > 0)) {
1360                     b = (*(rawpt + width) + *(rawpt - width)) / 2; /* B */
1361                     g = *rawpt;                                    /* G */
1362                     r = (*(rawpt - 1) + *(rawpt + 1)) / 2;         /* R */
1363                 }
1364                 else {
1365                     /* bottom line or left column */
1366                     b = *(rawpt - width); /* B */
1367                     g = *rawpt;           /* G */
1368                     r = *(rawpt + 1);     /* R */
1369                 }
1370             }
1371             else {
1372                 /* R */
1373                 if (i < (width * (height - 1)) &&
1374                     ((i % width) < (width - 1))) {
1375                     b = (*(rawpt - width - 1) + *(rawpt - width + 1) +
1376                          *(rawpt + width - 1) + *(rawpt + width + 1)) /
1377                         4; /* B */
1378                     g = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt - width) +
1379                          *(rawpt + width)) /
1380                         4;      /* G */
1381                     r = *rawpt; /* R */
1382                 }
1383                 else {
1384                     /* bottom line or right column */
1385                     b = *(rawpt - width - 1);                  /* B */
1386                     g = (*(rawpt - 1) + *(rawpt - width)) / 2; /* G */
1387                     r = *rawpt;                                /* R */
1388                 }
1389             }
1390         }
1391         rawpt++;
1392         switch (format->BytesPerPixel) {
1393             case 1:
1394                 *d8++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
1395                         ((b >> bloss) << bshift);
1396                 break;
1397             case 2:
1398                 *d16++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
1399                          ((b >> bloss) << bshift);
1400                 break;
1401             case 3:
1402                 *d8++ = b;
1403                 *d8++ = g;
1404                 *d8++ = r;
1405                 break;
1406             default:
1407                 *d32++ = ((r >> rloss) << rshift) | ((g >> gloss) << gshift) |
1408                          ((b >> bloss) << bshift);
1409                 break;
1410         }
1411     }
1412 }
1413 
1414 /* convert from YUV 4:2:0 (YU12) to RGB24 */
1415 /* based on v4lconvert_yuv420_to_rgb24 in libv4l (C) 2008 Hans de Goede. LGPL
1416  */
1417 void
yuv420_to_rgb(const void * src,void * dst,int width,int height,SDL_PixelFormat * format)1418 yuv420_to_rgb(const void *src, void *dst, int width, int height,
1419               SDL_PixelFormat *format)
1420 {
1421     int rshift, gshift, bshift, rloss, gloss, bloss, i, j, u1, v1, rg, y;
1422     const Uint8 *y1, *y2, *u, *v;
1423     Uint8 *d8_1, *d8_2;
1424     Uint16 *d16_1, *d16_2;
1425     Uint32 *d32_1, *d32_2;
1426 
1427     rshift = format->Rshift;
1428     gshift = format->Gshift;
1429     bshift = format->Bshift;
1430     rloss = format->Rloss;
1431     gloss = format->Gloss;
1432     bloss = format->Bloss;
1433 
1434     /* see http://en.wikipedia.org/wiki/YUV for an explanation of YUV420 */
1435     y1 = (Uint8 *)src;
1436     y2 = y1 + width;
1437     u = y1 + width * height;
1438     v = u + (width * height) / 4;
1439     j = height / 2;
1440     /* prepare the destination pointers for different surface depths. */
1441     d8_1 = (Uint8 *)dst;
1442     /* the following is because d8 used for both 8 and 24 bit surfaces */
1443     d8_2 = d8_1 + (format->BytesPerPixel == 3 ? width * 3 : 3);
1444     d16_1 = (Uint16 *)dst;
1445     d16_2 = d16_1 + width;
1446     d32_1 = (Uint32 *)dst;
1447     d32_2 = d32_1 + width;
1448 
1449     /* for the sake of speed, the nested while loops are inside of the switch
1450       statement for the different surface bit depths */
1451     switch (format->BytesPerPixel) {
1452         case 1:
1453             while (j--) {
1454                 i = width / 2;
1455                 while (i--) {
1456                     /* These formulas are from libv4l */
1457                     u1 = (((*u - 128) << 7) + (*u - 128)) >> 6;
1458                     rg = (((*u - 128) << 1) + (*u - 128) + ((*v - 128) << 2) +
1459                           ((*v - 128) << 1)) >>
1460                          3;
1461                     v1 = (((*v - 128) << 1) + (*v - 128)) >> 1;
1462                     u++;
1463                     v++;
1464                     /* do the pixels on row 1 */
1465                     y = *y1++;
1466                     *d8_1++ = ((SAT2(y + v1) >> rloss) << rshift) |
1467                               ((SAT2(y - rg) >> gloss) << gshift) |
1468                               ((SAT2(y + u1) >> bloss) << bshift);
1469                     y = *y1++;
1470                     *d8_1++ = ((SAT2(y + v1) >> rloss) << rshift) |
1471                               ((SAT2(y - rg) >> gloss) << gshift) |
1472                               ((SAT2(y + u1) >> bloss) << bshift);
1473                     /* do the pixels on row 2 */
1474                     y = *y2++;
1475                     *d8_2++ = ((SAT2(y + v1) >> rloss) << rshift) |
1476                               ((SAT2(y - rg) >> gloss) << gshift) |
1477                               ((SAT2(y + u1) >> bloss) << bshift);
1478                     y = *y2++;
1479                     *d8_2++ = ((SAT2(y + v1) >> rloss) << rshift) |
1480                               ((SAT2(y - rg) >> gloss) << gshift) |
1481                               ((SAT2(y + u1) >> bloss) << bshift);
1482                 }
1483                 /* y2 is at the beginning of a new row, make it the new row 1
1484                  */
1485                 y1 = y2;
1486                 /* and make row 2 one row further */
1487                 y2 += width;
1488                 d8_1 = d8_2;
1489                 d8_2 += width;
1490             }
1491             break;
1492         case 2:
1493             while (j--) {
1494                 i = width / 2;
1495                 while (i--) {
1496                     /* These formulas are from libv4l */
1497                     u1 = (((*u - 128) << 7) + (*u - 128)) >> 6;
1498                     rg = (((*u - 128) << 1) + (*u - 128) + ((*v - 128) << 2) +
1499                           ((*v - 128) << 1)) >>
1500                          3;
1501                     v1 = (((*v - 128) << 1) + (*v - 128)) >> 1;
1502                     u++;
1503                     v++;
1504                     /* do the pixels on row 1 */
1505                     y = *y1++;
1506                     *d16_1++ = ((SAT2(y + v1) >> rloss) << rshift) |
1507                                ((SAT2(y - rg) >> gloss) << gshift) |
1508                                ((SAT2(y + u1) >> bloss) << bshift);
1509                     y = *y1++;
1510                     *d16_1++ = ((SAT2(y + v1) >> rloss) << rshift) |
1511                                ((SAT2(y - rg) >> gloss) << gshift) |
1512                                ((SAT2(y + u1) >> bloss) << bshift);
1513                     /* do the pixels on row 2 */
1514                     y = *y2++;
1515                     *d16_2++ = ((SAT2(y + v1) >> rloss) << rshift) |
1516                                ((SAT2(y - rg) >> gloss) << gshift) |
1517                                ((SAT2(y + u1) >> bloss) << bshift);
1518                     y = *y2++;
1519                     *d16_2++ = ((SAT2(y + v1) >> rloss) << rshift) |
1520                                ((SAT2(y - rg) >> gloss) << gshift) |
1521                                ((SAT2(y + u1) >> bloss) << bshift);
1522                 }
1523                 /* y2 is at the beginning of a new row, make it the new row 1
1524                  */
1525                 y1 = y2;
1526                 /* and make row 2 one row further */
1527                 y2 += width;
1528                 d16_1 = d16_2;
1529                 d16_2 += width;
1530             }
1531             break;
1532         case 3:
1533             while (j--) {
1534                 i = width / 2;
1535                 while (i--) {
1536                     /* These formulas are from libv4l */
1537                     u1 = (((*u - 128) << 7) + (*u - 128)) >> 6;
1538                     rg = (((*u - 128) << 1) + (*u - 128) + ((*v - 128) << 2) +
1539                           ((*v - 128) << 1)) >>
1540                          3;
1541                     v1 = (((*v - 128) << 1) + (*v - 128)) >> 1;
1542                     u++;
1543                     v++;
1544                     /* do the pixels on row 1 */
1545                     y = *y1++;
1546                     *d8_1++ = SAT2(y + u1);
1547                     *d8_1++ = SAT2(y - rg);
1548                     *d8_1++ = SAT2(y + v1);
1549                     y = *y1++;
1550                     *d8_1++ = SAT2(y + u1);
1551                     *d8_1++ = SAT2(y - rg);
1552                     *d8_1++ = SAT2(y + v1);
1553                     /* do the pixels on row 2 */
1554                     y = *y2++;
1555                     *d8_2++ = SAT2(y + u1);
1556                     *d8_2++ = SAT2(y - rg);
1557                     *d8_2++ = SAT2(y + v1);
1558                     y = *y2++;
1559                     *d8_2++ = SAT2(y + u1);
1560                     *d8_2++ = SAT2(y - rg);
1561                     *d8_2++ = SAT2(y + v1);
1562                 }
1563                 /* y2 is at the beginning of a new row, make it the new row 1
1564                  */
1565                 y1 = y2;
1566                 /* and make row 2 one row further */
1567                 y2 += width;
1568                 d8_1 = d8_2;
1569                 /* since it is 3 bytes per pixel */
1570                 d8_2 += width * 3;
1571             }
1572             break;
1573         default:
1574             while (j--) {
1575                 i = width / 2;
1576                 while (i--) {
1577                     /* These formulas are from libv4l */
1578                     u1 = (((*u - 128) << 7) + (*u - 128)) >> 6;
1579                     rg = (((*u - 128) << 1) + (*u - 128) + ((*v - 128) << 2) +
1580                           ((*v - 128) << 1)) >>
1581                          3;
1582                     v1 = (((*v - 128) << 1) + (*v - 128)) >> 1;
1583                     u++;
1584                     v++;
1585                     /* do the pixels on row 1 */
1586                     y = *y1++;
1587                     *d32_1++ = ((SAT2(y + v1) >> rloss) << rshift) |
1588                                ((SAT2(y - rg) >> gloss) << gshift) |
1589                                ((SAT2(y + u1) >> bloss) << bshift);
1590                     y = *y1++;
1591                     *d32_1++ = ((SAT2(y + v1) >> rloss) << rshift) |
1592                                ((SAT2(y - rg) >> gloss) << gshift) |
1593                                ((SAT2(y + u1) >> bloss) << bshift);
1594                     /* do the pixels on row 2 */
1595                     y = *y2++;
1596                     *d32_2++ = ((SAT2(y + v1) >> rloss) << rshift) |
1597                                ((SAT2(y - rg) >> gloss) << gshift) |
1598                                ((SAT2(y + u1) >> bloss) << bshift);
1599                     y = *y2++;
1600                     *d32_2++ = ((SAT2(y + v1) >> rloss) << rshift) |
1601                                ((SAT2(y - rg) >> gloss) << gshift) |
1602                                ((SAT2(y + u1) >> bloss) << bshift);
1603                 }
1604                 /* y2 is at the beginning of a new row, make it the new row 1
1605                  */
1606                 y1 = y2;
1607                 /* and make row 2 one row further */
1608                 y2 += width;
1609                 d32_1 = d32_2;
1610                 d32_2 += width;
1611             }
1612             break;
1613     }
1614 }
1615 
1616 /* turn yuv420 into packed yuv. */
1617 void
yuv420_to_yuv(const void * src,void * dst,int width,int height,SDL_PixelFormat * format)1618 yuv420_to_yuv(const void *src, void *dst, int width, int height,
1619               SDL_PixelFormat *format)
1620 {
1621     const Uint8 *y1, *y2, *u, *v;
1622     Uint8 *d8_1, *d8_2;
1623     Uint16 *d16_1, *d16_2;
1624     Uint32 *d32_1, *d32_2;
1625     int rshift, gshift, bshift, rloss, gloss, bloss, j, i;
1626 
1627     rshift = format->Rshift;
1628     gshift = format->Gshift;
1629     bshift = format->Bshift;
1630     rloss = format->Rloss;
1631     gloss = format->Gloss;
1632     bloss = format->Bloss;
1633 
1634     d8_1 = (Uint8 *)dst;
1635     d8_2 = d8_1 + (format->BytesPerPixel == 3 ? width * 3 : 3);
1636     d16_1 = (Uint16 *)dst;
1637     d16_2 = d16_1 + width;
1638     d32_1 = (Uint32 *)dst;
1639     d32_2 = d32_1 + width;
1640     y1 = (Uint8 *)src;
1641     y2 = y1 + width;
1642     u = y1 + width * height;
1643     v = u + (width * height) / 4;
1644     j = height / 2;
1645 
1646     switch (format->BytesPerPixel) {
1647         case 1:
1648             while (j--) {
1649                 i = width / 2;
1650                 while (i--) {
1651                     *d8_1++ = ((*y1++ >> rloss) << rshift) |
1652                               ((*u >> gloss) << gshift) |
1653                               ((*v >> bloss) << bshift);
1654                     *d8_1++ = ((*y1++ >> rloss) << rshift) |
1655                               ((*u >> gloss) << gshift) |
1656                               ((*v >> bloss) << bshift);
1657                     *d8_2++ = ((*y2++ >> rloss) << rshift) |
1658                               ((*u >> gloss) << gshift) |
1659                               ((*v >> bloss) << bshift);
1660                     *d8_2++ = ((*y2++ >> rloss) << rshift) |
1661                               ((*u++ >> gloss) << gshift) |
1662                               ((*v++ >> bloss) << bshift);
1663                 }
1664                 y1 = y2;
1665                 y2 += width;
1666                 d8_1 = d8_2;
1667                 d8_2 += width;
1668             }
1669             break;
1670         case 2:
1671             while (j--) {
1672                 i = width / 2;
1673                 while (i--) {
1674                     *d16_1++ = ((*y1++ >> rloss) << rshift) |
1675                                ((*u >> gloss) << gshift) |
1676                                ((*v >> bloss) << bshift);
1677                     *d16_1++ = ((*y1++ >> rloss) << rshift) |
1678                                ((*u >> gloss) << gshift) |
1679                                ((*v >> bloss) << bshift);
1680                     *d16_2++ = ((*y2++ >> rloss) << rshift) |
1681                                ((*u >> gloss) << gshift) |
1682                                ((*v >> bloss) << bshift);
1683                     *d16_2++ = ((*y2++ >> rloss) << rshift) |
1684                                ((*u++ >> gloss) << gshift) |
1685                                ((*v++ >> bloss) << bshift);
1686                 }
1687                 y1 = y2;
1688                 y2 += width;
1689                 d16_1 = d16_2;
1690                 d16_2 += width;
1691             }
1692             break;
1693         case 3:
1694             while (j--) {
1695                 i = width / 2;
1696                 while (i--) {
1697                     *d8_1++ = *v;
1698                     *d8_1++ = *u;
1699                     *d8_1++ = *y1++;
1700                     *d8_1++ = *v;
1701                     *d8_1++ = *u;
1702                     *d8_1++ = *y1++;
1703                     *d8_2++ = *v;
1704                     *d8_2++ = *u;
1705                     *d8_2++ = *y2++;
1706                     *d8_2++ = *v++;
1707                     *d8_2++ = *u++;
1708                     *d8_2++ = *y2++;
1709                 }
1710                 y1 = y2;
1711                 y2 += width;
1712                 d8_1 = d8_2;
1713                 d8_2 += width * 3;
1714             }
1715             break;
1716         default:
1717             while (j--) {
1718                 i = width / 2;
1719                 while (i--) {
1720                     *d32_1++ = ((*y1++ >> rloss) << rshift) |
1721                                ((*u >> gloss) << gshift) |
1722                                ((*v >> bloss) << bshift);
1723                     *d32_1++ = ((*y1++ >> rloss) << rshift) |
1724                                ((*u >> gloss) << gshift) |
1725                                ((*v >> bloss) << bshift);
1726                     *d32_2++ = ((*y2++ >> rloss) << rshift) |
1727                                ((*u >> gloss) << gshift) |
1728                                ((*v >> bloss) << bshift);
1729                     *d32_2++ = ((*y2++ >> rloss) << rshift) |
1730                                ((*u++ >> gloss) << gshift) |
1731                                ((*v++ >> bloss) << bshift);
1732                 }
1733                 y1 = y2;
1734                 y2 += width;
1735                 d32_1 = d32_2;
1736                 d32_2 += width;
1737             }
1738             break;
1739     }
1740 }
1741 
1742 /*
1743  * Python API stuff
1744  */
1745 
1746 /* Camera class definition */
1747 PyMethodDef cameraobj_builtins[] = {
1748     {"start", (PyCFunction)camera_start, METH_NOARGS, DOC_CAMERASTART},
1749     {"stop", (PyCFunction)camera_stop, METH_NOARGS, DOC_CAMERASTOP},
1750     {"get_controls", (PyCFunction)camera_get_controls, METH_NOARGS,
1751      DOC_CAMERAGETCONTROLS},
1752     {"set_controls", (PyCFunction)camera_set_controls,
1753      METH_VARARGS | METH_KEYWORDS, DOC_CAMERASETCONTROLS},
1754     {"get_size", (PyCFunction)camera_get_size, METH_NOARGS, DOC_CAMERAGETSIZE},
1755     {"query_image", (PyCFunction)camera_query_image, METH_NOARGS,
1756      DOC_CAMERAQUERYIMAGE},
1757     {"get_image", (PyCFunction)camera_get_image, METH_VARARGS,
1758      DOC_CAMERAGETIMAGE},
1759     {"get_raw", (PyCFunction)camera_get_raw, METH_NOARGS, DOC_CAMERAGETRAW},
1760     {NULL, NULL, 0, NULL}};
1761 
1762 void
camera_dealloc(PyObject * self)1763 camera_dealloc(PyObject *self)
1764 {
1765 #if defined(PYGAME_WINDOWS_CAMERA)
1766     if (((pgCameraObject *)self)->open) {
1767         windows_close_device((pgCameraObject *)self);
1768     }
1769     windows_dealloc_device((pgCameraObject *)self);
1770 #else
1771     free(((pgCameraObject *)self)->device_name);
1772 #endif
1773     PyObject_DEL(self);
1774 }
1775 /*
1776 PyObject* camera_getattr(PyObject* self, char* attrname) {
1777     return Py_FindMethod(cameraobj_builtins, self, attrname);
1778 }
1779 */
1780 PyTypeObject pgCamera_Type = {
1781     PyVarObject_HEAD_INIT(NULL, 0) "Camera",
1782     sizeof(pgCameraObject),
1783     0,
1784     camera_dealloc,
1785     0,
1786     0,                 /*camera_getattr */
1787     NULL,              /*setattr*/
1788     NULL,              /*compare*/
1789     NULL,              /*repr*/
1790     NULL,              /*as_number*/
1791     NULL,              /*as_sequence*/
1792     NULL,              /*as_mapping*/
1793     (hashfunc)NULL,    /*hash*/
1794     (ternaryfunc)NULL, /*call*/
1795     (reprfunc)NULL,    /*str*/
1796     0L,
1797     0L,
1798     0L,
1799     0L,
1800     DOC_PYGAMECAMERACAMERA, /* Documentation string */
1801     0,                      /* tp_traverse */
1802     0,                      /* tp_clear */
1803     0,                      /* tp_richcompare */
1804     0,                      /* tp_weaklistoffset */
1805     0,                      /* tp_iter */
1806     0,                      /* tp_iternext */
1807     cameraobj_builtins,     /* tp_methods */
1808     0,                      /* tp_members */
1809     0,                      /* tp_getset */
1810     0,                      /* tp_base */
1811     0,                      /* tp_dict */
1812     0,                      /* tp_descr_get */
1813     0,                      /* tp_descr_set */
1814     0,                      /* tp_dictoffset */
1815     0,                      /* tp_init */
1816     0,                      /* tp_alloc */
1817     0,                      /* tp_new */
1818 };
1819 
1820 PyObject *
Camera(pgCameraObject * self,PyObject * arg)1821 Camera(pgCameraObject *self, PyObject *arg)
1822 {
1823 #if defined(__unix__)
1824     int w, h;
1825     char *dev_name = NULL;
1826     char *color = NULL;
1827     pgCameraObject *cameraobj;
1828 
1829     w = DEFAULT_WIDTH;
1830     h = DEFAULT_HEIGHT;
1831 
1832     if (!PyArg_ParseTuple(arg, "s|(ii)s", &dev_name, &w, &h, &color))
1833         return NULL;
1834 
1835     cameraobj = PyObject_NEW(pgCameraObject, &pgCamera_Type);
1836 
1837     if (cameraobj) {
1838         cameraobj->device_name =
1839             (char *)malloc((strlen(dev_name) + 1) * sizeof(char));
1840         if (!cameraobj->device_name) {
1841             Py_DECREF(cameraobj);
1842             return PyErr_NoMemory();
1843         }
1844         strcpy(cameraobj->device_name, dev_name);
1845         cameraobj->camera_type = 0;
1846         cameraobj->pixelformat = 0;
1847         if (color) {
1848             if (!strcmp(color, "YUV")) {
1849                 cameraobj->color_out = YUV_OUT;
1850             }
1851             else if (!strcmp(color, "HSV")) {
1852                 cameraobj->color_out = HSV_OUT;
1853             }
1854             else {
1855                 cameraobj->color_out = RGB_OUT;
1856             }
1857         }
1858         else {
1859             cameraobj->color_out = RGB_OUT;
1860         }
1861         cameraobj->buffers = NULL;
1862         cameraobj->n_buffers = 0;
1863         cameraobj->width = w;
1864         cameraobj->height = h;
1865         cameraobj->size = 0;
1866         cameraobj->hflip = 0;
1867         cameraobj->vflip = 0;
1868         cameraobj->brightness = 0;
1869         cameraobj->fd = -1;
1870     }
1871 
1872     return (PyObject *)cameraobj;
1873 #elif defined(PYGAME_WINDOWS_CAMERA)
1874     pgCameraObject *cameraobj;
1875     PyObject *name_obj = NULL;
1876     WCHAR *dev_name = NULL;
1877     int w, h;
1878     char *color = NULL;
1879     IMFActivate *p = NULL;
1880 
1881     w = DEFAULT_WIDTH;
1882     h = DEFAULT_HEIGHT;
1883 
1884     if (!PyArg_ParseTuple(arg, "O|(ii)s", &name_obj, &w, &h, &color))
1885         return NULL;
1886 
1887     /* needs to be freed with PyMem_Free later */
1888     dev_name = PyUnicode_AsWideCharString(name_obj, NULL);
1889 
1890     p = windows_device_from_name(dev_name);
1891 
1892     if (!p) {
1893         return RAISE(PyExc_ValueError,
1894                      "Couldn't find a camera with that name");
1895     }
1896 
1897     cameraobj = PyObject_NEW(pgCameraObject, &pgCamera_Type);
1898 
1899     if (color) {
1900         if (!strcmp(color, "YUV")) {
1901             cameraobj->color_out = YUV_OUT;
1902         }
1903         else if (!strcmp(color, "HSV")) {
1904             cameraobj->color_out = HSV_OUT;
1905         }
1906         else {
1907             cameraobj->color_out = RGB_OUT;
1908         }
1909     }
1910     else {
1911         cameraobj->color_out = RGB_OUT;
1912     }
1913 
1914     cameraobj->device_name = dev_name;
1915     cameraobj->width = w;
1916     cameraobj->height = h;
1917     cameraobj->open = 0;
1918     cameraobj->hflip = 0;
1919     cameraobj->vflip = 0;
1920     cameraobj->last_vflip = 0;
1921 
1922     cameraobj->raw_buf = NULL;
1923     cameraobj->buf = NULL;
1924     cameraobj->t_handle = NULL;
1925 
1926     if (!windows_init_device(self)) {
1927         return NULL;
1928     }
1929 
1930     return (PyObject *)cameraobj;
1931 #endif
1932 }
1933 
1934 /* Camera module definition */
1935 PyMethodDef camera_builtins[] = {
1936     {"colorspace", surf_colorspace, METH_VARARGS, DOC_PYGAMECAMERACOLORSPACE},
1937     {"list_cameras", list_cameras, METH_NOARGS, DOC_PYGAMECAMERALISTCAMERAS},
1938     {"Camera", (PyCFunction)Camera, METH_VARARGS, DOC_PYGAMECAMERACAMERA},
1939     {NULL, NULL, 0, NULL}};
1940 
MODINIT_DEFINE(_camera)1941 MODINIT_DEFINE(_camera)
1942 {
1943     PyObject *module;
1944     /* imported needed apis; Do this first so if there is an error
1945      * the module is not loaded.
1946      */
1947 
1948     static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
1949                                          "_camera",
1950                                          DOC_PYGAMECAMERA,
1951                                          -1,
1952                                          camera_builtins,
1953                                          NULL,
1954                                          NULL,
1955                                          NULL,
1956                                          NULL};
1957 
1958     import_pygame_base();
1959     if (PyErr_Occurred()) {
1960         MODINIT_ERROR;
1961     }
1962     import_pygame_surface();
1963     if (PyErr_Occurred()) {
1964         MODINIT_ERROR;
1965     }
1966 
1967     /* type preparation */
1968     // PyType_Init(pgCamera_Type);
1969     pgCamera_Type.tp_new = PyType_GenericNew;
1970     if (PyType_Ready(&pgCamera_Type) < 0) {
1971         MODINIT_ERROR;
1972     }
1973 
1974     /* create the module */
1975     module = PyModule_Create(&_module);
1976 
1977     Py_INCREF(&pgCamera_Type);
1978     PyModule_AddObject(module, "CameraType", (PyObject *)&pgCamera_Type);
1979 
1980     MODINIT_RETURN(module);
1981 }
1982