DevIL.NET.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // DevIL.NET
  2. // Copyright (c) 2005, Marco Mastropaolo
  3. // All rights reserved.
  4. // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
  5. // following conditions are met:
  6. // * Redistributions of source code must retain the above copyright notice, this list of conditions and the
  7. // following disclaimer.
  8. // * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
  9. // following disclaimer in the documentation and/or other materials provided with the distribution.
  10. // * Neither the name of DevIL.NET nor the names of its contributors may be used to endorse or promote products
  11. // derived from this software without specific prior written permission.
  12. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  13. // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  14. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  15. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  16. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  17. // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  18. // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  19. #using <mscorlib.dll>
  20. #using <System.Drawing.dll>
  21. #include <windows.h>
  22. #include "IL/il.h"
  23. #include "IL/ilu.h"
  24. #undef LoadBitmap // brain damaged windows.h macros..
  25. typedef ILboolean (*PFNILUSCALE)(ILuint Width, ILuint Height, ILuint Depth);
  26. typedef ILvoid (*PFNILUIMAGEPARAMETER)(ILenum PName, ILenum Param);
  27. namespace DevIL
  28. {
  29. class StringAutoMarshal
  30. {
  31. char* m_string;
  32. inline explicit StringAutoMarshal(const StringAutoMarshal& i_Source) : m_string(NULL) {}
  33. inline StringAutoMarshal& operator= (const StringAutoMarshal& i_Source) {}
  34. public:
  35. inline explicit StringAutoMarshal(const System::String __gc* i_strString) : m_string(NULL)
  36. {
  37. m_string = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(const_cast<System::String __gc*>(i_strString));
  38. }
  39. inline ~StringAutoMarshal()
  40. {
  41. System::Runtime::InteropServices::Marshal::FreeHGlobal((void*)m_string);
  42. }
  43. inline char* GetNativeString()
  44. {
  45. return m_string;
  46. }
  47. inline operator char*()
  48. {
  49. return m_string;
  50. }
  51. };
  52. public __value enum DevILScaleFilter
  53. {
  54. NEAREST = ILU_NEAREST,
  55. LINEAR = ILU_LINEAR,
  56. BILINEAR = ILU_BILINEAR,
  57. BOX = ILU_SCALE_BOX,
  58. TRIANGLE = ILU_SCALE_TRIANGLE,
  59. BELL = ILU_SCALE_BELL,
  60. BSPLINE = ILU_SCALE_BSPLINE,
  61. LANCZOS3 = ILU_SCALE_LANCZOS3,
  62. MITCHELL = ILU_SCALE_MITCHELL
  63. };
  64. public __value enum DevILScaleKind
  65. {
  66. DO_NOT_SCALE,
  67. WIDTH_AND_HEIGHT,
  68. WIDTH_ONLY,
  69. HEIGHT_ONLY,
  70. KEEPRATIO_USING_WIDTH,
  71. KEEPRATIO_USING_HEIGHT
  72. };
  73. public __value enum DevILErrorCode
  74. {
  75. OK = 0,
  76. ILU_DLL_NOT_FOUND = 0x0001,
  77. INVALID_ENUM = IL_INVALID_ENUM,
  78. OUT_OF_MEMORY = IL_OUT_OF_MEMORY,
  79. FORMAT_NOT_SUPPORTED = IL_FORMAT_NOT_SUPPORTED,
  80. INTERNAL_ERROR = IL_INTERNAL_ERROR,
  81. INVALID_VALUE = IL_INVALID_VALUE,
  82. ILLEGAL_OPERATION = IL_ILLEGAL_OPERATION,
  83. ILLEGAL_FILE_VALUE = IL_ILLEGAL_FILE_VALUE,
  84. INVALID_FILE_HEADER = IL_INVALID_FILE_HEADER,
  85. INVALID_PARAM = IL_INVALID_PARAM,
  86. COULD_NOT_OPEN_FILE = IL_COULD_NOT_OPEN_FILE,
  87. INVALID_EXTENSION = IL_INVALID_EXTENSION,
  88. FILE_ALREADY_EXISTS = IL_FILE_ALREADY_EXISTS,
  89. OUT_FORMAT_SAME = IL_OUT_FORMAT_SAME,
  90. STACK_OVERFLOW = IL_STACK_OVERFLOW,
  91. STACK_UNDERFLOW = IL_STACK_UNDERFLOW,
  92. INVALID_CONVERSION = IL_INVALID_CONVERSION,
  93. BAD_DIMENSIONS = IL_BAD_DIMENSIONS,
  94. FILE_READ_ERROR = IL_FILE_READ_ERROR,
  95. FILE_WRITE_ERROR = IL_FILE_WRITE_ERROR,
  96. LIB_GIF_ERROR = IL_LIB_GIF_ERROR,
  97. LIB_JPEG_ERROR = IL_LIB_JPEG_ERROR,
  98. LIB_PNG_ERROR = IL_LIB_PNG_ERROR,
  99. LIB_TIFF_ERROR = IL_LIB_TIFF_ERROR,
  100. LIB_MNG_ERROR = IL_LIB_MNG_ERROR,
  101. UNKNOWN_ERROR = IL_UNKNOWN_ERROR
  102. };
  103. public __gc class DevIL
  104. {
  105. protected:
  106. static ILuint s_iImageID = 0;
  107. static bool s_bInitDone = false;
  108. static bool s_bIluLoaded = false;
  109. static DevILErrorCode s_eErrCode = OK;
  110. static PFNILUSCALE pfnIluScale = NULL;
  111. static PFNILUIMAGEPARAMETER pfnIluImageParameter = NULL;
  112. static void LoadILU();
  113. public:
  114. static System::Drawing::Bitmap __gc* LoadBitmap(System::String __gc* i_szFileName);
  115. static System::Drawing::Bitmap __gc* LoadBitmapAndScale(System::String __gc* i_szFileName,
  116. int i_iWidth, int i_iHeight,
  117. DevILScaleFilter i_eFilter, DevILScaleKind i_eKind);
  118. static bool SaveBitmap(System::String __gc* i_szFileName, System::Drawing::Bitmap __gc* i_poBitmap);
  119. static DevILErrorCode GetErrorCode();
  120. };
  121. }
  122. void DevIL::DevIL::LoadILU()
  123. {
  124. HMODULE hM = LoadLibrary("ILU.dll");
  125. if (hM)
  126. {
  127. pfnIluScale = (PFNILUSCALE)GetProcAddress(hM, "iluScale");
  128. pfnIluImageParameter = (PFNILUIMAGEPARAMETER)GetProcAddress(hM, "iluImageParameter");
  129. s_bIluLoaded = (pfnIluScale != NULL) && (pfnIluImageParameter != NULL);
  130. }
  131. }
  132. System::Drawing::Bitmap __gc* DevIL::DevIL::LoadBitmap(System::String __gc* i_szFileName)
  133. {
  134. return LoadBitmapAndScale(i_szFileName, 0, 0, NEAREST, DO_NOT_SCALE);
  135. }
  136. DevIL::DevILErrorCode DevIL::DevIL::GetErrorCode()
  137. {
  138. if (s_eErrCode == OK)
  139. {
  140. return DevILErrorCode(ilGetError());
  141. }
  142. else
  143. {
  144. DevILErrorCode eErr = s_eErrCode;
  145. s_eErrCode = OK;
  146. return eErr;
  147. }
  148. }
  149. System::Drawing::Bitmap __gc* DevIL::DevIL::LoadBitmapAndScale(System::String __gc* i_szFileName,
  150. int i_iWidth, int i_iHeight,
  151. DevILScaleFilter i_eFilter,
  152. DevILScaleKind i_eKind)
  153. {
  154. if (!s_bInitDone)
  155. {
  156. ilInit();
  157. s_bInitDone = true;
  158. }
  159. ilGenImages(1, &s_iImageID);
  160. ilBindImage(s_iImageID);
  161. if (0==ilLoadImage(StringAutoMarshal(i_szFileName)))
  162. {
  163. return NULL;
  164. }
  165. int iW = ilGetInteger(IL_IMAGE_WIDTH);
  166. int iH = ilGetInteger(IL_IMAGE_HEIGHT);
  167. bool bResize = true;
  168. switch(i_eKind)
  169. {
  170. case WIDTH_AND_HEIGHT:
  171. iW = i_iWidth;
  172. iH = i_iHeight;
  173. break;
  174. case WIDTH_ONLY:
  175. iW = i_iWidth;
  176. break;
  177. case HEIGHT_ONLY:
  178. iH = i_iHeight;
  179. break;
  180. case KEEPRATIO_USING_WIDTH:
  181. iH = int(double(iH) * double(i_iWidth) / double(iW));
  182. iW = i_iWidth;
  183. break;
  184. case KEEPRATIO_USING_HEIGHT:
  185. iW = int(double(iW) * double(i_iHeight) / double(iH));
  186. iH = i_iHeight;
  187. break;
  188. case DO_NOT_SCALE:
  189. bResize = false;
  190. break;
  191. default:
  192. break;
  193. }
  194. System::Drawing::Bitmap __gc* pBmp = __gc new System::Drawing::Bitmap(iW, iH, System::Drawing::Imaging::PixelFormat::Format32bppArgb);
  195. System::Drawing::Rectangle rect; rect.X = 0; rect.Y = 0; rect.Width = iW; rect.Height = iH;
  196. System::Drawing::Imaging::BitmapData __gc* pBd = pBmp->LockBits(rect,
  197. System::Drawing::Imaging::ImageLockMode::WriteOnly,
  198. System::Drawing::Imaging::PixelFormat::Format32bppArgb);
  199. void* pScan0 = (void*)(pBd->Scan0);
  200. // this is dangerous bc we ignore stride.. but it works and is FAST! ;)
  201. if (bResize)
  202. {
  203. if (!s_bIluLoaded)
  204. {
  205. LoadILU();
  206. }
  207. if (s_bIluLoaded)
  208. {
  209. pfnIluImageParameter(ILU_FILTER, (int)(i_eFilter));
  210. pfnIluScale(iW, iH, 1);
  211. }
  212. else
  213. {
  214. s_eErrCode = ILU_DLL_NOT_FOUND;
  215. return NULL;
  216. }
  217. }
  218. ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE); // support for non 32bit images..
  219. ilCopyPixels(0, 0, 0, iW, iH, 1, IL_BGRA, IL_UNSIGNED_BYTE, pScan0);
  220. ilDeleteImages(1, &s_iImageID);
  221. pBmp->UnlockBits(pBd);
  222. return pBmp;
  223. }
  224. bool DevIL::DevIL::SaveBitmap(System::String __gc* i_szFileName, System::Drawing::Bitmap __gc* i_poBitmap)
  225. {
  226. if (!s_bInitDone)
  227. {
  228. ilInit();
  229. s_bInitDone = true;
  230. }
  231. ilGenImages(1, &s_iImageID);
  232. ilBindImage(s_iImageID);
  233. int iW = i_poBitmap->get_Width();
  234. int iH = i_poBitmap->get_Height();
  235. System::Drawing::Rectangle rect; rect.X = 0; rect.Y = 0; rect.Width = iW; rect.Height = iH;
  236. i_poBitmap->RotateFlip(System::Drawing::RotateFlipType::RotateNoneFlipY);
  237. System::Drawing::Imaging::BitmapData __gc* pBd = i_poBitmap->LockBits(rect,
  238. System::Drawing::Imaging::ImageLockMode::ReadOnly,
  239. System::Drawing::Imaging::PixelFormat::Format32bppArgb);
  240. void* pScan0 = (void*)(pBd->Scan0);
  241. bool bSuccess = 0!= ilTexImage(iW, iH, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, pScan0);
  242. if (!bSuccess)
  243. {
  244. return false;
  245. }
  246. bool bRes = ilSaveImage(StringAutoMarshal(i_szFileName))!=0;
  247. ilDeleteImages(1, &s_iImageID);
  248. i_poBitmap->UnlockBits(pBd);
  249. i_poBitmap->RotateFlip(System::Drawing::RotateFlipType::RotateNoneFlipY);
  250. return bRes;
  251. }