Made bilinear interpolation function work, and edge conditions into structs with static functions rather than plain functions (in order to make bilinear interpolation work.)

Originally committed to SVN as r1511.
This commit is contained in:
Niels Martin Hansen 2007-08-18 13:42:37 +00:00
parent 8e5e70cf8b
commit 17fbbaa583
2 changed files with 63 additions and 55 deletions

View file

@ -588,66 +588,74 @@ typedef BaseImageAggregateImpl<PixelFormat::ABGR> ImageABGR;
// Access pixels with various edge conditions
namespace EdgeCondition {
template<class PixFmt>
inline PixFmt &blackness(BaseImage<PixFmt> &img, int x, int y)
{
if (x < 0 || y < 0 || x >= img.width || x >= img.height) {
return PixFmt(); // all construct with all zeroes
} else {
struct Blackness {
static inline PixFmt &get(BaseImage<PixFmt> &img, int x, int y)
{
if (x < 0 || y < 0 || x >= img.width || x >= img.height) {
return PixFmt(); // all construct with all zeroes
} else {
return img.Pixel(x,y);
}
}
};
template<class PixFmt>
struct Closest {
static inline PixFmt &get(BaseImage<PixFmt> &img, int x, int y)
{
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= img.width) x = img.width-1;
if (y >= img.height) y = img.height - 1;
return img.Pixel(x,y);
}
}
};
template<class PixFmt>
inline PixFmt &closest(BaseImage<PixFmt> &img, int x, int y)
{
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= img.width) x = img.width-1;
if (y >= img.height) y = img.height - 1;
return img.Pixel(x,y);
}
struct Repeat {
static inline PixFmt &get(BaseImage<PixFmt> &img, int x, int y)
{
while (x < 0) x += img.width;
while (y < 0) y += img.height;
while (x >= img.width) x -= img.width;
while (y >= img.height) y -= img.height;
return img.Pixel(x,y);
}
};
template<class PixFmt>
inline PixFmt &repeat(BaseImage<PixFmt> &img, int x, int y)
{
while (x < 0) x += img.width;
while (y < 0) y += img.height;
while (x >= img.width) x -= img.width;
while (y >= img.height) y -= img.height;
return img.Pixel(x,y);
}
template<class PixFmt>
inline PixFmt &mirror(BaseImage<PixFmt> &img, int x, int y)
{
while (x < 0) x += img.width*2;
while (y < 0) y += img.height*2;
while (x >= img.width*2) x -= img.width*2;
while (y >= img.height*2) y -= img.height*2;
if (x >= img.width) x = img.width - x;
if (y >= img.height) y = img.height - y;
return img.Pixel(x,y);
}
struct Mirror {
static inline PixFmt &get(BaseImage<PixFmt> &img, int x, int y)
{
while (x < 0) x += img.width*2;
while (y < 0) y += img.height*2;
while (x >= img.width*2) x -= img.width*2;
while (y >= img.height*2) y -= img.height*2;
if (x >= img.width) x = img.width - x;
if (y >= img.height) y = img.height - y;
return img.Pixel(x,y);
}
};
}
// FIXME: this is completely broken, the compiler won't accept it
// when instantiated with one of the EdgeCondition functions for EdgeCond
template<class PixFmt, class EdgeCond>
template<class PixFmt, typename EdgeCond>
inline PixFmt GetPixelBilinear(BaseImage<PixFmt> &img, double x, double y)
{
PixFmt res;
double xpct = x - floor(x), ypct = y - floor(y);
const PixFmt &src11 = EdgeCond(img, (int)x, (int)y);
const PixFmt &src12 = EdgeCond(img, (int)x, 1+(int)y);
const PixFmt &src21 = EdgeCond(img, 1+(int)x, (int)y);
const PixFmt &src22 = EdgeCond(img, 1+(int)x, 1+(int)y);
const PixFmt &src11 = EdgeCond::get(img, (int)x, (int)y);
const PixFmt &src12 = EdgeCond::get(img, (int)x, 1+(int)y);
const PixFmt &src21 = EdgeCond::get(img, 1+(int)x, (int)y);
const PixFmt &src22 = EdgeCond::get(img, 1+(int)x, 1+(int)y);
res.R() += (1-xpct) * (1-ypct) * src11.R() + (1-xpct) * ypct * src12.R() + xpct * (1-ypct) * src21.R() + xpct * ypct * src22.R();
res.G() += (1-xpct) * (1-ypct) * src11.G() + (1-xpct) * ypct * src12.G() + xpct * (1-ypct) * src21.G() + xpct * ypct * src22.G();
res.B() += (1-xpct) * (1-ypct) * src11.B() + (1-xpct) * ypct * src12.B() + xpct * (1-ypct) * src21.B() + xpct * ypct * src22.B();
res.A() += (1-xpct) * (1-ypct) * src11.A() + (1-xpct) * ypct * src12.A() + xpct * (1-ypct) * src21.A() + xpct * ypct * src22.A();
res.R() = (1-xpct) * (1-ypct) * src11.R() + (1-xpct) * ypct * src12.R() + xpct * (1-ypct) * src21.R() + xpct * ypct * src22.R();
res.G() = (1-xpct) * (1-ypct) * src11.G() + (1-xpct) * ypct * src12.G() + xpct * (1-ypct) * src21.G() + xpct * ypct * src22.G();
res.B() = (1-xpct) * (1-ypct) * src11.B() + (1-xpct) * ypct * src12.B() + xpct * (1-ypct) * src21.B() + xpct * ypct * src22.B();
res.A() = (1-xpct) * (1-ypct) * src11.A() + (1-xpct) * ypct * src12.A() + xpct * (1-ypct) * src21.A() + xpct * ypct * src22.A();
return res;
}

