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