Implement raster.pixel_value_map function using expression evaluator. Seems to work correct.

Originally committed to SVN as r1507.
This commit is contained in:
Niels Martin Hansen 2007-08-17 23:56:20 +00:00
parent 3b5e953c70
commit a460743682
5 changed files with 112 additions and 1 deletions

View file

@ -217,4 +217,10 @@ else return the third argument.
Sample programs Sample programs
--------------- ---------------
To be written. No functions in OverLua use the expression evaluator yet. For raster.pixel_value_map:
"rand =t0 t0 =R t0 =G t0 =B"
Create a field of random gray-values.
"0 =R 1 G - =G"
Zero out the red channel and invert the green channel.

View file

@ -188,6 +188,25 @@ The filter is one-dimensional, but is applied first horizontally and then
vertically ovre the image to get the final image. vertically ovre the image to get the final image.
raster.pixel_value_map(surface, expression)
Map an expression over every pixel RGB value 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:
R In range 0..1, red component. Input and output.
G Ditto, for green component.
B Ditto, for blue component.
X X-coordinate of pixel being processed. Input only.
Y Y-coordinate of pixel being processed. Input only.
More filtering functions are planned, though no specifics yet. More filtering functions are planned, though no specifics yet.
Wishes/suggestions are welcome, and so are patches to add more functions. Wishes/suggestions are welcome, and so are patches to add more functions.

View file

@ -5,5 +5,10 @@ function render_frame(f, t)
--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) raster.radial_blur(surf, 200, 200, t/60)
raster.pixel_value_map(surf, "0 =R 1 G - =G")
f.overlay_cairo_surface(surf, 0, 0) 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)
end end

View file

@ -105,6 +105,9 @@ namespace ExpressionEngine {
// Create a machine from a specification and a program source // Create a machine from a specification and a program source
Machine(const Specification &spec, const char *source); Machine(const Specification &spec, const char *source);
// Create a blank machine
Machine() { }
}; };
}; };

View file

@ -30,6 +30,7 @@
#include <omp.h> #include <omp.h>
#include <stdint.h> #include <stdint.h>
#include "expression_engine.h"
#include "raster_ops.h" #include "raster_ops.h"
#include "../lua51/src/lauxlib.h" #include "../lua51/src/lauxlib.h"
@ -686,6 +687,82 @@ static int separable_filter(lua_State *L)
} }
static int pixel_value_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(5);
spec.registers[0] = "R";
spec.registers[1] = "G";
spec.registers[2] = "B";
spec.registers[3] = "X";
spec.registers[4] = "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);
if (format == CAIRO_FORMAT_ARGB32) {
BaseImage<PixelFormat::cairo_argb32> img(width, height, stride, data);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
PixelFormat::cairo_argb32 &p = img.Pixel(x, y);
machine.registers[0] = (double)p.R() / 255.0;
machine.registers[1] = (double)p.G() / 255.0;
machine.registers[2] = (double)p.B() / 255.0;
machine.registers[3] = x;
machine.registers[4] = y;
machine.Run();
p.R() = (uint8_t)(machine.registers[0] * 255);
p.G() = (uint8_t)(machine.registers[1] * 255);
p.B() = (uint8_t)(machine.registers[2] * 255);
}
}
}
else if (format == CAIRO_FORMAT_RGB24) {
BaseImage<PixelFormat::cairo_rgb24> img(width, height, stride, data);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
PixelFormat::cairo_rgb24 &p = img.Pixel(x, y);
machine.registers[0] = (double)p.R() / 255.0;
machine.registers[1] = (double)p.G() / 255.0;
machine.registers[2] = (double)p.B() / 255.0;
machine.registers[3] = x;
machine.registers[4] = y;
machine.Run();
p.R() = (uint8_t)(machine.registers[0] * 255);
p.G() = (uint8_t)(machine.registers[1] * 255);
p.B() = (uint8_t)(machine.registers[2] * 255);
}
}
}
else {
luaL_error(L, "Unsupported pixel format");
}
cairo_surface_mark_dirty(surf);
return 0;
}
// Registration // Registration
static luaL_Reg rasterlib[] = { static luaL_Reg rasterlib[] = {
@ -693,6 +770,7 @@ static luaL_Reg rasterlib[] = {
{"directional_blur", directional_blur}, {"radial_blur", radial_blur}, {"directional_blur", directional_blur}, {"radial_blur", radial_blur},
{"separable_filter", separable_filter}, {"separable_filter", separable_filter},
{"invert", invert_image}, {"invert", invert_image},
{"pixel_value_map", pixel_value_map},
{NULL, NULL} {NULL, NULL}
}; };