diff --git a/OverLua/docs/overlua.txt b/OverLua/docs/overlua.txt index 6d7e51f92..95de7fa05 100644 --- a/OverLua/docs/overlua.txt +++ b/OverLua/docs/overlua.txt @@ -161,6 +161,22 @@ For RGB24 surfaces, all channels are inverted. For A8 and A1 surfaces the alpha is inverted. +raster.separable_filter(surface, filter, divisor) + +Apply a custom separable filter over the image. + +The filter must be a table of integers. After the convoluted value of each +pixel is calculated, it is divided by divisor before it's stored back to the +image. + +Note that this function can only work on integers, floating point values in +the filter or divisor will be rounded first. To get higher precision, scale +up the filter and divisor. (Treat it as fixed-point math.) + +The filter is one-dimensional, but is applied first horizontally and then +vertically ovre the image to get the final image. + + More filtering functions are planned, though no specifics yet. Wishes/suggestions are welcome, and so are patches to add more functions. diff --git a/OverLua/docs/test3.lua b/OverLua/docs/test3.lua index e3bc15f06..f0197487a 100644 --- a/OverLua/docs/test3.lua +++ b/OverLua/docs/test3.lua @@ -1,6 +1,7 @@ function render_frame(f, t) local surf = f.create_cairo_surface() - raster.gaussian_blur(surf, t)--1+(1-math.cos(t*10))*2) - raster.invert(surf) + --raster.gaussian_blur(surf, t)--1+(1-math.cos(t*10))*2) + --raster.invert(surf) + raster.separable_filter(surf, {-1, 3, -1}, 1) f.overlay_cairo_surface(surf, 0, 0) end diff --git a/OverLua/raster_ops.cpp b/OverLua/raster_ops.cpp index c049efc55..7a841a15f 100644 --- a/OverLua/raster_ops.cpp +++ b/OverLua/raster_ops.cpp @@ -408,10 +408,44 @@ static int invert_image(lua_State *L) } +static int separable_filter(lua_State *L) +{ + cairo_surface_t *surf = CheckSurface(L, 1); + if (!lua_istable(L, 2)) { + luaL_error(L, "Expected table as second argument to raster.separable_filter, got %s", luaL_typename(L, 2)); + return 0; + } + int divisor = luaL_checkint(L, 3); + + int width = (int)lua_objlen(L, 2); + if (width < 1) { + luaL_error(L, "Cannot apply empty filter"); + return 0; + } + int *kernel = new int[width]; + int i = 0; + lua_pushnil(L); + while (lua_next(L, 2)) { + if (lua_isnumber(L, -1)) { + kernel[i] = (int)lua_tointeger(L, -1); + } + i++; + lua_pop(L, 1); + } + + ApplySeparableFilter(L, surf, kernel, width, divisor); + + delete[] kernel; + + return 0; +} + + // Registration static luaL_Reg rasterlib[] = { {"gaussian_blur", gaussian_blur}, {"box_blur", box_blur}, + {"separable_filter", separable_filter}, {"invert", invert_image}, {NULL, NULL} };