diff --git a/OverLua/docs/expression-evaluator.txt b/OverLua/docs/expression-evaluator.txt index 1036aaf50..142d43edb 100644 --- a/OverLua/docs/expression-evaluator.txt +++ b/OverLua/docs/expression-evaluator.txt @@ -224,3 +224,9 @@ Create a field of random gray-values. "0 =R 1 G - =G" Zero out the red channel and invert the green channel. + + +For raster.pixel_coord_map: + +"X .5 rand - + =X Y .5 rand - + =Y" +Create some jitter in the pixels. diff --git a/OverLua/docs/overlua.txt b/OverLua/docs/overlua.txt index d3492043c..fcf4b2df1 100644 --- a/OverLua/docs/overlua.txt +++ b/OverLua/docs/overlua.txt @@ -207,6 +207,23 @@ The following new registers are made available to the expression evaluator: Y Y-coordinate of pixel being processed. Input only. +raster.pixel_coord_map(surface, expression) + +Map each pixel coordinate pair to a new coordinate pair in the surface. Only +works for ARGB32 and RGB24 surfaces. + +The expression is an RPN expression in the OverLua Expression Evaluator +language, see expression-evaluator.txt for details. + +No additional functions are made available to the expression evaluator by +this function. + +The following new registers are made available to the expression evaluator: + X Absolute pixel X coordinate. Input and output. The output may be + non-integer, in that case bilinear interpolation is used. + Y Ditto, for Y coordinate. + + 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 1a53015fe..1a0ce61b6 100644 --- a/OverLua/docs/test3.lua +++ b/OverLua/docs/test3.lua @@ -4,11 +4,12 @@ function render_frame(f, t) --raster.invert(surf) --raster.separable_filter(surf, {-1, 3, -1}, 1) --raster.directional_blur(surf, t, t/10) - raster.radial_blur(surf, 200, 200, t/60) - raster.pixel_value_map(surf, "0 =R 1 G - =G") + --raster.radial_blur(surf, 200, 200, t/60) + raster.pixel_value_map(surf, "G rand 0.1 * + =G G 1 - 1 G ifgtz =G") + raster.pixel_coord_map(surf, "X .5 rand - + =X Y .5 rand - + =Y") f.overlay_cairo_surface(surf, 0, 0) - surf = cairo.image_surface_create(200, 200, "rgb24") - raster.pixel_value_map(surf, "rand =t0 t0 =R t0 =G t0 =B") - f.overlay_cairo_surface(surf, 20, 20) + --surf = cairo.image_surface_create(200, 200, "rgb24") + --raster.pixel_value_map(surf, "rand =t0 t0 =R t0 =G t0 =B") + --f.overlay_cairo_surface(surf, 20, 20) end diff --git a/OverLua/raster_ops.cpp b/OverLua/raster_ops.cpp index cae633416..e340b890a 100644 --- a/OverLua/raster_ops.cpp +++ b/OverLua/raster_ops.cpp @@ -763,6 +763,73 @@ static int pixel_value_map(lua_State *L) } +static int pixel_coord_map(lua_State *L) +{ + cairo_surface_t *surf = CheckSurface(L, 1); + const char *program = luaL_checkstring(L, 2); + + // Set up engine specs + ExpressionEngine::Specification spec; + spec.registers.resize(2); + spec.registers[0] = "X"; + spec.registers[1] = "Y"; + + // Compile program + ExpressionEngine::Machine machine; + try { + machine = ExpressionEngine::Machine(spec, program); + } + catch (const char *e) { + // This is a parse error + luaL_error(L, "Error in expression program near\"%s\"", e); + } + + // Init image + cairo_surface_flush(surf); + int width = cairo_image_surface_get_width(surf); + int height = cairo_image_surface_get_height(surf); + ptrdiff_t stride = (ptrdiff_t)cairo_image_surface_get_stride(surf); + unsigned char *data = cairo_image_surface_get_data(surf); + cairo_format_t format = cairo_image_surface_get_format(surf); + + unsigned char *work = new unsigned char[height * stride]; + memcpy(work, data, height*stride); + + if (format == CAIRO_FORMAT_ARGB32) { + BaseImage simg(width, height, stride, work); + BaseImage dimg(width, height, stride, data); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + machine.registers[0] = x; + machine.registers[1] = y; + machine.Run(); + dimg.Pixel(x, y) = GetPixelBilinear >(simg, machine.registers[0], machine.registers[1]); + } + } + } + else if (format == CAIRO_FORMAT_RGB24) { + BaseImage simg(width, height, stride, work); + BaseImage dimg(width, height, stride, data); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + machine.registers[0] = x; + machine.registers[1] = y; + machine.Run(); + dimg.Pixel(x, y) = GetPixelBilinear >(simg, machine.registers[0], machine.registers[1]); + } + } + } + else { + luaL_error(L, "Unsupported pixel format"); + } + + delete[] work; + cairo_surface_mark_dirty(surf); + + return 0; +} + + // Registration static luaL_Reg rasterlib[] = { @@ -770,7 +837,7 @@ static luaL_Reg rasterlib[] = { {"directional_blur", directional_blur}, {"radial_blur", radial_blur}, {"separable_filter", separable_filter}, {"invert", invert_image}, - {"pixel_value_map", pixel_value_map}, + {"pixel_value_map", pixel_value_map}, {"pixel_coord_map", pixel_coord_map}, {NULL, NULL} };