7bed5c77a4da340d15f52beb1943baa87305d1c4
[blender.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 #if !defined FILTERSOURCE_H
24 #define FILTERSOURCE_H
25
26 #include "Common.h"
27
28 #include "FilterBase.h"
29
30
31 /// class for RGB24 conversion
32 class FilterRGB24 : public FilterBase
33 {
34 public:
35         /// constructor
36         FilterRGB24 (void) {}
37         /// destructor
38         virtual ~FilterRGB24 (void) {}
39
40         /// get source pixel size
41         virtual unsigned int getPixelSize (void) { return 3; }
42
43 protected:
44         /// filter pixel, source byte buffer
45         virtual unsigned int filter (unsigned char * src, short x, short y,
46                 short * size, unsigned int pixSize, unsigned int val)
47         { return 0xFF000000 | src[0] << 16 | src[1] << 8 | src[2]; }
48 };
49
50
51 /// class for BGR24 conversion
52 class FilterBGR24 : public FilterBase
53 {
54 public:
55         /// constructor
56         FilterBGR24 (void) {}
57         /// destructor
58         virtual ~FilterBGR24 (void) {}
59
60         /// get source pixel size
61         virtual unsigned int getPixelSize (void) { return 3; }
62
63 protected:
64         /// filter pixel, source byte buffer
65         virtual unsigned int filter (unsigned char * src, short x, short y,
66                 short * size, unsigned int pixSize, unsigned int val)
67         { return 0xFF000000 | src[2] << 16 | src[1] << 8 | src[0]; }
68 };
69
70
71 /// class for YV12 conversion
72 class FilterYV12 : public FilterBase
73 {
74 public:
75         /// constructor
76         FilterYV12 (void) {}
77         /// destructor
78         virtual ~FilterYV12 (void) {}
79
80         /// get source pixel size
81         virtual unsigned int getPixelSize (void) { return 1; }
82
83         /// set pointers to color buffers
84         void setBuffs (unsigned char * buff, short * size)
85         {
86                 unsigned int buffSize = size[0] * size[1];
87                 m_buffV = buff + buffSize;
88                 m_buffU = m_buffV + (buffSize >> 2);
89                 m_pitchUV = size[0] >> 1;
90         }
91
92 protected:
93         /// begin of V buffer
94         unsigned char * m_buffV;
95         /// begin of U buffer
96         unsigned char * m_buffU;
97         /// pitch for V & U buffers
98         short m_pitchUV;
99
100         /// interpolation function
101         int interpol (int a, int b, int c, int d)
102         { return (9 * (b + c) - a - d + 8) >> 4; }
103
104         /// common horizontal interpolation
105         int interpolH (unsigned char * src)
106         { return interpol(*(src-1), *src, *(src+1), *(src+2)); }
107
108         /// common vertical interpolation
109         int interpolV (unsigned char * src)
110         { return interpol(*(src-m_pitchUV), *src, *(src+m_pitchUV), *(src+2*m_pitchUV)); }
111
112         /// common joined vertical and horizontal interpolation
113         int interpolVH (unsigned char * src)
114         {
115                 return interpol(interpolV(src-1), interpolV(src), interpolV(src+1),
116                         interpolV(src+2));
117         }
118
119         /// is pixel on edge
120         bool isEdge (short x, short y, short * size)
121         { return x <= 1 || x >= size[0] - 4 || y <= 1 || y >= size[1] - 4; }
122
123         /// get the first parameter on the low edge
124         unsigned char * interParA (unsigned char * src, short x, short size, short shift)
125         { return x > 1 ? src - shift : src; }
126         /// get the third parameter on the high edge
127         unsigned char * interParC (unsigned char * src, short x, short size, short shift)
128         { return x < size - 2 ? src + shift : src; }
129         /// get the fourth parameter on the high edge
130         unsigned char * interParD (unsigned char * src, short x, short size, short shift)
131         { return x < size - 4 ? src + 2 * shift : x < size - 2 ? src + shift : src; }
132
133         /// horizontal interpolation on edges
134         int interpolEH (unsigned char * src, short x, short size)
135         { 
136                 return interpol(*interParA(src, x, size, 1), *src,
137                         *interParC(src, x, size, 1), *interParD(src, x, size, 1));
138         }
139
140         /// vertical interpolation on edges
141         int interpolEV (unsigned char * src, short y, short size)
142         { 
143                 return interpol(*interParA(src, y, size, m_pitchUV), *src,
144                         *interParC(src, y, size, m_pitchUV), *interParD(src, y, size, m_pitchUV));
145         }
146
147         /// joined vertical and horizontal interpolation on edges
148         int interpolEVH (unsigned char * src, short x, short y, short * size)
149         {
150                 return interpol(interpolEV(interParA(src, x, size[0], 1), y, size[1]),
151                         interpolEV(src, y, size[1]), interpolEV(interParC(src, x, size[0], 1), y, size[1]),
152                         interpolEV(interParD(src, x, size[0], 1), y, size[1]));
153         }
154
155
156         /// filter pixel, source byte buffer
157         virtual unsigned int filter (unsigned char * src, short x, short y,
158                 short * size, unsigned int pixSize, unsigned int val)
159         {
160                 // V & U offset
161                 long offset = (x >> 1) + m_pitchUV * (y >> 1);
162                 // get modified YUV -> CDE: C = Y - 16; D = U - 128; E = V - 128
163                 int c = *src - 16;
164                 int d = m_buffU[offset] - 128;
165                 int e = m_buffV[offset] - 128;
166                 // if horizontal interpolation is needed
167                 if ((x & 1) == 1)
168                         // if vertical interpolation is needed too
169                         if ((y & 1) == 1)
170                                 // if this pixel is on the edge
171                                 if (isEdge(x, y, size))
172                                 {
173                                         // get U & V from edge
174                                         d = interpolEVH(m_buffU + offset, x, y, size) - 128;
175                                         e = interpolEVH(m_buffV + offset, x, y, size) - 128;
176                                 }
177                                 // otherwise get U & V from inner range
178                                 else
179                                 {
180                                         d = interpolVH(m_buffU + offset) - 128;
181                                         e = interpolVH(m_buffV + offset) - 128;
182                                 }
183                                 // otherwise use horizontal interpolation only
184                         else
185                                 // if this pixel is on the edge
186                                 if (isEdge(x, y, size))
187                                 {
188                                         // get U & V from edge
189                                         d = interpolEH(m_buffU + offset, x, size[0]) - 128;
190                                         e = interpolEH(m_buffV + offset, x, size[0]) - 128;
191                                 }
192                                 // otherwise get U & V from inner range
193                                 else
194                                 {
195                                         d = interpolH(m_buffU + offset) - 128;
196                                         e = interpolH(m_buffV + offset) - 128;
197                                 }
198                                 // otherwise if only vertical interpolation is needed
199                 else if ((y & 1) == 1)
200                         // if this pixel is on the edge
201                         if (isEdge(x, y, size))
202                         {
203                                 // get U & V from edge
204                                 d = interpolEV(m_buffU + offset, y, size[1]) - 128;
205                                 e = interpolEV(m_buffV + offset, y, size[1]) - 128;
206                         }
207                         // otherwise get U & V from inner range
208                         else
209                         {
210                                 d = interpolV(m_buffU + offset) - 128;
211                                 e = interpolV(m_buffV + offset) - 128;
212                         }
213                 // convert to RGB
214                 // R = clip(( 298 * C           + 409 * E + 128) >> 8)
215                 // G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
216                 // B = clip(( 298 * C + 516 * D           + 128) >> 8)
217                 int red = (298 * c + 409 * e + 128) >> 8;
218                 if (red >= 0x100) red = 0xFF;
219                 else if (red < 0) red = 0;
220                 int green = 298 * c - 100 * d - 208 * e;
221                 if (green > 0x10000) green = 0xFF00;
222                 else if (green < 0) green = 0;
223                 int blue = (298 * c + 516 * d + 128) << 8;
224                 if (blue > 0x1000000) blue = 0xFF0000;
225                 else if (blue < 0) blue = 0;
226                 // return result
227                 return 0xFF000000 | blue & 0xFF0000 | green & 0xFF00
228                         | red & 0xFF;
229         }
230 };
231
232
233 #endif