shell32: Have SHELL_ArgifyW respect the length of the buffer passed in and report...
[wine.git] / dlls / qcap / yuv.c
blob36e1855f6f2103a9bfc8ac03ed379e98505cebd3
1 /* DirectShow capture services (QCAP.DLL)
3 * Copyright 2005 Maarten Lankhorst
5 * This file contains the part of the vfw capture interface that
6 * does the actual Video4Linux(1/2) stuff required for capturing
7 * and setting/getting media format..
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 #include "strmif.h"
30 #include "qcap_main.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
35 static int yuv_xy[256]; /* Gray value */
36 static int yuv_gu[256]; /* Green U */
37 static int yuv_bu[256]; /* Blue U */
38 static int yuv_rv[256]; /* Red V */
39 static int yuv_gv[256]; /* Green V */
40 static int initialised = 0;
42 static inline int ValidRange(int in) {
43 if (in > 255) in = 255;
44 if (in < 0) in = 0;
45 return in;
48 typedef struct RGB {
49 #if 0 /* For some reason I have to revert R and B, not sure why */
50 unsigned char r, g, b;
51 #else
52 unsigned char b, g, r;
53 #endif
54 } RGB;
56 static inline void YUV2RGB(const unsigned char y_, const unsigned char cb, const unsigned char cr, RGB* retval) {
57 retval->r = ValidRange(yuv_xy[y_] + yuv_rv[cr]);
58 retval->g = ValidRange(yuv_xy[y_] + yuv_gu[cb] + yuv_gv[cr]);
59 retval->b = ValidRange(yuv_xy[y_] + yuv_bu[cb]);
62 void YUV_Init(void) {
63 float y, u, v;
64 int y_, cb, cr;
66 if (initialised++) return;
68 for (y_ = 0; y_ <= 255; y_++)
70 y = ((float) 255 / 219) * (y_ - 16);
71 yuv_xy[y_] = ValidRange((int) (y));
74 for (cb = 0; cb <= 255; cb++)
76 u = ((float) 255 / 224) * (cb - 128);
77 yuv_gu[cb] = - ValidRange((int) (0.344 * u));
78 yuv_bu[cb] = ValidRange((int) (1.772 * u));
81 for (cr = 0; cr <= 255; cr++)
83 v = ((float) 255 / 224) * (cr - 128);
84 yuv_rv[cr] = ValidRange((int) (1.402 * v));
85 yuv_gv[cr] = - ValidRange((int) (0.714 * v));
87 TRACE("Filled hash table\n");
90 static void Parse_YUYV(unsigned char *destbuffer, const unsigned char *input, int width, int height)
92 const unsigned char *pY, *pCb, *pCr;
93 int togo = width * height / 2;
94 pY = input;
95 pCb = input+1;
96 pCr = input+3;
97 while (--togo) {
98 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
99 pY += 2; destbuffer += 3;
100 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
101 pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
105 static void Parse_UYVY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
107 const unsigned char *pY, *pCb, *pCr;
108 int togo = width * height / 2;
109 pY = input+1;
110 pCb = input;
111 pCr = input+2;
112 while (--togo) {
113 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
114 pY += 2; destbuffer += 3;
115 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
116 pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
120 static void Parse_UYYVYY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
122 const unsigned char *pY, *pCb, *pCr;
123 int togo = width * height / 4;
124 pY = input+1;
125 pCb = input;
126 pCr = input+4;
127 while (--togo) {
128 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
129 destbuffer += 3; pY++;
130 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
131 pY += 2; destbuffer += 3;
132 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
133 destbuffer += 3; pY++;
134 YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
135 pY += 2; pCb += 6; pCr += 6; destbuffer += 3;
139 static void Parse_PYUV(unsigned char *destbuffer, const unsigned char *input, int width, int height, int wstep, int hstep)
141 /* We have 3 pointers, One to Y, one to Cb and 1 to Cr */
143 /* C19 *89* declaration block (Grr julliard for not allowing C99) */
144 int uvjump, ysize, uvsize;
145 const unsigned char *pY, *pCb, *pCr;
146 int swstep = 0, shstep = 0;
147 int ypos = 0, xpos = 0;
148 int indexUV = 0, cUv;
149 /* End of Grr */
151 uvjump = width / wstep;
152 ysize = width * height;
153 uvsize = (width / wstep) * (height / hstep);
154 pY = input;
155 pCb = pY + ysize;
156 pCr = pCb + uvsize;
157 /* Bottom down DIB */
158 do {
159 swstep = 0;
160 cUv = indexUV;
161 for (xpos = 0; xpos < width; xpos++) {
162 YUV2RGB(*(pY++), pCb[cUv], pCr[cUv], (RGB *)destbuffer);
163 destbuffer += 3;
164 if (++swstep == wstep) {
165 cUv++;
166 swstep = 0;
169 if (++shstep == hstep) {
170 shstep = 0;
171 indexUV = cUv;
173 } while (++ypos < height);
176 void YUV_To_RGB24(enum YUV_Format format, unsigned char *target, const unsigned char *source, int width, int height) {
177 int wstep, hstep;
178 if (format < ENDPLANAR) {
179 switch (format) {
180 case YUVP_421: wstep = 2; hstep = 1; break;
181 case YUVP_422: wstep = 2; hstep = 2; break;
182 case YUVP_441: wstep = 4; hstep = 1; break;
183 case YUVP_444: wstep = 4; hstep = 4; break;
184 default: ERR("Unhandled format \"%d\"\n", format); return;
186 Parse_PYUV(target, source, width, height, wstep, hstep);
187 } else {
188 switch (format) {
189 case YUYV: Parse_YUYV(target, source, width, height); return;
190 case UYVY: Parse_UYVY(target, source, width, height); return;
191 case UYYVYY: Parse_UYYVYY(target, source, width, height); return;
192 default: ERR("Unhandled format \"%d\"\n", format); return;