lmtgraphicsmagick.c /size: 6220 b    last modification: 2024-01-16 10:22
1/*
2    See license.txt in the root of this project.
3*/
4
5/* For now just a simple conversion, like in the example module. */
6
7# include "luametatex.h"
8# include "lmtoptional.h"
9
10typedef enum gmlib_NoiseType {
11    UniformNoise,
12    GaussianNoise,
13    MultiplicativeGaussianNoise,
14    ImpulseNoise,
15    LaplacianNoise,
16    PoissonNoise,
17    RandomNoise,
18    UndefinedNoise
19} gmlib_NoiseType;
20
21typedef struct gmlib_state_info {
22
23    int initialized;
24    int padding;
25
26    void (*gm_InitializeMagick) (
27     // void **argv
28        void *path
29    );
30
31    void (*gm_DestroyMagick) (
32        void
33    );
34
35    void * (*gm_NewMagickWand) (
36        void
37    );
38
39    void (*gm_DestroyMagickWand) (
40        void *wand
41    );
42
43    int (*gm_MagickReadImage) (
44        void       *wand,
45        const char *name
46    );
47
48    int (*gm_MagickWriteImage) (
49        void       *wand,
50        const char *name
51    );
52
53    int (*gm_MagickBlurImage) (
54        void         *wand,
55        const double  radius,
56        const double  sigma
57    );
58
59    int (*gm_MagickAddNoiseImage) (
60        void  *wand,
61        const  gmlib_NoiseType noise_type
62    );
63
64} gmlib_state_info;
65
66static gmlib_state_info gmlib_state = {
67
68    .initialized            = 0,
69    .padding                = 0,
70
71    .gm_InitializeMagick    = NULL,
72    .gm_DestroyMagick       = NULL,
73    .gm_NewMagickWand       = NULL,
74    .gm_DestroyMagickWand   = NULL,
75    .gm_MagickReadImage     = NULL,
76    .gm_MagickWriteImage    = NULL,
77
78    .gm_MagickBlurImage     = NULL,
79    .gm_MagickAddNoiseImage = NULL,
80
81};
82
83static int gmlib_initialize(lua_State * L) // todo: table
84{
85    if (! gmlib_state.initialized) {
86        const char *filename1 = lua_tostring(L,1);
87        const char *filename2 = lua_tostring(L,2);
88        if (filename1) {
89
90            lmt_library lib = lmt_library_load(filename1);
91
92            gmlib_state.gm_InitializeMagick = lmt_library_find(lib, "InitializeMagick");
93            gmlib_state.gm_DestroyMagick    = lmt_library_find(lib, "DestroyMagick");
94
95            gmlib_state.initialized = lmt_library_okay(lib);
96        }
97        if (gmlib_state.initialized && filename2) {
98
99            lmt_library lib = lmt_library_load(filename2);
100
101            gmlib_state.gm_NewMagickWand       = lmt_library_find(lib, "NewMagickWand");
102            gmlib_state.gm_DestroyMagickWand   = lmt_library_find(lib, "DestroyMagickWand");
103            gmlib_state.gm_MagickReadImage     = lmt_library_find(lib, "MagickReadImage");
104            gmlib_state.gm_MagickWriteImage    = lmt_library_find(lib, "MagickWriteImage");
105
106            gmlib_state.gm_MagickBlurImage     = lmt_library_find(lib, "MagickBlurImage");
107            gmlib_state.gm_MagickAddNoiseImage = lmt_library_find(lib, "MagickAddNoiseImage");
108
109            gmlib_state.initialized = lmt_library_okay(lib);
110        }
111    }
112    lua_pushboolean(L, gmlib_state.initialized);
113    return 1;
114}
115
116/* We could have a callback for stdout and error. */
117
118/* Somehow not in gm: (void) MagickImageCommand(image_info, arg_count, args, NULL, exception); */
119
120static int gmlib_execute(lua_State * L)
121{
122    if (gmlib_state.initialized) {
123        if (gmlib_state.initialized == 1) {
124            /* Once per run. */
125            gmlib_state.gm_InitializeMagick(NULL);
126            gmlib_state.initialized = 2;
127        }
128        if (lua_type(L, 1) == LUA_TTABLE) {
129            void        *wand    = NULL;
130            const char  *inpname = NULL;
131            const char  *outname = NULL;
132            lua_getfield(L, -1, "inputfile" ); inpname = luaL_optstring(L, -1, NULL); lua_pop(L, 1);
133            lua_getfield(L, -1, "outputfile"); outname = luaL_optstring(L, -1, NULL); lua_pop(L, 1);
134         /* gmlib_state.gm_InitializeMagick(NULL); */
135            wand = gmlib_state.gm_NewMagickWand();
136            if (wand) {
137                int state = gmlib_state.gm_MagickReadImage(wand, inpname);  /* todo: check return status */
138                if (state) {
139                    /* fun stuff */
140                    if (lua_getfield(L, -1, "blur" ) == LUA_TTABLE) {
141                        lua_getfield(L, -1, "radius");
142                        lua_getfield(L, -2, "sigma");
143                        gmlib_state.gm_MagickBlurImage(wand, lua_tonumber(L, -2), lua_tonumber(L, -1));
144                        lua_pop(L, 3);
145                    } else {
146                        lua_pop(L, 1);
147                    }
148                    if (lua_getfield(L, -1, "noise" ) == LUA_TTABLE) {
149                        lua_getfield(L, -1, "type");
150                        gmlib_state.gm_MagickAddNoiseImage(wand, lmt_tointeger(L, -1));
151                        lua_pop(L, 2);
152                    } else {
153                        lua_pop(L, 1);
154                    }
155                    /* done */
156                    state = gmlib_state.gm_MagickWriteImage(wand, outname); /* todo: check return status */
157                    gmlib_state.gm_DestroyMagickWand(wand);
158                    if (state) {
159                        lua_pushboolean(L, 1);
160                        return 1;
161                    } else {
162                        lua_pushboolean(L, 0);
163                        lua_pushliteral(L, "possible write error");
164                        return 2;
165                    }
166                } else {
167                    gmlib_state.gm_DestroyMagickWand(wand);
168                    lua_pushboolean(L, 0);
169                    lua_pushliteral(L, "possible read error");
170                    return 2;
171                }
172            } else {
173                lua_pushboolean(L, 0);
174                lua_pushliteral(L, "possible memory issue");
175                return 2;
176            }
177         /* gmlib_state.gm_DestroyMagick(); */
178        } else {
179            lua_pushboolean(L, 0);
180            lua_pushliteral(L, "invalid specification");
181            return 2;
182        }
183    }
184    lua_pushboolean(L, 0);
185    lua_pushliteral(L, "not initialized");
186    return 2;
187}
188
189static struct luaL_Reg gmlib_function_list[] = {
190    { "initialize", gmlib_initialize },
191    { "execute",    gmlib_execute    },
192    { NULL,         NULL             },
193};
194
195int luaopen_graphicsmagick(lua_State * L)
196{
197    lmt_library_register(L, "graphicsmagick", gmlib_function_list);
198    return 0;
199}
200