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 // Access pixels with various edge conditions
namespace EdgeCondition { namespace EdgeCondition {
template<class PixFmt> template<class PixFmt>
inline PixFmt &blackness(BaseImage<PixFmt> &img, int x, int y) 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 if (x < 0 || y < 0 || x >= img.width || x >= img.height) {
} else { 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); return img.Pixel(x,y);
} }
} };
template<class PixFmt> template<class PixFmt>
inline PixFmt &closest(BaseImage<PixFmt> &img, int x, int y) struct Repeat {
{ static inline PixFmt &get(BaseImage<PixFmt> &img, int x, int y)
if (x < 0) x = 0; {
if (y < 0) y = 0; while (x < 0) x += img.width;
if (x >= img.width) x = img.width-1; while (y < 0) y += img.height;
if (y >= img.height) y = img.height - 1; while (x >= img.width) x -= img.width;
return img.Pixel(x,y); while (y >= img.height) y -= img.height;
} return img.Pixel(x,y);
}
};
template<class PixFmt> template<class PixFmt>
inline PixFmt &repeat(BaseImage<PixFmt> &img, int x, int y) struct Mirror {
{ 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 < 0) x += img.width*2;
while (x >= img.width) x -= img.width; while (y < 0) y += img.height*2;
while (y >= img.height) y -= img.height; while (x >= img.width*2) x -= img.width*2;
return img.Pixel(x,y); 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;
template<class PixFmt> return img.Pixel(x,y);
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);
}
} }
// FIXME: this is completely broken, the compiler won't accept it // FIXME: this is completely broken, the compiler won't accept it
// when instantiated with one of the EdgeCondition functions for EdgeCond // 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) inline PixFmt GetPixelBilinear(BaseImage<PixFmt> &img, double x, double y)
{ {
PixFmt res; PixFmt res;
double xpct = x - floor(x), ypct = y - floor(y); double xpct = x - floor(x), ypct = y - floor(y);
const PixFmt &src11 = EdgeCond(img, (int)x, (int)y); const PixFmt &src11 = EdgeCond::get(img, (int)x, (int)y);
const PixFmt &src12 = EdgeCond(img, (int)x, 1+(int)y); const PixFmt &src12 = EdgeCond::get(img, (int)x, 1+(int)y);
const PixFmt &src21 = EdgeCond(img, 1+(int)x, (int)y); const PixFmt &src21 = EdgeCond::get(img, 1+(int)x, (int)y);
const PixFmt &src22 = EdgeCond(img, 1+(int)x, 1+(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.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.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.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.A() = (1-xpct) * (1-ypct) * src11.A() + (1-xpct) * ypct * src12.A() + xpct * (1-ypct) * src21.A() + xpct * ypct * src22.A();
return res; return res;
} }

View file

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