|
30 | 30 | #include <omp.h>
|
31 | 31 | #include <stdint.h>
|
32 | 32 |
|
| 33 | +#include "expression_engine.h" |
33 | 34 | #include "raster_ops.h"
|
34 | 35 | #include "../lua51/src/lauxlib.h"
|
35 | 36 |
|
@@ -686,13 +687,90 @@ static int separable_filter(lua_State *L)
|
686 | 687 | }
|
687 | 688 |
|
688 | 689 |
|
| 690 | +static int pixel_value_map(lua_State *L) |
| 691 | +{ |
| 692 | + cairo_surface_t *surf = CheckSurface(L, 1); |
| 693 | + const char *program = luaL_checkstring(L, 2); |
| 694 | + |
| 695 | + // Set up engine specs |
| 696 | + ExpressionEngine::Specification spec; |
| 697 | + spec.registers.resize(5); |
| 698 | + spec.registers[0] = "R"; |
| 699 | + spec.registers[1] = "G"; |
| 700 | + spec.registers[2] = "B"; |
| 701 | + spec.registers[3] = "X"; |
| 702 | + spec.registers[4] = "Y"; |
| 703 | + |
| 704 | + // Compile program |
| 705 | + ExpressionEngine::Machine machine; |
| 706 | + try { |
| 707 | + machine = ExpressionEngine::Machine(spec, program); |
| 708 | + } |
| 709 | + catch (const char *e) { |
| 710 | + // This is a parse error |
| 711 | + luaL_error(L, "Error in expression program near\"%s\"", e); |
| 712 | + } |
| 713 | + |
| 714 | + // Init image |
| 715 | + cairo_surface_flush(surf); |
| 716 | + int width = cairo_image_surface_get_width(surf); |
| 717 | + int height = cairo_image_surface_get_height(surf); |
| 718 | + ptrdiff_t stride = (ptrdiff_t)cairo_image_surface_get_stride(surf); |
| 719 | + unsigned char *data = cairo_image_surface_get_data(surf); |
| 720 | + cairo_format_t format = cairo_image_surface_get_format(surf); |
| 721 | + |
| 722 | + if (format == CAIRO_FORMAT_ARGB32) { |
| 723 | + BaseImage<PixelFormat::cairo_argb32> img(width, height, stride, data); |
| 724 | + for (int y = 0; y < height; y++) { |
| 725 | + for (int x = 0; x < width; x++) { |
| 726 | + PixelFormat::cairo_argb32 &p = img.Pixel(x, y); |
| 727 | + machine.registers[0] = (double)p.R() / 255.0; |
| 728 | + machine.registers[1] = (double)p.G() / 255.0; |
| 729 | + machine.registers[2] = (double)p.B() / 255.0; |
| 730 | + machine.registers[3] = x; |
| 731 | + machine.registers[4] = y; |
| 732 | + machine.Run(); |
| 733 | + p.R() = (uint8_t)(machine.registers[0] * 255); |
| 734 | + p.G() = (uint8_t)(machine.registers[1] * 255); |
| 735 | + p.B() = (uint8_t)(machine.registers[2] * 255); |
| 736 | + } |
| 737 | + } |
| 738 | + } |
| 739 | + else if (format == CAIRO_FORMAT_RGB24) { |
| 740 | + BaseImage<PixelFormat::cairo_rgb24> img(width, height, stride, data); |
| 741 | + for (int y = 0; y < height; y++) { |
| 742 | + for (int x = 0; x < width; x++) { |
| 743 | + PixelFormat::cairo_rgb24 &p = img.Pixel(x, y); |
| 744 | + machine.registers[0] = (double)p.R() / 255.0; |
| 745 | + machine.registers[1] = (double)p.G() / 255.0; |
| 746 | + machine.registers[2] = (double)p.B() / 255.0; |
| 747 | + machine.registers[3] = x; |
| 748 | + machine.registers[4] = y; |
| 749 | + machine.Run(); |
| 750 | + p.R() = (uint8_t)(machine.registers[0] * 255); |
| 751 | + p.G() = (uint8_t)(machine.registers[1] * 255); |
| 752 | + p.B() = (uint8_t)(machine.registers[2] * 255); |
| 753 | + } |
| 754 | + } |
| 755 | + } |
| 756 | + else { |
| 757 | + luaL_error(L, "Unsupported pixel format"); |
| 758 | + } |
| 759 | + |
| 760 | + cairo_surface_mark_dirty(surf); |
| 761 | + |
| 762 | + return 0; |
| 763 | +} |
| 764 | + |
| 765 | + |
689 | 766 | // Registration
|
690 | 767 |
|
691 | 768 | static luaL_Reg rasterlib[] = {
|
692 | 769 | {"gaussian_blur", gaussian_blur}, {"box_blur", box_blur},
|
693 | 770 | {"directional_blur", directional_blur}, {"radial_blur", radial_blur},
|
694 | 771 | {"separable_filter", separable_filter},
|
695 | 772 | {"invert", invert_image},
|
| 773 | + {"pixel_value_map", pixel_value_map}, |
696 | 774 | {NULL, NULL}
|
697 | 775 | };
|
698 | 776 |
|
|
0 commit comments