00001 #include "lugre_prefix.h"
00002 #include "lugre_luabind.h"
00003 #include "lugre_ogrewrapper.h"
00004 #include "lugre_image.h"
00005 #include "lugre_bitmask.h"
00006 #include "lugre_luabind_direct.h"
00007 #include "lugre_luabind_ogrehelper.h"
00008 #include <Ogre.h>
00009
00010 extern "C" {
00011 #include "lua.h"
00012 #include "lauxlib.h"
00013 #include "lualib.h"
00014 }
00015
00016
00017 #include <map>
00018
00019 using namespace Ogre;
00020
00021 namespace Lugre {
00022
00023 cImage::cImage () {}
00024 cImage::~cImage () {}
00025
00026
00027 Ogre::PixelFormat iPreparedFormat = Ogre::PF_BYTE_RGBA;
00028 Ogre::uchar* pPreparedBuf = 0;
00029 unsigned int iPreparedWidth = 0;
00030 unsigned int iPreparedHeight = 0;
00031 unsigned int iPreparedBufferSize = 0;
00032 unsigned int iPreparedRowSize = 0;
00033
00034
00035 int LugreImage_CreateFromOgreImage (lua_State *L,Ogre::Image* pImg) { PROFILE return cLuaBind<cImage>::CreateUData(L,new cImage(pImg)); }
00036
00037
00038 bool MySubImage (Ogre::Image& pImageSrc,Ogre::Image& pImageDst,int iOffsetX,int iOffsetY,int iNewWidth,int iNewHeight) {
00039 if (iNewWidth <= 0) { printf("SubImage error, iNewWidth(%d) <= 0\n",iNewWidth); return false; }
00040 if (iNewHeight <= 0) { printf("SubImage error, iNewHeight(%d) <= 0\n",iNewHeight); return false; }
00041 if (iOffsetX < 0) { printf("SubImage error, iOffsetX(%d) < 0\n",iOffsetX); return false; }
00042 if (iOffsetY < 0) { printf("SubImage error, iOffsetY(%d) < 0\n",iOffsetY); return false; }
00043 if (iOffsetX+iNewWidth > pImageSrc.getWidth()) { printf("SubImage error, right(%d) > w\n",iOffsetX+iNewWidth); return false; }
00044 if (iOffsetY+iNewHeight > pImageSrc.getHeight()) { printf("SubImage error, bottom(%d) > h\n",iOffsetY+iNewHeight); return false; }
00045
00046
00047 Ogre::PixelFormat iPixelFormat = pImageSrc.getFormat();
00048
00049 Ogre::uchar* dataD = (Ogre::uchar*)OGRE_MALLOC(Ogre::PixelUtil::getMemorySize(iNewWidth,iNewHeight,1,iPixelFormat), MEMCATEGORY_GENERAL);
00050 Ogre::uchar* dataS = pImageSrc.getData();
00051 size_t pixelsizeS = pImageSrc.getBPP() / 8;
00052 size_t wS = pImageSrc.getWidth();
00053
00054
00055 int rowlenD = pixelsizeS * iNewWidth;
00056 int rowlenS = pixelsizeS * wS;
00057 Ogre::uchar* reader = &dataS[pixelsizeS*(wS * (iOffsetY) + iOffsetX)];
00058 Ogre::uchar* writer = dataD;
00059 for (int y=0;y<iNewHeight;++y,reader+=rowlenS,writer+=rowlenD) memcpy(writer,reader,rowlenD);
00060
00061 pImageDst.loadDynamicImage(dataD,iNewWidth,iNewHeight,1,iPixelFormat,true);
00062 return true;
00063 }
00064
00065 void PrintOgreExceptionAndTipps(Ogre::Exception& e);
00066
00067 class cImage_L : public cLuaBind<cImage> { public:
00069 virtual void RegisterMethods (lua_State *L) { PROFILE
00070 #define REGISTER_METHOD(methodname) mlMethod.push_back(make_luaL_reg(#methodname,&cImage_L::methodname));
00071 REGISTER_METHOD(Destroy);
00072 REGISTER_METHOD(SaveAsFile);
00073 REGISTER_METHOD(GetWidth);
00074 REGISTER_METHOD(GetHeight);
00075 REGISTER_METHOD(MakeTexture);
00076 REGISTER_METHOD(LoadToTexture);
00077 REGISTER_METHOD(GenerateBitMask);
00078
00079 LUABIND_QUICKWRAP( GetQuickHandle, { return cLuaBindDirectOgreHelper::PushImage(L,&checkudata_alive(L)->mImage); });
00080 LUABIND_QUICKWRAP( ColorReplace, { cOgreWrapper::ImageColorReplace( checkudata_alive(L)->mImage,cLuaBindDirectOgreHelper::ParamColourValue(L,2),cLuaBindDirectOgreHelper::ParamColourValue(L,3)); });
00081 LUABIND_QUICKWRAP( ColorKeyToAlpha, { cOgreWrapper::ImageColorKeyToAlpha( checkudata_alive(L)->mImage,cLuaBindDirectOgreHelper::ParamColourValue(L,2)); });
00082
00084 LUABIND_QUICKWRAP( BlitPart, { cOgreWrapper::ImageBlitPart(checkudata_alive(L,1)->mImage,checkudata_alive(L,2)->mImage,
00085 ParamInt(L,3),ParamInt(L,4),ParamInt(L,5),ParamInt(L,6),ParamInt(L,7),ParamInt(L,8)); });
00086
00087 lua_register(L,"LoadImageFromFile", &cImage_L::LoadImageFromFile);
00088 lua_register(L,"LoadImageFromTexture", &cImage_L::LoadImageFromTexture);
00089 lua_register(L,"SubImage", &cImage_L::SubImage);
00090 lua_register(L,"ImageScale", &cImage_L::ImageScale);
00091 lua_register(L,"ImageBlit", &cImage_L::ImageBlit);
00092 lua_register(L,"CreateImage", &cImage_L::CreateImage);
00093
00094 lua_register(L,"PrepareImage", &cImage_L::PrepareImage);
00095 lua_register(L,"CreatePreparedImage", &cImage_L::CreatePreparedImage);
00096 lua_register(L,"SetPixelInPreparedImage", &cImage_L::SetPixelInPreparedImage);
00097 }
00098
00099
00100
00102 static int Destroy (lua_State *L) { PROFILE delete checkudata_alive(L); return 0; }
00103
00105 static int SaveAsFile (lua_State *L) { PROFILE
00106 Ogre::Image& mImage = checkudata_alive(L)->mImage;
00107 if (mImage.getWidth() <= 0 || mImage.getHeight() <= 0) return 0;
00108 std::string sFileName = luaL_checkstring(L,2);
00109 try {
00110 mImage.save(sFileName);
00111 } catch( Ogre::Exception& e ) {
00112 printf("warning, Image:SaveAsFile failed with exception\n");
00113 PrintOgreExceptionAndTipps(e);
00114 return 0;
00115 }
00116 lua_pushboolean(L,true);
00117 return 1;
00118 }
00119
00121 static int GetWidth (lua_State *L) { PROFILE
00122 lua_pushnumber(L,checkudata_alive(L)->mImage.getWidth());
00123 return 1;
00124 }
00125
00127 static int GetHeight (lua_State *L) { PROFILE
00128 lua_pushnumber(L,checkudata_alive(L)->mImage.getHeight());
00129 return 1;
00130 }
00131
00135 static int MakeTexture (lua_State *L) { PROFILE
00136 std::string sTexName = (lua_gettop(L) >= 2 && !lua_isnil(L,2)) ? luaL_checkstring(L,2) : cOgreWrapper::GetSingleton().GetUniqueName();
00137 bool bIsAlpha = (lua_gettop(L) >= 3 && !lua_isnil(L,3)) ? lua_toboolean(L,3) : false;
00138
00139 const Ogre::String& group = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
00140 Ogre::TextureType texType = TEX_TYPE_2D;
00141 int iNumMipmaps = MIP_DEFAULT;
00142 Ogre::Real gamma = 1.0f;
00143 Ogre::PixelFormat desiredFormat = PF_UNKNOWN;
00144
00145 Ogre::TextureManager::getSingleton().loadImage(sTexName,group,checkudata_alive(L)->mImage,texType,iNumMipmaps,gamma,bIsAlpha,desiredFormat);
00146 lua_pushstring(L,sTexName.c_str());
00147 return 1;
00148 }
00149
00152 static int LoadToTexture (lua_State *L) { PROFILE
00153 std::string sTexName = luaL_checkstring(L,2);
00154 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().load(sTexName,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00155 if (tex.isNull()) return 0;
00156 tex->unload();
00157 tex->loadImage(checkudata_alive(L)->mImage);
00158 lua_pushboolean(L,true);
00159 return 1;
00160 }
00161
00164 static int GenerateBitMask (lua_State *L) { PROFILE
00165 cBitMask* pTarget = new cBitMask();
00166 float fMinAlpha = (lua_gettop(L) >= 2 && !lua_isnil(L,2)) ? luaL_checknumber(L,2) : 0.5;
00167 pTarget->SetDataFromOgreImage(checkudata_alive(L)->mImage,fMinAlpha);
00168 return cLuaBind<cBitMask>::CreateUData(L,pTarget);
00169 }
00170
00171
00172
00176 static int LoadImageFromFile (lua_State *L) { PROFILE
00177 cImage* pImage = new cImage();
00178 std::string sFileNameOrPath = luaL_checkstring(L,1);
00179 try {
00180 pImage->mImage.load(sFileNameOrPath,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00181 } catch (...) { delete pImage; return 0; }
00182 return CreateUData(L,pImage);
00183 }
00184
00187 static int LoadImageFromTexture (lua_State *L) { PROFILE
00188 std::string sTexName = luaL_checkstring(L,1);
00189 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().load(sTexName,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00190 if (tex.isNull()) return 0;
00191
00192
00193 Ogre::HardwarePixelBufferSharedPtr b = tex->getBuffer();
00194 if (b.isNull()) return 0;
00195
00196
00197 cImage* pImage = new cImage();
00198 Ogre::PixelFormat myformat = Ogre::PF_A8R8G8B8;
00199 Ogre::uchar* buf = (Ogre::uchar*)OGRE_MALLOC(Ogre::PixelUtil::getMemorySize(b->getWidth(),b->getHeight(),1,myformat), MEMCATEGORY_GENERAL);
00200 b->blitToMemory(Ogre::PixelBox(Ogre::Box(0,0,b->getWidth(),b->getHeight()),myformat,buf));
00201
00202
00203 pImage->mImage.loadDynamicImage(buf,b->getWidth(),b->getHeight(),1,myformat,true);
00204
00205 return CreateUData(L,pImage);
00206 }
00207
00209 static int SubImage (lua_State *L) { PROFILE
00210
00211 Ogre::Image& pImageS = checkudata_alive(L)->mImage;
00212 int iOffsetX = luaL_checkint(L,2);
00213 int iOffsetY = luaL_checkint(L,3);
00214 int iNewWidth = luaL_checkint(L,4);
00215 int iNewHeight = luaL_checkint(L,5);
00216
00217 cImage* pImageDest = new cImage();
00218 MySubImage(pImageS,pImageDest->mImage,iOffsetX,iOffsetY,iNewWidth,iNewHeight);
00219 return CreateUData(L,pImageDest);
00220 }
00221
00222
00224 static int ImageScale (lua_State *L) { PROFILE
00225
00226 cImage* pImageSource = checkudata_alive(L);
00227 int iNewWidth = luaL_checkint(L,2);
00228 int iNewHeight = luaL_checkint(L,3);
00229
00230
00231 Ogre::PixelFormat iPixelFormat = pImageSource->mImage.getFormat();
00232 Ogre::PixelBox pPBoxSrc = pImageSource->mImage.getPixelBox();
00233
00234
00235 Ogre::uchar* pDestBuffer = (Ogre::uchar*)OGRE_MALLOC(Ogre::PixelUtil::getMemorySize(iNewWidth,iNewHeight,1,iPixelFormat), MEMCATEGORY_GENERAL);
00236 Ogre::PixelBox pPBoxDest (iNewWidth,iNewHeight,1,iPixelFormat,pDestBuffer);
00237 Ogre::Image::Filter iFilter = Ogre::Image::FILTER_BILINEAR;
00238 Ogre::Image::scale(pPBoxSrc,pPBoxDest,iFilter);
00239
00240 cImage* pImageDest = new cImage();
00241 pImageDest->mImage.loadDynamicImage(pDestBuffer,iNewWidth,iNewHeight,1,iPixelFormat,true);
00242 return CreateUData(L,pImageDest);
00243 }
00244
00247 static int ImageBlit (lua_State *L) { PROFILE
00248 Ogre::Image& pImageS = checkudata_alive(L,1)->mImage;
00249 Ogre::Image& pImageD = checkudata_alive(L,2)->mImage;
00250 int x = luaL_checkint(L,3);
00251 int y = luaL_checkint(L,4);
00252 cOgreWrapper::ImageBlit(pImageS,pImageD,x,y);
00253 return 0;
00254 }
00255
00257 static int CreateImage (lua_State *L) { PROFILE
00258 return CreateUData(L,new cImage());
00259 }
00260
00261
00266 static int PrepareImage (lua_State *L) { PROFILE
00267 assert(pPreparedBuf == 0 && "you must call CreatePreparedImage between the PrepareImage calls");
00268
00269 iPreparedWidth = luaL_checkint(L,1);
00270 iPreparedHeight = luaL_checkint(L,2);
00271
00272 assert(iPreparedWidth > 0 && iPreparedHeight > 0 && "size must not be 0");
00273
00274 iPreparedBufferSize = Ogre::PixelUtil::getMemorySize(iPreparedWidth,iPreparedHeight,1,iPreparedFormat);
00275 iPreparedRowSize = Ogre::PixelUtil::getNumElemBytes(iPreparedFormat) * iPreparedWidth;
00276 pPreparedBuf = (Ogre::uchar*)OGRE_MALLOC(iPreparedBufferSize, MEMCATEGORY_GENERAL);
00277
00278 if(
00279 lua_gettop(L) >= 3 && !lua_isnil(L,3) &&
00280 lua_gettop(L) >= 4 && !lua_isnil(L,4) &&
00281 lua_gettop(L) >= 5 && !lua_isnil(L,5) &&
00282 lua_gettop(L) >= 6 && !lua_isnil(L,6)
00283 ){
00284
00285 float r = luaL_checknumber(L,3);
00286 float g = luaL_checknumber(L,4);
00287 float b = luaL_checknumber(L,5);
00288 float a = luaL_checknumber(L,6);
00289
00290 int pitch = Ogre::PixelUtil::getNumElemBytes(iPreparedFormat);
00291
00292 for(Ogre::uchar *p = pPreparedBuf; (p - pPreparedBuf) < iPreparedBufferSize;p += pitch){
00293 Ogre::PixelUtil::packColour(r,g,b,a,iPreparedFormat,p);
00294 }
00295 } else {
00296
00297 memset(pPreparedBuf, 0, iPreparedBufferSize);
00298 }
00299
00300 return 0;
00301 }
00302
00305 static int CreatePreparedImage (lua_State *L) { PROFILE
00306 cImage* pImageDest = new cImage();
00307 pImageDest->mImage.loadDynamicImage(pPreparedBuf,iPreparedWidth,iPreparedHeight,1,iPreparedFormat,true);
00308
00309 pPreparedBuf = 0;
00310 iPreparedWidth = 0;
00311 iPreparedHeight = 0;
00312
00313 return CreateUData(L,pImageDest);
00314 }
00315
00318 static int SetPixelInPreparedImage (lua_State *L) { PROFILE
00319 int x = luaL_checkint(L,1);
00320 int y = luaL_checkint(L,2);
00321
00322 if(x < 0 || y < 0 || x >= iPreparedWidth || y >= iPreparedHeight)return 0;
00323
00324 float r = luaL_checknumber(L,3);
00325 float g = luaL_checknumber(L,4);
00326 float b = luaL_checknumber(L,5);
00327 float a = luaL_checknumber(L,6);
00328
00329 Ogre::uchar *p = pPreparedBuf + (y * iPreparedRowSize + x * Ogre::PixelUtil::getNumElemBytes(iPreparedFormat));
00330 Ogre::PixelUtil::packColour(r,g,b,a,iPreparedFormat,p);
00331
00332 return 0;
00333 }
00334
00335 virtual const char* GetLuaTypeName () { return "lugre.Image"; }
00336 };
00337
00339 void cImage::LuaRegister (lua_State *L) { PROFILE
00340 cLuaBind<cImage>::GetSingletonPtr(new cImage_L())->LuaRegister(L);
00341 }
00342
00343 };