summaryrefslogtreecommitdiff
path: root/src/lua5/imlua_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua5/imlua_image.c')
-rw-r--r--src/lua5/imlua_image.c1061
1 files changed, 1061 insertions, 0 deletions
diff --git a/src/lua5/imlua_image.c b/src/lua5/imlua_image.c
new file mode 100644
index 0000000..22ed38c
--- /dev/null
+++ b/src/lua5/imlua_image.c
@@ -0,0 +1,1061 @@
+/** \file
+ * \brief IM Lua 5 Binding
+ *
+ * See Copyright Notice in im_lib.h
+ * $Id: imlua_image.c,v 1.1 2008/10/17 06:16:32 scuri Exp $
+ */
+
+#include <string.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#include "im.h"
+#include "im_image.h"
+#include "im_util.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "imlua.h"
+#include "imlua_image.h"
+#include "imlua_palette.h"
+#include "imlua_aux.h"
+
+
+static imImage** imlua_rawcheckimage(lua_State *L, int param)
+{
+ return (imImage**) luaL_checkudata(L, param, "imImage");
+}
+
+imImage* imlua_checkimage(lua_State *L, int param)
+{
+ imImage** image_p = imlua_rawcheckimage(L, param);
+
+ if (!(*image_p))
+ luaL_argerror(L, param, "destroyed imImage");
+
+ return *image_p;
+}
+
+int imlua_pushimageerror(lua_State *L, imImage* image, int error)
+{
+ if (error)
+ {
+ lua_pushnil(L);
+ imlua_pusherror(L, error);
+ return 2;
+ }
+ else
+ {
+ imlua_pushimage(L, image);
+ return 1;
+ }
+}
+
+void imlua_pushimage(lua_State *L, imImage* image)
+{
+ if (!image)
+ lua_pushnil(L);
+ else
+ {
+ imImage **image_p = (imImage**) lua_newuserdata(L, sizeof(imImage*));
+ *image_p = image;
+ luaL_getmetatable(L, "imImage");
+ lua_setmetatable(L, -2);
+ }
+}
+
+/*****************************************************************************\
+ image channel, for indexing
+\*****************************************************************************/
+static imluaImageChannel *imlua_newimagechannel (lua_State *L, imImage *image, int channel)
+{
+ imluaImageChannel* imagechannel = (imluaImageChannel*) lua_newuserdata(L, sizeof(imluaImageChannel));
+ imagechannel->image = image;
+ imagechannel->channel = channel;
+ luaL_getmetatable(L, "imImageChannel");
+ lua_setmetatable(L, -2);
+ return imagechannel;
+}
+
+static imluaImageChannel* imlua_checkimagechannel (lua_State *L, int param)
+{
+ return (imluaImageChannel*) luaL_checkudata(L, param, "imImageChannel");
+}
+
+/*****************************************************************************\
+ image row, for indexing
+\*****************************************************************************/
+static imluaImageRow *imlua_newimagerow (lua_State *L, imImage *image, int channel, int row)
+{
+ imluaImageRow* imagerow = (imluaImageRow*) lua_newuserdata(L, sizeof(imluaImageRow));
+ imagerow->image = image;
+ imagerow->channel = channel;
+ imagerow->row = row;
+ luaL_getmetatable(L, "imImageChannelRow");
+ lua_setmetatable(L, -2);
+ return imagerow;
+}
+
+static imluaImageRow* imlua_checkimagerow (lua_State *L, int param)
+{
+ return (imluaImageRow*) luaL_checkudata(L, param, "imImageChannelRow");
+}
+
+/*****************************************************************************\
+ im.ImageCreate(width, height, color_space, data_type)
+\*****************************************************************************/
+static int imluaImageCreate (lua_State *L)
+{
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+ int color_space = luaL_checkint(L, 3);
+ int data_type = luaL_checkint(L, 4);
+
+ imImage *image = imImageCreate(width, height, color_space, data_type);
+ imlua_pushimage(L, image);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:AddAlpha()
+\*****************************************************************************/
+static int imluaImageAddAlpha (lua_State *L)
+{
+ imImageAddAlpha(imlua_checkimage(L, 1));
+ return 0;
+}
+
+/*****************************************************************************\
+ image:Reshape()
+\*****************************************************************************/
+static int imluaImageReshape (lua_State *L)
+{
+ imImage* im = imlua_checkimage(L, 1);
+ int width = luaL_checkint(L, 2);
+ int height = luaL_checkint(L, 3);
+
+ imImageReshape(im, width, height);
+ return 0;
+}
+
+/*****************************************************************************\
+ image:Copy()
+\*****************************************************************************/
+static int imluaImageCopy (lua_State *L)
+{
+ imImage* src_image = imlua_checkimage(L, 1);
+ imImage* dst_image = imlua_checkimage(L, 2);
+
+ imlua_match(L, src_image, dst_image);
+ imImageCopy(src_image, dst_image);
+ return 0;
+}
+
+/*****************************************************************************\
+ image:CopyData()
+\*****************************************************************************/
+static int imluaImageCopyData (lua_State *L)
+{
+ imImage* src_image = imlua_checkimage(L, 1);
+ imImage* dst_image = imlua_checkimage(L, 2);
+
+ imlua_match(L, src_image, dst_image);
+ imImageCopyData(src_image, dst_image);
+ return 0;
+}
+
+/*****************************************************************************\
+ image:Duplicate()
+\*****************************************************************************/
+static int imluaImageDuplicate (lua_State *L)
+{
+ imImage* image = imlua_checkimage(L, 1);
+ imImage *new_image = imImageDuplicate(image);
+ imlua_pushimage(L, new_image);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:Clone()
+\*****************************************************************************/
+static int imluaImageClone (lua_State *L)
+{
+ imImage* image = imlua_checkimage(L, 1);
+ imImage *new_image = imImageClone(image);
+ imlua_pushimage(L, new_image);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:SetAttribute(attrib, data_type, count, data)
+\*****************************************************************************/
+static int imluaImageSetAttribute (lua_State *L)
+{
+ int i, count = 0;
+ void *data = NULL;
+
+ imImage* image = imlua_checkimage(L, 1);
+ const char *attrib = luaL_checkstring(L, 2);
+ int data_type = luaL_checkint(L, 3);
+
+ if (!lua_isnil(L, 4))
+ {
+ if (lua_isstring(L, 4) && data_type != IM_BYTE)
+ luaL_argerror(L, 4, "if value is string, then data type must be byte");
+ else
+ {
+ luaL_checktype(L, 4, LUA_TTABLE);
+ count = imlua_getn(L, 4);
+ data = malloc(imDataTypeSize(data_type) * count);
+ }
+
+ switch (data_type)
+ {
+ case IM_BYTE:
+ {
+ if (lua_isstring(L, 4))
+ {
+ const char* str = lua_tostring(L, 4);
+ count = strlen(str)+1;
+ data = malloc(imDataTypeSize(data_type) * count);
+ memcpy(data, str, count);
+ }
+ else
+ {
+ imbyte *data_byte = (imbyte*) data;
+ for (i = 0; i < count; i++)
+ {
+ lua_rawgeti(L, 4, i+1);
+ data_byte[i] = (imbyte)luaL_checkint(L, -1);
+ lua_pop(L, 1);
+ }
+ }
+ }
+ break;
+
+ case IM_USHORT:
+ {
+ imushort *data_ushort = (imushort*) data;
+ for (i = 0; i < count; i++)
+ {
+ lua_rawgeti(L, 4, i+1);
+ data_ushort[i] = (imushort)luaL_checkint(L, -1);
+ lua_pop(L, 1);
+ }
+ }
+ break;
+
+ case IM_INT:
+ {
+ int *data_int = (int*) data;
+ for (i = 0; i < count; i++)
+ {
+ lua_rawgeti(L, 4, i+1);
+ data_int[i] = luaL_checkint(L, -1);
+ lua_pop(L, 1);
+ }
+ }
+ break;
+
+ case IM_FLOAT:
+ {
+ float *data_float = (float*) data;
+ for (i = 0; i < count; i++)
+ {
+ lua_rawgeti(L, 4, i+1);
+ data_float[i] = (float) luaL_checknumber(L, -1);
+ lua_pop(L, 1);
+ }
+ }
+ break;
+
+ case IM_CFLOAT:
+ {
+ float *data_float = (float*) data;
+ for (i = 0; i < count; i++)
+ {
+ int two;
+ float *value = imlua_toarrayfloat(L, -1, &two, 1);
+ if (two != 2)
+ {
+ free(value);
+ luaL_argerror(L, 4, "invalid value");
+ }
+
+ data_float[i] = value[0];
+ data_float[i+1] = value[1];
+ free(value);
+ lua_pop(L, 1);
+ }
+ }
+ break;
+ }
+ }
+
+ imImageSetAttribute(image, attrib, data_type, count, data);
+ return 0;
+}
+
+/*****************************************************************************\
+ image:GetAttribute(attrib)
+\*****************************************************************************/
+static int imluaImageGetAttribute (lua_State *L)
+{
+ int data_type;
+ int i, count;
+ const void *data;
+ int as_string = 0;
+
+ imImage* image = imlua_checkimage(L, 1);
+ const char *attrib = luaL_checkstring(L, 2);
+
+ data = imImageGetAttribute(image, attrib, &data_type, &count);
+ if (!data)
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ if (data_type == IM_BYTE && lua_isboolean(L, 3))
+ as_string = lua_toboolean(L, 3);
+
+ if (!as_string)
+ lua_newtable(L);
+
+ switch (data_type)
+ {
+ case IM_BYTE:
+ {
+ if (as_string)
+ {
+ lua_pushstring(L, (const char*)data);
+ }
+ else
+ {
+ imbyte *data_byte = (imbyte*) data;
+ for (i = 0; i < count; i++, data_byte++)
+ {
+ lua_pushnumber(L, *data_byte);
+ lua_rawseti(L, -2, i+1);
+ }
+ }
+ }
+ break;
+
+ case IM_USHORT:
+ {
+ imushort *data_ushort = (imushort*) data;
+ for (i = 0; i < count; i++, data_ushort += 2)
+ {
+ lua_pushnumber(L, *data_ushort);
+ lua_rawseti(L, -2, i+1);
+ }
+ }
+ break;
+
+ case IM_INT:
+ {
+ int *data_int = (int*) data;
+ for (i = 0; i < count; i++, data_int++)
+ {
+ lua_pushnumber(L, *data_int);
+ lua_rawseti(L, -2, i+1);
+ }
+ }
+ break;
+
+ case IM_FLOAT:
+ {
+ float *data_float = (float*) data;
+ for (i = 0; i < count; i++, data_float++)
+ {
+ lua_pushnumber(L, *data_float);
+ lua_rawseti(L, -2, i+1);
+ }
+ }
+ break;
+
+ case IM_CFLOAT:
+ {
+ float *data_float = (float*) data;
+ for (i = 0; i < count; i++, data_float += 2)
+ {
+ imlua_newarrayfloat(L, data_float, 2, 1);
+ lua_rawseti(L, -2, i+1);
+ }
+ }
+ break;
+ }
+
+ lua_pushnumber(L, data_type);
+
+ return 2;
+}
+
+/*****************************************************************************\
+ image:GetAttributeList()
+\*****************************************************************************/
+static int imluaImageGetAttributeList (lua_State *L)
+{
+ int i, attrib_count;
+ char **attrib;
+
+ imImage* image = imlua_checkimage(L, 1);
+
+ imImageGetAttributeList(image, NULL, &attrib_count);
+
+ attrib = (char**) malloc(attrib_count * sizeof(char*));
+
+ imImageGetAttributeList(image, attrib, &attrib_count);
+
+ lua_newtable(L);
+ for (i = 0; i < attrib_count; i++)
+ {
+ lua_pushstring(L, attrib[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+
+ return 1;
+}
+
+/*****************************************************************************\
+ image:Clear()
+\*****************************************************************************/
+static int imluaImageClear (lua_State *L)
+{
+ imImageClear(imlua_checkimage(L, 1));
+ return 0;
+}
+
+/*****************************************************************************\
+ image:isBitmap()
+\*****************************************************************************/
+static int imluaImageIsBitmap (lua_State *L)
+{
+ lua_pushboolean(L, imImageIsBitmap(imlua_checkimage(L, 1)));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:GetPalette()
+\*****************************************************************************/
+static int imluaImageGetPalette (lua_State *L)
+{
+ imImage *image = imlua_checkimage(L, 1);
+ long* color = malloc(sizeof(long) * 256);
+ memcpy(color, image->palette, sizeof(long) * 256);
+ imlua_pushpalette(L, color, 256);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:SetPalette
+\*****************************************************************************/
+static int imluaImageSetPalette (lua_State *L)
+{
+ imImage *image = imlua_checkimage(L, 1);
+ imluaPalette *pal = imlua_checkpalette(L, 2);
+ imImageSetPalette(image, pal->color, pal->count);
+ return 0;
+}
+
+/*****************************************************************************\
+ image:CopyAttributes(dst_image)
+\*****************************************************************************/
+static int imluaImageCopyAttributes (lua_State *L)
+{
+ imImage *src_image = imlua_checkimage(L, 1);
+ imImage *dst_image = imlua_checkimage(L, 2);
+
+ imImageCopyAttributes(src_image, dst_image);
+ return 0;
+}
+
+/*****************************************************************************\
+ image:MatchSize(image2)
+\*****************************************************************************/
+static int imluaImageMatchSize (lua_State *L)
+{
+ imImage *image1 = imlua_checkimage(L, 1);
+ imImage *image2 = imlua_checkimage(L, 2);
+
+ lua_pushboolean(L, imImageMatchSize(image1, image2));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:MatchColor(image2)
+\*****************************************************************************/
+static int imluaImageMatchColor (lua_State *L)
+{
+ imImage *image1 = imlua_checkimage(L, 1);
+ imImage *image2 = imlua_checkimage(L, 2);
+
+ lua_pushboolean(L, imImageMatchColor(image1, image2));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:MatchDataType(image2)
+\*****************************************************************************/
+static int imluaImageMatchDataType (lua_State *L)
+{
+ imImage *image1 = imlua_checkimage(L, 1);
+ imImage *image2 = imlua_checkimage(L, 2);
+
+ lua_pushboolean(L, imImageMatchDataType(image1, image2));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:MatchColorSpace(image2)
+\*****************************************************************************/
+static int imluaImageMatchColorSpace (lua_State *L)
+{
+ imImage *image1 = imlua_checkimage(L, 1);
+ imImage *image2 = imlua_checkimage(L, 2);
+
+ lua_pushboolean(L, imImageMatchColorSpace(image1, image2));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:Match(image2)
+\*****************************************************************************/
+static int imluaImageMatch (lua_State *L)
+{
+ imImage *image1 = imlua_checkimage(L, 1);
+ imImage *image2 = imlua_checkimage(L, 2);
+
+ lua_pushboolean(L, imImageMatch(image1, image2));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:SetBinary()
+\*****************************************************************************/
+static int imluaImageSetBinary (lua_State *L)
+{
+ imImageSetBinary(imlua_checkimage(L, 1));
+ return 0;
+}
+
+/*****************************************************************************\
+ image:MakeBinary()
+\*****************************************************************************/
+static int imluaImageMakeBinary (lua_State *L)
+{
+ imImageMakeBinary(imlua_checkimage(L, 1));
+ return 0;
+}
+
+/*****************************************************************************\
+ image:Width()
+\*****************************************************************************/
+static int imluaImageWidth(lua_State *L)
+{
+ imImage *im = imlua_checkimage(L, 1);
+ lua_pushnumber(L, im->width);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:Height()
+\*****************************************************************************/
+static int imluaImageHeight(lua_State *L)
+{
+ imImage *im = imlua_checkimage(L, 1);
+ lua_pushnumber(L, im->height);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:Depth()
+\*****************************************************************************/
+static int imluaImageDepth(lua_State *L)
+{
+ imImage *im = imlua_checkimage(L, 1);
+ lua_pushnumber(L, im->depth);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:DataType()
+\*****************************************************************************/
+static int imluaImageDataType(lua_State *L)
+{
+ imImage *im = imlua_checkimage(L, 1);
+ lua_pushnumber(L, im->data_type);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:ColorSpace()
+\*****************************************************************************/
+static int imluaImageColorSpace(lua_State *L)
+{
+ imImage *im = imlua_checkimage(L, 1);
+ lua_pushnumber(L, im->color_space);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:HasAlpha()
+\*****************************************************************************/
+static int imluaImageHasAlpha(lua_State *L)
+{
+ imImage *im = imlua_checkimage(L, 1);
+ lua_pushnumber(L, im->has_alpha);
+ return 1;
+}
+
+/*****************************************************************************\
+ im.FileImageLoad(filename, [index])
+\*****************************************************************************/
+static int imluaFileImageLoad (lua_State *L)
+{
+ const char *filename = luaL_checkstring(L, 1);
+ int index = luaL_optint(L, 2, 0);
+ int error;
+ imImage *image = imFileImageLoad(filename, index, &error);
+ return imlua_pushimageerror(L, image, error);
+}
+
+/*****************************************************************************\
+ im.FileImageLoadRegion(filename, [index])
+\*****************************************************************************/
+static int imluaFileImageLoadRegion (lua_State *L)
+{
+ const char *filename = luaL_checkstring(L, 1);
+ int index = luaL_checkint(L, 2);
+ int bitmap = luaL_checkint(L, 3);
+ int xmin = luaL_checkint(L, 4);
+ int xmax = luaL_checkint(L, 5);
+ int ymin = luaL_checkint(L, 6);
+ int ymax = luaL_checkint(L, 7);
+ int width = luaL_checkint(L, 8);
+ int height = luaL_checkint(L, 9);
+ int error;
+ imImage *image = imFileImageLoadRegion(filename, index, bitmap, &error, xmin, xmax, ymin, ymax, width, height);
+ return imlua_pushimageerror(L, image, error);
+}
+
+/*****************************************************************************\
+ im.FileImageLoadBitmap(filename, [index])
+\*****************************************************************************/
+static int imluaFileImageLoadBitmap (lua_State *L)
+{
+ const char *filename = luaL_checkstring(L, 1);
+ int index = luaL_optint(L, 2, 0);
+ int error;
+ imImage *image = imFileImageLoadBitmap(filename, index, &error);
+ return imlua_pushimageerror(L, image, error);
+}
+
+/*****************************************************************************\
+ im.FileImageSave(filename, format, image)
+\*****************************************************************************/
+static int imluaFileImageSave (lua_State *L)
+{
+ const char *file_name = luaL_checkstring(L, 1);
+ const char *format = luaL_checkstring(L, 2);
+ imImage *image = imlua_checkimage(L, 3);
+
+ imlua_pusherror(L, imFileImageSave(file_name, format, image));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:Save(filename, format)
+\*****************************************************************************/
+static int imluaImageSave (lua_State *L)
+{
+ imImage *image = imlua_checkimage(L, 1);
+ const char *file_name = luaL_checkstring(L, 2);
+ const char *format = luaL_checkstring(L, 3);
+
+ imlua_pusherror(L, imFileImageSave(file_name, format, image));
+ return 1;
+}
+
+/*****************************************************************************\
+ image:Destroy()
+\*****************************************************************************/
+static int imluaImageDestroy (lua_State *L)
+{
+ imImage** image_p = imlua_rawcheckimage(L, 1);
+ if (!(*image_p))
+ luaL_argerror(L, 1, "destroyed imImage");
+
+ imImageDestroy(*image_p);
+ *image_p = NULL; /* mark as destroyed */
+ return 0;
+}
+
+/*****************************************************************************\
+ gc
+\*****************************************************************************/
+static int imluaImage_gc (lua_State *L)
+{
+ imImage** image_p = imlua_rawcheckimage(L, 1);
+ if (*image_p)
+ {
+ imImageDestroy(*image_p);
+ *image_p = NULL; /* mark as destroyed */
+ }
+
+ return 0;
+}
+
+/*****************************************************************************\
+ image tostring
+\*****************************************************************************/
+static int imluaImage_tostring (lua_State *L)
+{
+ imImage** image_p = (imImage**)lua_touserdata(L, 1);
+ if (*image_p)
+ {
+ imImage *image = *image_p;
+ lua_pushfstring(L, "imImage(%p) [width=%d,height=%d,color_space=%s,data_type=%s,depth=%d]",
+ image_p,
+ image->width,
+ image->height,
+ imColorModeSpaceName(image->color_space),
+ imDataTypeName(image->data_type),
+ image->depth
+ );
+ }
+ else
+ {
+ lua_pushfstring(L, "imImage(%p)-destroyed", image_p);
+ }
+
+ return 1;
+}
+
+/*****************************************************************************\
+ imagechannel tostring
+\*****************************************************************************/
+static int imluaImageChannel_tostring (lua_State *L)
+{
+ imluaImageChannel *imagechannel = imlua_checkimagechannel(L, 1);
+ lua_pushfstring(L, "imImageChannel(%p) [channel=%d]",
+ imagechannel,
+ imagechannel->channel
+ );
+ return 1;
+}
+
+/*****************************************************************************\
+ imagerow tostring
+\*****************************************************************************/
+static int imluaImageRow_tostring (lua_State *L)
+{
+ char buff[32];
+ imluaImageRow *imagerow = imlua_checkimagerow(L, 1);
+
+ sprintf(buff, "%p", lua_touserdata(L, 1));
+ lua_pushfstring(L, "imImageRow(%s) [channel=%d,row=%d]",
+ buff,
+ imagerow->channel,
+ imagerow->row
+ );
+ return 1;
+}
+
+/*****************************************************************************\
+ image row indexing
+\*****************************************************************************/
+static int imluaImageRow_index (lua_State *L)
+{
+ int index;
+ imluaImageRow *imagerow = imlua_checkimagerow(L, 1);
+ imImage *image = imagerow->image;
+ int channel = imagerow->channel;
+ int row = imagerow->row;
+ int column = luaL_checkint(L, 2);
+
+ if (column < 0 || column >= imagerow->image->width)
+ luaL_argerror(L, 2, "invalid column, out of bounds");
+
+ index = channel * image->width * image->height + row * image->width + column;
+
+ switch (image->data_type)
+ {
+ case IM_BYTE:
+ {
+ imbyte *bdata = (imbyte*) image->data[0];
+ lua_pushnumber(L, (lua_Number) bdata[index]);
+ }
+ break;
+
+ case IM_USHORT:
+ {
+ imushort *udata = (imushort*) image->data[0];
+ lua_pushnumber(L, (lua_Number) udata[index]);
+ }
+ break;
+
+ case IM_INT:
+ {
+ int *idata = (int*) image->data[0];
+ lua_pushnumber(L, (lua_Number) idata[index]);
+ }
+ break;
+
+ case IM_FLOAT:
+ {
+ float *fdata = (float*) image->data[0];
+ lua_pushnumber(L, (lua_Number) fdata[index]);
+ }
+ break;
+
+ case IM_CFLOAT:
+ {
+ float *cdata = (float*) image->data[0];
+ imlua_newarrayfloat(L, cdata + (2*index), 2, 1);
+ }
+ break;
+ }
+
+ return 1;
+}
+
+/*****************************************************************************\
+ image row new index
+\*****************************************************************************/
+static int imluaImageRow_newindex (lua_State *L)
+{
+ int index;
+ imluaImageRow *imagerow = imlua_checkimagerow(L, 1);
+ imImage *image = imagerow->image;
+ int channel = imagerow->channel;
+ int row = imagerow->row;
+ int column = luaL_checkint(L, 2);
+
+ if (column < 0 || column >= imagerow->image->width)
+ luaL_argerror(L, 2, "invalid column, out of bounds");
+
+ index = channel * image->width * image->height + row * image->width + column;
+
+ switch (image->data_type)
+ {
+ case IM_BYTE:
+ {
+ lua_Number value = luaL_checknumber(L, 3);
+ imbyte *bdata = (imbyte*) image->data[0];
+ bdata[index] = (imbyte) value;
+ }
+ break;
+
+ case IM_USHORT:
+ {
+ lua_Number value = luaL_checknumber(L, 3);
+ imushort *udata = (imushort*) image->data[0];
+ udata[index] = (imushort) value;
+ }
+ break;
+
+ case IM_INT:
+ {
+ lua_Number value = luaL_checknumber(L, 3);
+ int *idata = (int*) image->data[0];
+ idata[index] = (int) value;
+ }
+ break;
+
+ case IM_FLOAT:
+ {
+ lua_Number value = luaL_checknumber(L, 3);
+ float *fdata = (float*) image->data[0];
+ fdata[index] = (float) value;
+ }
+ break;
+
+ case IM_CFLOAT:
+ {
+ int count;
+ float *cdata = (float*) image->data[0];
+ float *value = imlua_toarrayfloat(L, 3, &count, 1);
+ if (count != 2)
+ {
+ free(value);
+ luaL_argerror(L, 3, "invalid value");
+ }
+
+ cdata[2*index] = value[0];
+ cdata[2*index+1] = value[1];
+ free(value);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************\
+ image channel indexing
+\*****************************************************************************/
+static int imluaImageChannel_index (lua_State *L)
+{
+ imluaImageChannel *imagechannel = imlua_checkimagechannel(L, 1);
+ int row = luaL_checkint(L, 2);
+
+ if (row < 0 || row >= imagechannel->image->height)
+ luaL_argerror(L, 2, "invalid row, out of bounds");
+
+ imlua_newimagerow(L, imagechannel->image, imagechannel->channel, row);
+ return 1;
+}
+
+/*****************************************************************************\
+ image indexing
+\*****************************************************************************/
+static int imluaImage_index (lua_State *L)
+{
+ imImage *image = imlua_checkimage(L, 1);
+
+ if (lua_isnumber(L, 2))
+ {
+ /* handle numeric indexing */
+ int channel = luaL_checkint(L, 2);
+
+ /* create channel */
+ if (channel < 0 || channel >= image->depth)
+ luaL_argerror(L, 2, "invalid channel, out of bounds");
+
+ imlua_newimagechannel(L, image, channel);
+ }
+ else if (lua_isstring(L, 2))
+ {
+ /* get raw method */
+ lua_getmetatable(L, 1);
+ lua_pushvalue(L, 2);
+ lua_rawget(L, -2);
+ }
+ else
+ {
+ lua_pushnil(L);
+ }
+
+ return 1;
+}
+
+static const luaL_reg imimage_lib[] = {
+ {"ImageCreate", imluaImageCreate},
+ {"ImageDestroy", imluaImageDestroy},
+ {"FileImageLoad", imluaFileImageLoad},
+ {"FileImageLoadBitmap", imluaFileImageLoadBitmap},
+ {"FileImageLoadRegion", imluaFileImageLoadRegion},
+ {"FileImageSave", imluaFileImageSave},
+ {NULL, NULL}
+};
+
+static const luaL_reg imimage_metalib[] = {
+ {"Destroy", imluaImageDestroy},
+ {"AddAlpha", imluaImageAddAlpha},
+ {"Reshape", imluaImageReshape},
+ {"Copy", imluaImageCopy},
+ {"CopyData", imluaImageCopyData},
+ {"Duplicate", imluaImageDuplicate},
+ {"Clone", imluaImageClone},
+ {"SetAttribute", imluaImageSetAttribute},
+ {"GetAttribute", imluaImageGetAttribute},
+ {"GetAttributeList", imluaImageGetAttributeList},
+ {"Clear", imluaImageClear},
+ {"IsBitmap", imluaImageIsBitmap},
+ {"SetPalette", imluaImageSetPalette},
+ {"GetPalette", imluaImageGetPalette},
+ {"CopyAttributes", imluaImageCopyAttributes},
+ {"MatchSize", imluaImageMatchSize},
+ {"MatchColor", imluaImageMatchColor},
+ {"MatchDataType", imluaImageMatchDataType},
+ {"MatchColorSpace", imluaImageMatchColorSpace},
+ {"Match", imluaImageMatch},
+ {"SetBinary", imluaImageSetBinary},
+ {"MakeBinary", imluaImageMakeBinary},
+ {"Width", imluaImageWidth},
+ {"Height", imluaImageHeight},
+ {"Depth", imluaImageDepth},
+ {"DataType", imluaImageDataType},
+ {"ColorSpace", imluaImageColorSpace},
+ {"HasAlpha", imluaImageHasAlpha},
+ {"Save", imluaImageSave},
+
+ {"__gc", imluaImage_gc},
+ {"__tostring", imluaImage_tostring},
+ {"__index", imluaImage_index},
+
+ {NULL, NULL}
+};
+
+static void createmeta (lua_State *L)
+{
+ luaL_newmetatable(L, "imImageChannel"); /* create new metatable for imImageChannel handles */
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, imluaImageChannel_index);
+ lua_rawset(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, imluaImageChannel_tostring);
+ lua_rawset(L, -3);
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+
+ luaL_newmetatable(L, "imImageChannelRow"); /* create new metatable for imImageChannelRow handles */
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, imluaImageRow_index);
+ lua_rawset(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, imluaImageRow_newindex);
+ lua_rawset(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, imluaImageRow_tostring);
+ lua_rawset(L, -3);
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+
+ /* Object Oriented Access */
+ luaL_newmetatable(L, "imImage"); /* create new metatable for imImage handles */
+ lua_pushliteral(L, "__index"); /* dummy code because imluaImage_index will overwrite this behavior */
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+ luaL_register(L, NULL, imimage_metalib); /* register methods */
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+}
+
+/* If all parameteres, besides the image, are nil, this is equivalent to image:Clone.
+ If any parameter is not nil, then the value is used instead of the one from the source image.
+ If a parameter is a function, then the function is called, passing the source
+ image as parameter, to obtain the substituion value. */
+static void reg_image(lua_State *L)
+{
+ const char* data = {
+"function im.ImageCreateBased(image, width, height, color_space, data_type) \n"
+" -- default values are those of the source image \n"
+" width = width or image:Width() \n"
+" height = height or image:Height() \n"
+" color_space = color_space or image:ColorSpace() \n"
+" data_type = data_type or image:DataType() \n"
+" \n"
+" -- callback to calculate parameters based on source image \n"
+" if type(width) == \"function\" then width = width(image) end \n"
+" if type(height) == \"function\" then height = height(image) end \n"
+" if type(color_space) == \"function\" then color_space = color_space(image) end \n"
+" if type(data_type) == \"function\" then data_type = data_type(image) end \n"
+" \n"
+" -- create a new image \n"
+" new_image = im.ImageCreate(width, height, color_space, data_type) \n"
+" image:CopyAttributes(new_image) \n"
+" return new_image \n"
+"end \n"
+ };
+
+ if (luaL_loadbuffer(L, data, strlen(data), "reg_image")==0) lua_pcall(L, 0, 0, 0);
+}
+
+void imlua_open_image (lua_State *L)
+{
+ /* "im" table is at the top of the stack */
+ createmeta(L);
+ luaL_register(L, NULL, imimage_lib);
+ reg_image(L);
+}