View file

@ -429,8 +429,8 @@ struct DirectionalBlurFilter {
{
int a = 0;
for (int t = -gk.width/2, i = 0; i < gk.width; t++, i++) {
//PixelFormat::A8 &srcpx = GetPixelBilinear<PixelFormat::A8, EdgeCondition::repeat>(src, x+xstep*t, y+ystep*t);
PixelFormat::A8 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
PixelFormat::A8 &srcpx = GetPixelBilinear<PixelFormat::A8, EdgeCondition::Repeat<PixelFormat::A8> >(src, x+xstep*t, y+ystep*t);
//PixelFormat::A8 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
a += srcpx.A() * gk.kernel[i];
}
PixelFormat::A8 res;
@ -442,8 +442,8 @@ struct DirectionalBlurFilter {
{
int r = 0, g = 0, b = 0;
for (int t = -gk.width/2, i = 0; i < gk.width; t++, i++) {
//PixelFormat::cairo_rgb24 &srcpx = GetPixelBilinear<PixelFormat::cairo_rgb24, EdgeCondition::repeat>(src, x+xstep*t, y+ystep*t);
PixelFormat::cairo_rgb24 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
PixelFormat::cairo_rgb24 &srcpx = GetPixelBilinear<PixelFormat::cairo_rgb24, EdgeCondition::Repeat<PixelFormat::cairo_rgb24> >(src, x+xstep*t, y+ystep*t);
//PixelFormat::cairo_rgb24 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
r += srcpx.R() * gk.kernel[i];
g += srcpx.G() * gk.kernel[i];
b += srcpx.B() * gk.kernel[i];
@ -461,8 +461,8 @@ struct DirectionalBlurFilter {
{
int a = 0, r = 0, g = 0, b = 0;
for (int t = -gk.width/2, i = 0; i < gk.width; t++, i++) {
//PixelFormat::cairo_argb32 &srcpx = GetPixelBilinear<PixelFormat::cairo_argb32, EdgeCondition::repeat>(src, x+xstep*t, y+ystep*t);
PixelFormat::cairo_argb32 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
PixelFormat::cairo_argb32 &srcpx = GetPixelBilinear<PixelFormat::cairo_argb32, EdgeCondition::Repeat<PixelFormat::cairo_argb32> >(src, x+xstep*t, y+ystep*t);
//PixelFormat::cairo_argb32 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
a += srcpx.A() * gk.kernel[i];
r += srcpx.R() * gk.kernel[i];
g += srcpx.G() * gk.kernel[i];
@ -510,8 +510,8 @@ struct RadialBlurFilter {
int divisor = 0;
int a = 0;
for (int t = 0, i = gk.width/2; i < gk.width; t++, i++) {
//PixelFormat::A8 &srcpx = GetPixelBilinear<PixelFormat::A8, EdgeCondition::repeat>(src, x+xstep*t, y+ystep*t);
PixelFormat::A8 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
PixelFormat::A8 &srcpx = GetPixelBilinear<PixelFormat::A8, EdgeCondition::Repeat<PixelFormat::A8> >(src, x+xstep*t, y+ystep*t);
//PixelFormat::A8 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
a += srcpx.A() * gk.kernel[i];
divisor += gk.kernel[i];
}
@ -528,8 +528,8 @@ struct RadialBlurFilter {
int divisor = 0;
int r = 0, g = 0, b = 0;
for (int t = 0, i = gk.width/2; i < gk.width; t++, i++) {
//PixelFormat::A8 &srcpx = GetPixelBilinear<PixelFormat::A8, EdgeCondition::repeat>(src, x+xstep*t, y+ystep*t);
PixelFormat::cairo_rgb24 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
PixelFormat::cairo_rgb24 &srcpx = GetPixelBilinear<PixelFormat::cairo_rgb24, EdgeCondition::Repeat<PixelFormat::cairo_rgb24> >(src, x+xstep*t, y+ystep*t);
//PixelFormat::cairo_rgb24 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
r += srcpx.R() * gk.kernel[i];
g += srcpx.G() * gk.kernel[i];
b += srcpx.B() * gk.kernel[i];
@ -552,8 +552,8 @@ struct RadialBlurFilter {
int divisor = 0;
int a = 0, r = 0, g = 0, b = 0;
for (int t = 0, i = gk.width/2; i < gk.width; t++, i++) {
//PixelFormat::A8 &srcpx = GetPixelBilinear<PixelFormat::A8, EdgeCondition::repeat>(src, x+xstep*t, y+ystep*t);
PixelFormat::cairo_argb32 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
PixelFormat::cairo_argb32 &srcpx = GetPixelBilinear<PixelFormat::cairo_argb32, EdgeCondition::Repeat<PixelFormat::cairo_argb32> >(src, x+xstep*t, y+ystep*t);
//PixelFormat::cairo_argb32 &srcpx = EdgeCondition::repeat(src, (int)(x+xstep*t), (int)(y+ystep*t));
a += srcpx.A() * gk.kernel[i];
r += srcpx.R() * gk.kernel[i];
g += srcpx.G() * gk.kernel[i];