doxygen: bge scenegraph and videotexture
[blender-staging.git] / source / gameengine / VideoTexture / FilterSource.h
1 /* $Id$
2 -----------------------------------------------------------------------------
3 This source file is part of blendTex library
4
5 Copyright (c) 2007 The Zdeno Ash Miklas
6
7 This program is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the Free Software
9 Foundation; either version 2 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License along with
17 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
19 http://www.gnu.org/copyleft/lesser.txt.
20 -----------------------------------------------------------------------------
21 */
22
23 /** \file FilterSource.h
24  *  \ingroup bgevideotex
25  */
26  
27 #if !defined FILTERSOURCE_H
28 #define FILTERSOURCE_H
29
30 #include "Common.h"
31
32 #include "FilterBase.h"
33
34
35 /// class for RGB24 conversion
36 class FilterRGB24 : public FilterBase
37 {
38 public:
39         /// constructor
40         FilterRGB24 (void) {}
41         /// destructor
42         virtual ~FilterRGB24 (void) {}
43
44         /// get source pixel size
45         virtual unsigned int getPixelSize (void) { return 3; }
46
47 protected:
48         /// filter pixel, source byte buffer
49         virtual unsigned int filter (unsigned char * src, short x, short y,
50                 short * size, unsigned int pixSize, unsigned int val)
51         { VT_RGBA(val,src[0],src[1],src[2],0xFF); return val; }
52 };
53
54 /// class for RGBA32 conversion
55 class FilterRGBA32 : public FilterBase
56 {
57 public:
58         /// constructor
59         FilterRGBA32 (void) {}
60         /// destructor
61         virtual ~FilterRGBA32 (void) {}
62
63         /// get source pixel size
64         virtual unsigned int getPixelSize (void) { return 4; }
65
66 protected:
67         /// filter pixel, source byte buffer
68         virtual unsigned int filter (unsigned char * src, short x, short y,
69                 short * size, unsigned int pixSize, unsigned int val)
70         { 
71                 if ((intptr_t(src)&0x3) == 0) 
72                         return *(unsigned int*)src;
73                 else 
74                 {
75                         VT_RGBA(val,src[0],src[1],src[2],src[3]); 
76                         return val; 
77                 }
78         }
79 };
80
81 /// class for BGR24 conversion
82 class FilterBGR24 : public FilterBase
83 {
84 public:
85         /// constructor
86         FilterBGR24 (void) {}
87         /// destructor
88         virtual ~FilterBGR24 (void) {}
89
90         /// get source pixel size
91         virtual unsigned int getPixelSize (void) { return 3; }
92
93 protected:
94         /// filter pixel, source byte buffer
95         virtual unsigned int filter (unsigned char * src, short x, short y,
96                 short * size, unsigned int pixSize, unsigned int val)
97         { VT_RGBA(val,src[2],src[1],src[0],0xFF); return val; }
98 };
99
100 /// class for YV12 conversion
101 class FilterYV12 : public FilterBase
102 {
103 public:
104         /// constructor
105         FilterYV12 (void) {}
106         /// destructor
107         virtual ~FilterYV12 (void) {}
108
109         /// get source pixel size
110         virtual unsigned int getPixelSize (void) { return 1; }
111
112         /// set pointers to color buffers
113         void setBuffs (unsigned char * buff, short * size)
114         {
115                 unsigned int buffSize = size[0] * size[1];
116                 m_buffV = buff + buffSize;
117                 m_buffU = m_buffV + (buffSize >> 2);
118                 m_pitchUV = size[0] >> 1;
119         }
120
121 protected:
122         /// begin of V buffer
123         unsigned char * m_buffV;
124         /// begin of U buffer
125         unsigned char * m_buffU;
126         /// pitch for V & U buffers
127         short m_pitchUV;
128
129         /// interpolation function
130         int interpol (int a, int b, int c, int d)
131         { return (9 * (b + c) - a - d + 8) >> 4; }
132
133         /// common horizontal interpolation
134         int interpolH (unsigned char * src)
135         { return interpol(*(src-1), *src, *(src+1), *(src+2)); }
136
137         /// common vertical interpolation
138         int interpolV (unsigned char * src)
139         { return interpol(*(src-m_pitchUV), *src, *(src+m_pitchUV), *(src+2*m_pitchUV)); }
140
141         /// common joined vertical and horizontal interpolation
142         int interpolVH (unsigned char * src)
143         {
144                 return interpol(interpolV(src-1), interpolV(src), interpolV(src+1),
145                         interpolV(src+2));
146         }
147
148         /// is pixel on edge
149         bool isEdge (short x, short y, short * size)
150         { return x <= 1 || x >= size[0] - 4 || y <= 1 || y >= size[1] - 4; }
151
152         /// get the first parameter on the low edge
153         unsigned char * interParA (unsigned char * src, short x, short size, short shift)
154         { return x > 1 ? src - shift : src; }
155         /// get the third parameter on the high edge
156         unsigned char * interParC (unsigned char * src, short x, short size, short shift)
157         { return x < size - 2 ? src + shift : src; }
158         /// get the fourth parameter on the high edge
159         unsigned char * interParD (unsigned char * src, short x, short size, short shift)
160         { return x < size - 4 ? src + 2 * shift : x < size - 2 ? src + shift : src; }
161
162         /// horizontal interpolation on edges
163         int interpolEH (unsigned char * src, short x, short size)
164         { 
165                 return interpol(*interParA(src, x, size, 1), *src,
166                         *interParC(src, x, size, 1), *interParD(src, x, size, 1));
167         }
168
169         /// vertical interpolation on edges
170         int interpolEV (unsigned char * src, short y, short size)
171         { 
172                 return interpol(*interParA(src, y, size, m_pitchUV), *src,
173                         *interParC(src, y, size, m_pitchUV), *interParD(src, y, size, m_pitchUV));
174         }
175
176         /// joined vertical and horizontal interpolation on edges
177         int interpolEVH (unsigned char * src, short x, short y, short * size)
178         {
179                 return interpol(interpolEV(interParA(src, x, size[0], 1), y, size[1]),
180                         interpolEV(src, y, size[1]), interpolEV(interParC(src, x, size[0], 1), y, size[1]),
181                         interpolEV(interParD(src, x, size[0], 1), y, size[1]));
182         }
183
184
185         /// filter pixel, source byte buffer
186         virtual unsigned int filter (unsigned char * src, short x, short y,
187                 short * size, unsigned int pixSize, unsigned int val)
188         {
189                 // V & U offset
190                 long offset = (x >> 1) + m_pitchUV * (y >> 1);
191                 // get modified YUV -> CDE: C = Y - 16; D = U - 128; E = V - 128
192                 int c = *src - 16;
193                 int d = m_buffU[offset] - 128;
194                 int e = m_buffV[offset] - 128;
195                 // if horizontal interpolation is needed
196                 if ((x & 1) == 1) {
197                         // if vertical interpolation is needed too
198                         if ((y & 1) == 1)
199                         {
200                                 // if this pixel is on the edge
201                                 if (isEdge(x, y, size))
202                                 {
203                                         // get U & V from edge
204                                         d = interpolEVH(m_buffU + offset, x, y, size) - 128;
205                                         e = interpolEVH(m_buffV + offset, x, y, size) - 128;
206                                 }
207                                 // otherwise get U & V from inner range
208                                 else
209                                 {
210                                         d = interpolVH(m_buffU + offset) - 128;
211                                         e = interpolVH(m_buffV + offset) - 128;
212                                 }
213                                 // otherwise use horizontal interpolation only
214                         }
215                         else {
216                                 // if this pixel is on the edge
217                                 if (isEdge(x, y, size))
218                                 {
219                                         // get U & V from edge
220                                         d = interpolEH(m_buffU + offset, x, size[0]) - 128;
221                                         e = interpolEH(m_buffV + offset, x, size[0]) - 128;
222                                 }
223                                 // otherwise get U & V from inner range
224                                 else
225                                 {
226                                         d = interpolH(m_buffU + offset) - 128;
227                                         e = interpolH(m_buffV + offset) - 128;
228                                 }
229                                 // otherwise if only vertical interpolation is needed
230                         }
231                 }
232                 else if ((y & 1) == 1) {
233                         // if this pixel is on the edge
234                         if (isEdge(x, y, size))
235                         {
236                                 // get U & V from edge
237                                 d = interpolEV(m_buffU + offset, y, size[1]) - 128;
238                                 e = interpolEV(m_buffV + offset, y, size[1]) - 128;
239                         }
240                         // otherwise get U & V from inner range
241                         else
242                         {
243                                 d = interpolV(m_buffU + offset) - 128;
244                                 e = interpolV(m_buffV + offset) - 128;
245                         }
246                 }
247                 // convert to RGB
248                 // R = clip(( 298 * C           + 409 * E + 128) >> 8)
249                 // G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
250                 // B = clip(( 298 * C + 516 * D           + 128) >> 8)
251                 int red = (298 * c + 409 * e + 128) >> 8;
252                 if (red >= 0x100) red = 0xFF;
253                 else if (red < 0) red = 0;
254                 int green = (298 * c - 100 * d - 208 * e) >> 8;
255                 if (green >= 0x100) green = 0xFF;
256                 else if (green < 0) green = 0;
257                 int blue = (298 * c + 516 * d + 128) >> 8;
258                 if (blue >= 0x100) blue = 0xFF;
259                 else if (blue < 0) blue = 0;
260                 // return result
261                 VT_RGBA(val, red, green, blue, 0xFF);
262                 return val;
263         }
264 };
265
266
267 #endif