il_io.c
Upload User: wmy0603
Upload Date: 2022-05-02
Package Size: 1808k
Code Size: 13k
Development Platform:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. //
  3. // ImageLib Sources
  4. // Copyright (C) 2000-2009 by Denton Woods
  5. // Last modified: 03/07/2009
  6. //
  7. // Filename: src-IL/src/il_io.c
  8. //
  9. // Description: Determines image types and loads/saves images
  10. //
  11. //-----------------------------------------------------------------------------
  12. #include "il_internal.h"
  13. #include "il_register.h"
  14. #include "il_pal.h"
  15. #include <string.h>
  16. // Returns a widened version of a string.
  17. // Make sure to free this after it is used.  Code help from
  18. //  https://buildsecurityin.us-cert.gov/daisy/bsi-rules/home/g1/769-BSI.html
  19. #if defined(_UNICODE)
  20. wchar_t *WideFromMultiByte(const char *Multi)
  21. {
  22. ILint Length;
  23. wchar_t *Temp;
  24. Length = (ILint)mbstowcs(NULL, (const char*)Multi, 0) + 1; // note error return of -1 is possible
  25. if (Length == 0) {
  26. ilSetError(IL_INVALID_PARAM);
  27. return NULL;
  28. }
  29. if (Length > ULONG_MAX/sizeof(wchar_t)) {
  30. ilSetError(IL_INTERNAL_ERROR);
  31. return NULL;
  32. }
  33. Temp = (wchar_t*)ialloc(Length * sizeof(wchar_t));
  34. mbstowcs(Temp, (const char*)Multi, Length); 
  35. return Temp;
  36. }
  37. #endif
  38. ILenum ILAPIENTRY ilTypeFromExt(ILconst_string FileName)
  39. {
  40. ILenum Type;
  41. ILstring Ext;
  42. if (FileName == NULL || ilStrLen(FileName) < 1) {
  43. ilSetError(IL_INVALID_PARAM);
  44. return IL_TYPE_UNKNOWN;
  45. }
  46. Ext = iGetExtension(FileName);
  47. //added 2003-08-31: fix sf bug 789535
  48. if (Ext == NULL) {
  49. return IL_TYPE_UNKNOWN;
  50. }
  51. Type = IL_TYPE_UNKNOWN;
  52. int i, j;
  53. for (i = 0; i < IL_FORMATS_COUNT && Type != IL_TYPE_UNKNOWN; i++)
  54. {
  55. if (Formats[i].Extensions == NULL)
  56. continue;
  57. for (j = 0; Formats[i].Extensions[j] != NULL; j++)
  58. if (!iStrCmp(Ext, Formats[i].Extensions[j]))
  59. {
  60. Type = i;
  61. break;
  62. }
  63. }
  64. return Type;
  65. }
  66. //changed 2003-09-17 to ILAPIENTRY
  67. ILenum ILAPIENTRY ilDetermineType(ILconst_string FileName)
  68. {
  69. ILHANDLE File;
  70. ILenum Type;
  71. if (FileName == NULL)
  72. return IL_TYPE_UNKNOWN;
  73. File = iopenr(FileName);
  74. if (File == NULL) {
  75. ilSetError(IL_COULD_NOT_OPEN_FILE);
  76. return IL_FALSE;
  77. }
  78. Type = ilDetermineTypeF(File);
  79. icloser(File);
  80. return Type;
  81. }
  82. ILenum ILAPIENTRY ilDetermineTypeF(ILHANDLE File)
  83. {
  84. if (File == NULL)
  85. return IL_TYPE_UNKNOWN;
  86. int i;
  87. for (i = 0; i < IL_FORMATS_COUNT; i++)
  88. {
  89. if (Formats[i].Extensions == NULL)
  90. continue;
  91. if (Formats[i].Callbacks.ilIsValidF == NULL)
  92. continue;
  93. else if ( Formats[i].Callbacks.ilIsValidF(File) )
  94. return i;
  95. }
  96. return IL_TYPE_UNKNOWN;
  97. }
  98. ILenum ILAPIENTRY ilDetermineTypeL(const void *Lump, ILuint Size)
  99. {
  100. if (Lump == NULL)
  101. return IL_TYPE_UNKNOWN;
  102. int i;
  103. for (i = 0; i < IL_FORMATS_COUNT; i++)
  104. {
  105. if (Formats[i].Extensions == NULL)
  106. continue;
  107. if (Formats[i].Callbacks.ilIsValidL == NULL)
  108. continue;
  109. else if ( Formats[i].Callbacks.ilIsValidL(Lump, Size) )
  110. return i;
  111. }
  112. return IL_TYPE_UNKNOWN;
  113. }
  114. ILboolean ILAPIENTRY ilIsValid(ILenum Type, ILconst_string FileName)
  115. {
  116. if (FileName == NULL) {
  117. ilSetError(IL_INVALID_PARAM);
  118. return IL_FALSE;
  119. }
  120. if (Formats[Type].Callbacks.ilIsValid == NULL)
  121. {
  122. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  123. return IL_FALSE;
  124. }
  125.         if (Formats[Type].Callbacks.ilIsValid(FileName) == IL_FALSE)
  126. {
  127. ilSetError(IL_INVALID_ENUM);
  128. return IL_FALSE;
  129. }
  130. return IL_TRUE;
  131. }
  132. ILboolean ILAPIENTRY ilIsValidF(ILenum Type, ILHANDLE File)
  133. {
  134. if (File == NULL) {
  135. ilSetError(IL_INVALID_PARAM);
  136. return IL_FALSE;
  137. }
  138. if (Formats[Type].Callbacks.ilIsValidF == NULL)
  139. {
  140. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  141. return IL_FALSE;
  142. }
  143. return Formats[Type].Callbacks.ilIsValidF(File);
  144. ilSetError(IL_INVALID_ENUM);
  145. return IL_FALSE;
  146. }
  147. ILboolean ILAPIENTRY ilIsValidL(ILenum Type, void *Lump, ILuint Size)
  148. {
  149. if (Lump == NULL) {
  150. ilSetError(IL_INVALID_PARAM);
  151. return IL_FALSE;
  152. }
  153. if (Formats[Type].Callbacks.ilIsValidL == NULL)
  154. {
  155. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  156. return IL_FALSE;
  157. }
  158. return Formats[Type].Callbacks.ilIsValidL(Lump, Size);
  159. ilSetError(IL_INVALID_ENUM);
  160. return IL_FALSE;
  161. }
  162. //! Attempts to load an image from a file.  The file format is specified by the user.
  163. /*! param Type Format of this file.  Acceptable values are IL_BLP, IL_BMP, IL_CUT, IL_DCX, IL_DDS,
  164. IL_DICOM, IL_DOOM, IL_DOOM_FLAT, IL_DPX, IL_EXR, IL_FITS, IL_FTX, IL_GIF, IL_HDR, IL_ICO, IL_ICNS,
  165. IL_IFF, IL_IWI, IL_JP2, IL_JPG, IL_LIF, IL_MDL, IL_MNG, IL_MP3, IL_PCD, IL_PCX, IL_PIX, IL_PNG,
  166. IL_PNM, IL_PSD, IL_PSP, IL_PXR, IL_ROT, IL_SGI, IL_SUN, IL_TEXTURE, IL_TGA, IL_TIFF, IL_TPL,
  167. IL_UTX, IL_VTF, IL_WAL, IL_WBMP, IL_XPM, IL_RAW, IL_JASC_PAL and IL_TYPE_UNKNOWN.
  168. If IL_TYPE_UNKNOWN is specified, ilLoad will try to determine the type of the file and load it.
  169. param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives
  170.        the filename of the file to load.
  171. return Boolean value of failure or success.  Returns IL_FALSE if all three loading methods
  172.        have been tried and failed.*/
  173. ILboolean ILAPIENTRY ilLoad(ILenum Type, ILconst_string FileName)
  174. {
  175. ILboolean bRet;
  176. if (FileName == NULL || ilStrLen(FileName) < 1) {
  177. ilSetError(IL_INVALID_PARAM);
  178. return IL_FALSE;
  179. }
  180. if (Formats[Type].Callbacks.ilLoad == NULL)
  181. {
  182. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  183. return IL_FALSE;
  184. }
  185. bRet = Formats[Type].Callbacks.ilLoad(FileName);
  186. return bRet;
  187. }
  188. //! Attempts to load an image from a file stream.  The file format is specified by the user.
  189. /*! param Type Format of this file. You can look up acceptable values in include/IL/il.h.
  190. If IL_TYPE_UNKNOWN is specified, ilLoadF will try to determine the type of the file and load it.
  191. param File File stream to load from.
  192. return Boolean value of failure or success.  Returns IL_FALSE if loading fails.*/
  193. ILboolean ILAPIENTRY ilLoadF(ILenum Type, ILHANDLE File)
  194. {
  195. if (File == NULL) {
  196. ilSetError(IL_INVALID_PARAM);
  197. return IL_FALSE;
  198. }
  199. if (Type == IL_TYPE_UNKNOWN)
  200. Type = ilDetermineTypeF(File);
  201. if (Formats[Type].Callbacks.ilLoadF == NULL)
  202. {
  203. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  204. return IL_FALSE;
  205. }
  206. return Formats[Type].Callbacks.ilLoadF(File);
  207. ilSetError(IL_INVALID_ENUM);
  208. return IL_FALSE;
  209. }
  210. //! Attempts to load an image from a memory buffer.  The file format is specified by the user.
  211. /*! param Type Format of this file. You can look up acceptable values in include/IL/il.h.
  212. If IL_TYPE_UNKNOWN is specified, ilLoadL will try to determine the type of the file and load it.
  213. param Lump The buffer where the file data is located
  214. param Size Size of the buffer
  215. return Boolean value of failure or success.  Returns IL_FALSE if loading fails.*/
  216. ILboolean ILAPIENTRY ilLoadL(ILenum Type, const void *Lump, ILuint Size)
  217. {
  218. if (Lump == NULL || Size == 0) {
  219. ilSetError(IL_INVALID_PARAM);
  220. return IL_FALSE;
  221. }
  222. if (Type == IL_TYPE_UNKNOWN)
  223. Type = ilDetermineTypeL(Lump, Size);
  224. /* format name can be told in terms of its extension */
  225. if (Formats[Type].Callbacks.ilLoadL == NULL)
  226. {
  227. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  228. return IL_FALSE;
  229. }
  230. return Formats[Type].Callbacks.ilLoadL(Lump, Size);
  231. ilSetError(IL_INVALID_ENUM);
  232. return IL_FALSE;
  233. }
  234. //! Attempts to load an image from a file with various different methods before failing - very generic.
  235. /*! The ilLoadImage function allows a general interface to the specific internal file-loading
  236. routines.  First, it finds the extension and checks to see if any user-registered functions
  237. (registered through ilRegisterLoad) match the extension. If nothing matches, it takes the
  238. extension and determines which function to call based on it. Lastly, it attempts to identify
  239. the image based on various image header verification functions, such as ilIsValidPngF.
  240. If all this checking fails, IL_FALSE is returned with no modification to the current bound image.
  241. param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives
  242.        the filename of the file to load.
  243. return Boolean value of failure or success.  Returns IL_FALSE if all three loading methods
  244.        have been tried and failed.*/
  245. ILboolean ILAPIENTRY ilLoadImage(ILconst_string FileName)
  246. {
  247. ILstring Ext;
  248. ILenum Type;
  249. ILboolean bRet = IL_FALSE;
  250. LOG_ACTION_BEGIN(il_load_image, IL_LOG_INFO, "Trying to load file '%s'", FileName);
  251. if (iCurImage == NULL) {
  252. LOG_ACTION_END(il_load_image, LOG_RES_FAIL);
  253. ilSetError(IL_ILLEGAL_OPERATION);
  254. return IL_FALSE;
  255. }
  256. if (FileName == NULL || ilStrLen(FileName) < 1) {
  257. LOG_ACTION_END(il_load_image, LOG_RES_FAIL);
  258. ilSetError(IL_INVALID_PARAM);
  259. return IL_FALSE;
  260. }
  261. Ext = iGetExtension(FileName);
  262. // Try registered procedures first (so users can override default lib functions).
  263. if (iRegisterLoad(FileName))
  264. {
  265. LOG_ACTION_END(il_load_image, LOG_RES_OK);
  266. return IL_TRUE;
  267. }
  268. int i, j;
  269. for (i = 0; i < IL_FORMATS_COUNT; i++)
  270. {
  271. if (Formats[i].Extensions == NULL)
  272. continue;
  273. for (j = 0; Formats[i].Extensions[j] != NULL; j++)
  274. if (!iStrCmp(Ext, Formats[i].Extensions[j]))
  275. {
  276. if (Formats[i].Callbacks.ilLoad == NULL)
  277. {
  278. LOG_ACTION_END(il_load_image, LOG_RES_FAIL);
  279. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  280. return IL_FALSE;
  281. }
  282. bRet = Formats[i].Callbacks.ilLoad(FileName);
  283. goto finish;
  284. }
  285. }
  286. // As a last-ditch effort, try to identify the image
  287. Type = ilDetermineType(FileName);
  288. if (Type == IL_TYPE_UNKNOWN) {
  289. LOG_ACTION_END(il_load_image, LOG_RES_FAIL);
  290. ilSetError(IL_INVALID_EXTENSION);
  291. return IL_FALSE;
  292. }
  293. bRet = ilLoad(Type, FileName);
  294. finish:
  295. LOG_ACTION_END(il_load_image, (bRet == IL_TRUE) ? LOG_RES_OK : LOG_RES_FAIL);
  296. return bRet;
  297. }
  298. //! Attempts to save an image to a file.  The file format is specified by the user.
  299. /*! param Type Format of this file.  Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR,
  300. IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIFF,
  301. IL_VTF, IL_WBMP and IL_JASC_PAL.
  302. param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives
  303.        the filename to save to.
  304. return Boolean value of failure or success.  Returns IL_FALSE if saving failed.*/
  305. ILboolean ILAPIENTRY ilSave(ILenum Type, ILconst_string FileName)
  306. {
  307. if (Formats[Type].Callbacks.ilSave == NULL)
  308. {
  309. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  310. return IL_FALSE;
  311. }
  312. ILboolean retval =  Formats[Type].Callbacks.ilSave(FileName);
  313. if (retval == IL_FALSE)
  314. {
  315. ilSetError(IL_INVALID_ENUM);
  316. }
  317. else
  318. return retval;
  319. }
  320. //! Attempts to save an image to a file stream.  The file format is specified by the user.
  321. /*! param Type Format of this file.  Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR,
  322. IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIFF,
  323. IL_VTF, IL_WBMP and IL_JASC_PAL.
  324. param File File stream to save to.
  325. return Boolean value of failure or success.  Returns IL_FALSE if saving failed.*/
  326. ILuint ILAPIENTRY ilSaveF(ILenum Type, ILHANDLE File)
  327. {
  328. ILboolean Ret;
  329. if (File == NULL) {
  330. ilSetError(IL_INVALID_PARAM);
  331. return 0;
  332. }
  333. if (Formats[Type].Callbacks.ilSaveF == NULL)
  334. {
  335. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  336. return IL_FALSE;
  337. }
  338. return Formats[Type].Callbacks.ilSaveF(File);
  339. if (Ret == IL_FALSE)
  340. return 0;
  341. return itellw();
  342. }
  343. //! Attempts to save an image to a memory buffer.  The file format is specified by the user.
  344. /*! param Type Format of this image file.  Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR,
  345. IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIFF,
  346. IL_VTF, IL_WBMP and IL_JASC_PAL.
  347. param Lump Memory buffer to save to
  348. param Size Size of the memory buffer
  349. return Boolean value of failure or success.  Returns IL_FALSE if saving failed.*/
  350. ILuint ILAPIENTRY ilSaveL(ILenum Type, void *Lump, ILuint Size)
  351. {
  352. if (Lump == NULL) {
  353. if (Size != 0) {
  354. ilSetError(IL_INVALID_PARAM);
  355. return 0;
  356. }
  357. // The user wants to know how large of a buffer they need.
  358. else {
  359. return ilDetermineSize(Type);
  360. }
  361. }
  362. if (Formats[Type].Callbacks.ilSaveL == NULL)
  363. {
  364. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  365. return IL_FALSE;
  366. }
  367. return Formats[Type].Callbacks.ilSaveL(Lump, Size);
  368. ilSetError(IL_INVALID_ENUM);
  369. return 0;
  370. }
  371. /** Saves the current image based on the extension given in FileName.
  372.  * param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives the filename to save to.
  373.  * return Boolean value of failure or success.  Returns IL_FALSE if saving failed.
  374.  */
  375. ILboolean ILAPIENTRY ilSaveImage(ILconst_string FileName)
  376. {
  377. LOG_ACTION_BEGIN(save_image, IL_LOG_INFO, "Trying to save image to '%s'", FileName);
  378. ILstring Ext;
  379. ILboolean bRet = IL_FALSE;
  380. if (FileName == NULL || ilStrLen(FileName) < 1) {
  381. LOG_ACTION_END(save_image, LOG_RES_FAIL);
  382. ilSetError(IL_INVALID_PARAM);
  383. return IL_FALSE;
  384. }
  385. if (iCurImage == NULL) {
  386. LOG_ACTION_END(save_image, LOG_RES_FAIL);
  387. ilSetError(IL_ILLEGAL_OPERATION);
  388. return IL_FALSE;
  389. }
  390. Ext = iGetExtension(FileName);
  391. if (Ext == NULL) {
  392. LOG_ACTION_END(save_image, LOG_RES_FAIL);
  393. ilSetError(IL_INVALID_PARAM);
  394. return IL_FALSE;
  395. }
  396. int i, j;
  397. for (i = 0; i < IL_FORMATS_COUNT; i++)
  398. {
  399. if (Formats[i].Extensions == NULL)
  400. continue;
  401. for (j = 0; Formats[i].Extensions[j] != NULL; j++)
  402. if (!iStrCmp(Ext, Formats[i].Extensions[j]))
  403. {
  404. if (Formats[i].Callbacks.ilSave == NULL)
  405. {
  406. LOG_ACTION_END(save_image, LOG_RES_FAIL);
  407. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  408. return IL_FALSE;
  409. }
  410. bRet = Formats[i].Callbacks.ilSave(FileName);
  411. goto finish;
  412. }
  413. }
  414. // Try registered procedures
  415. if (iRegisterSave(FileName))
  416. {
  417. LOG_ACTION_END(save_image, LOG_RES_OK);
  418. return IL_TRUE;
  419. }
  420. LOG_ACTION_END(save_image, LOG_RES_FAIL);
  421. ilSetError(IL_INVALID_EXTENSION);
  422. return IL_FALSE;
  423. finish:
  424. LOG_ACTION_END(save_image,  (bRet == IL_TRUE) ? LOG_RES_OK : LOG_RES_FAIL);
  425. return bRet;
  426. }