I can has radial blur! *wheeee*

Originally committed to SVN as r1490.
This commit is contained in:
Niels Martin Hansen 2007-08-15 01:08:31 +00:00
parent e99d9800c0
commit 4ddc7d5820
4 changed files with 105 additions and 4 deletions

View file

@ -157,6 +157,11 @@ Apply a variable strength directional gaussian kernel blur to the image.
Also known as motion blur. The angle is given in radians. Also known as motion blur. The angle is given in radians.
raster.radial_blur(surface, cx, cy, sigma)
Apply a variable strength radial gaussian blur centered on pixel (cx,cy).
raster.invert(surface) raster.invert(surface)
Invert the colour in the given surface. Invert the colour in the given surface.

View file

@ -36,7 +36,7 @@ function render_frame(f, t)
ctx.text_path("OverLua") ctx.text_path("OverLua")
ctx.fill() ctx.fill()
raster.gaussian_blur(surf, (1-math.cos(t*10))*2) raster.directional_blur(surf, t, 5)
f.overlay_cairo_surface(surf, 200, 50) f.overlay_cairo_surface(surf, 200, 50)
end end

View file

@ -3,6 +3,7 @@ function render_frame(f, t)
--raster.gaussian_blur(surf, t)--1+(1-math.cos(t*10))*2) --raster.gaussian_blur(surf, t)--1+(1-math.cos(t*10))*2)
--raster.invert(surf) --raster.invert(surf)
--raster.separable_filter(surf, {-1, 3, -1}, 1) --raster.separable_filter(surf, {-1, 3, -1}, 1)
raster.directional_blur(surf, t, t/10) --raster.directional_blur(surf, t, t/10)
raster.radial_blur(surf, 200, 200, t/60)
f.overlay_cairo_surface(surf, 0, 0) f.overlay_cairo_surface(surf, 0, 0)
end end

View file

@ -477,7 +477,8 @@ struct DirectionalBlurFilter {
res.G() = g; res.G() = g;
res.B() = b; res.B() = b;
return res; return res;
}}; }
};
static int directional_blur(lua_State *L) static int directional_blur(lua_State *L)
@ -493,6 +494,99 @@ static int directional_blur(lua_State *L)
} }
struct RadialBlurFilter {
GaussianKernel gk;
int cx, cy;
RadialBlurFilter(int x, int y, double sigma) :
gk(sigma), cx(x), cy(y)
{
}
inline PixelFormat::A8 a8(BaseImage<PixelFormat::A8> &src, int x, int y)
{
if (x == cx && y == cy) return src.Pixel(x, y);
double xstep = x-cx, ystep = y-cy, ivlen = 1/sqrt(xstep*xstep+ystep*ystep);
xstep *= ivlen; ystep *= ivlen;
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));
a += srcpx.A() * gk.kernel[i];
divisor += gk.kernel[i];
}
PixelFormat::A8 res;
a = a / divisor; if (a < 0) a = 0; if (a > 255) a = 255;
res.A() = a;
return res;
}
inline PixelFormat::cairo_rgb24 rgb24(BaseImage<PixelFormat::cairo_rgb24> &src, int x, int y)
{
if (x == cx && y == cy) return src.Pixel(x, y);
double xstep = x-cx, ystep = y-cy, ivlen = 1/sqrt(xstep*xstep+ystep*ystep);
xstep *= ivlen; ystep *= ivlen;
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));
r += srcpx.R() * gk.kernel[i];
g += srcpx.G() * gk.kernel[i];
b += srcpx.B() * gk.kernel[i];
divisor += gk.kernel[i];
}
PixelFormat::cairo_rgb24 res;
r = r / divisor; if (r < 0) r = 0; if (r > 255) r = 255;
g = g / divisor; if (g < 0) g = 0; if (g > 255) g = 255;
b = b / divisor; if (b < 0) b = 0; if (b > 255) b = 255;
res.R() = r;
res.G() = g;
res.B() = b;
return res;
}
inline PixelFormat::cairo_argb32 argb32(BaseImage<PixelFormat::cairo_argb32> &src, int x, int y)
{
if (x == cx && y == cy) return src.Pixel(x, y);
double xstep = x-cx, ystep = y-cy, ivlen = 1/sqrt(xstep*xstep+ystep*ystep);
xstep *= ivlen; ystep *= ivlen;
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));
a += srcpx.A() * gk.kernel[i];
r += srcpx.R() * gk.kernel[i];
g += srcpx.G() * gk.kernel[i];
b += srcpx.B() * gk.kernel[i];
divisor += gk.kernel[i];
}
PixelFormat::cairo_argb32 res;
a = a / divisor; if (a < 0) a = 0; if (a > 255) a = 255;
r = r / divisor; if (r < 0) r = 0; if (r > 255) r = 255;
g = g / divisor; if (g < 0) g = 0; if (g > 255) g = 255;
b = b / divisor; if (b < 0) b = 0; if (b > 255) b = 255;
res.A() = a;
res.R() = r;
res.G() = g;
res.B() = b;
return res;
}
};
static int radial_blur(lua_State *L)
{
cairo_surface_t *surf = CheckSurface(L, 1);
int x = luaL_checkint(L, 2);
int y = luaL_checkint(L, 3);
double sigma = luaL_checknumber(L, 4);
RadialBlurFilter filter(x, y, sigma);
ApplyGeneralFilter(L, surf, filter);
return 0;
}
static int invert_image(lua_State *L) static int invert_image(lua_State *L)
{ {
cairo_surface_t *surf = CheckSurface(L, 1); cairo_surface_t *surf = CheckSurface(L, 1);
@ -595,7 +689,8 @@ static int separable_filter(lua_State *L)
// Registration // Registration
static luaL_Reg rasterlib[] = { static luaL_Reg rasterlib[] = {
{"gaussian_blur", gaussian_blur}, {"box_blur", box_blur}, {"directional_blur", directional_blur}, {"gaussian_blur", gaussian_blur}, {"box_blur", box_blur},
{"directional_blur", directional_blur}, {"radial_blur", radial_blur},
{"separable_filter", separable_filter}, {"separable_filter", separable_filter},
{"invert", invert_image}, {"invert", invert_image},
{NULL, NULL} {NULL, NULL}