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

Visual C++

  1. //-----------------------------------------------------------------------------
  2. //
  3. // ImageLib Sources
  4. // Copyright (C) 2000-2008 by Denton Woods
  5. // Last modified: 12/17/2008
  6. //
  7. // Filename: src-IL/src/il_stack.c
  8. //
  9. // Description: The main image stack
  10. //
  11. //-----------------------------------------------------------------------------
  12. // Credit goes to John Villar (johnny@reliaschev.com) for making the suggestion
  13. // of not letting the user use ILimage structs but instead binding images
  14. // like OpenGL.
  15. #include "il_internal.h"
  16. #include "il_logging.h"
  17. #include "il_stack.h"
  18. //! Creates Num images and puts their index in Images - similar to glGenTextures().
  19. void ILAPIENTRY ilGenImages(ILsizei Num, ILuint *Images)
  20. {
  21. ILsizei Index = 0;
  22. iFree *TempFree = FreeNames;
  23. if (Num < 1 || Images == NULL) {
  24. ilSetError(IL_INVALID_VALUE);
  25. return;
  26. }
  27. // No images have been generated yet, so create the image stack.
  28. if (ImageStack == NULL)
  29. if (!iEnlargeStack())
  30. return;
  31. do {
  32. if (FreeNames != NULL) {  // If any have been deleted, then reuse their image names.
  33.                         TempFree = (iFree*)FreeNames->Next;
  34.                         Images[Index] = FreeNames->Name;
  35.                         ImageStack[FreeNames->Name] = ilNewImage(1, 1, 1, 1, 1);
  36.                         ifree(FreeNames);
  37.                         FreeNames = TempFree;
  38. } else {
  39.                         if (LastUsed >= StackSize)
  40. if (!iEnlargeStack())
  41. return;
  42. Images[Index] = LastUsed;
  43. // Must be all 1's instead of 0's, because some functions would divide by 0.
  44. ImageStack[LastUsed] = ilNewImage(1, 1, 1, 1, 1);
  45. LastUsed++;
  46. }
  47. } while (++Index < Num);
  48. LOG_ADVANCED(IL_LOG_INFO, _("ilGenImages: Generated %u images, the first is %u"), Num, Images[0]);
  49. return;
  50. }
  51. ILuint ILAPIENTRY ilGenImage()
  52. {
  53.     ILuint i;
  54.     ilGenImages(1,&i);
  55.     return i;
  56. }
  57. //! Makes Image the current active image - similar to glBindTexture().
  58. void ILAPIENTRY ilBindImage(ILuint Image)
  59. {
  60. if (ImageStack == NULL || StackSize == 0) {
  61. if (!iEnlargeStack()) {
  62. return;
  63. }
  64. }
  65. // If the user requests a high image name.
  66. while (Image >= StackSize) {
  67. if (!iEnlargeStack()) {
  68. return;
  69. }
  70. }
  71. if (ImageStack[Image] == NULL) {
  72. ImageStack[Image] = ilNewImage(1, 1, 1, 1, 1);
  73. if (Image >= LastUsed) // >= ?
  74. LastUsed = Image + 1;
  75. }
  76. iCurImage = ImageStack[Image];
  77. CurName = Image;
  78. LOG_ADVANCED(IL_LOG_VERBOSE, _("ilBindImage: The current image is now %u"), Image);
  79. ParentImage = IL_TRUE;
  80. return;
  81. }
  82. //! Deletes Num images from the image stack - similar to glDeleteTextures().
  83. void ILAPIENTRY ilDeleteImages(ILsizei Num, const ILuint *Images)
  84. {
  85. iFree *Temp = FreeNames;
  86. ILuint Index = 0;
  87. if (Num < 1) {
  88. //ilSetError(IL_INVALID_VALUE);
  89. return;
  90. }
  91. if (StackSize == 0)
  92. return;
  93. LOG_ADVANCED(IL_LOG_INFO, _("ilDeleteImages: Deleted %u images, the first one was %u"), Num, * Images);
  94. do {
  95. if (Images[Index] > 0 && Images[Index] < LastUsed) {  // <= ?
  96. /*if (FreeNames != NULL) {  // Terribly inefficient
  97. Temp = FreeNames;
  98. do {
  99. if (Temp->Name == Images[Index]) {
  100. continue;  // Sufficient?
  101. }
  102. } while ((Temp = Temp->Next));
  103. }*/
  104. // Already has been deleted or was never used.
  105. if (ImageStack[Images[Index]] == NULL)
  106. continue;
  107. // Find out if current image - if so, set to default image zero.
  108. if (Images[Index] == CurName || Images[Index] == 0) {
  109. iCurImage = ImageStack[0];
  110. CurName = 0;
  111. }
  112. // Should *NOT* be NULL here!
  113. ilCloseImage(ImageStack[Images[Index]]);
  114. ImageStack[Images[Index]] = NULL;
  115. // Add to head of list - works for empty and non-empty lists
  116. Temp = (iFree*)ialloc(sizeof(iFree));
  117. if (!Temp) {
  118. return;
  119. }
  120. Temp->Name = Images[Index];
  121. Temp->Next = FreeNames;
  122. FreeNames = Temp;
  123. }
  124. /*else {  // Shouldn't set an error...just continue onward.
  125. ilSetError(IL_ILLEGAL_OPERATION);
  126. }*/
  127. } while (++Index < (ILuint)Num);
  128. }
  129. void ILAPIENTRY ilDeleteImage(const ILuint Num) {
  130.     ilDeleteImages(1,&Num);
  131. }
  132. //! Checks if Image is a valid ilGenImages-generated image (like glIsTexture()).
  133. ILboolean ILAPIENTRY ilIsImage(ILuint Image)
  134. {
  135. //iFree *Temp = FreeNames;
  136. if (ImageStack == NULL)
  137. return IL_FALSE;
  138. if (Image >= LastUsed || Image == 0)
  139. return IL_FALSE;
  140. /*do {
  141. if (Temp->Name == Image)
  142. return IL_FALSE;
  143. } while ((Temp = Temp->Next));*/
  144. if (ImageStack[Image] == NULL)  // Easier check.
  145. return IL_FALSE;
  146. return IL_TRUE;
  147. }
  148. //! Closes Image and frees all memory associated with it.
  149. ILAPI void ILAPIENTRY ilCloseImage(ILimage *Image)
  150. {
  151. if (Image == NULL)
  152. return;
  153. if (Image->Data != NULL) {
  154. ifree(Image->Data);
  155. Image->Data = NULL;
  156. }
  157. if (Image->Pal.Palette != NULL && Image->Pal.PalSize > 0 && Image->Pal.PalType != IL_PAL_NONE) {
  158. ifree(Image->Pal.Palette);
  159. Image->Pal.Palette = NULL;
  160. }
  161. if (Image->Next != NULL) {
  162. ilCloseImage(Image->Next);
  163. Image->Next = NULL;
  164. }
  165. if (Image->Faces != NULL) {
  166. ilCloseImage(Image->Faces);
  167. Image->Mipmaps = NULL;
  168. }
  169. if (Image->Mipmaps != NULL) {
  170. ilCloseImage(Image->Mipmaps);
  171. Image->Mipmaps = NULL;
  172. }
  173. if (Image->Layers != NULL) {
  174. ilCloseImage(Image->Layers);
  175. Image->Layers = NULL;
  176. }
  177. if (Image->AnimList != NULL && Image->AnimSize != 0) {
  178. ifree(Image->AnimList);
  179. Image->AnimList = NULL;
  180. }
  181. if (Image->Profile != NULL && Image->ProfileSize != 0) {
  182. ifree(Image->Profile);
  183. Image->Profile = NULL;
  184. Image->ProfileSize = 0;
  185. }
  186. if (Image->DxtcData != NULL && Image->DxtcFormat != IL_DXT_NO_COMP) {
  187. ifree(Image->DxtcData);
  188. Image->DxtcData = NULL;
  189. Image->DxtcFormat = IL_DXT_NO_COMP;
  190. Image->DxtcSize = 0;
  191. }
  192. ifree(Image);
  193. Image = NULL;
  194. return;
  195. }
  196. ILAPI ILboolean ILAPIENTRY ilIsValid_PAL(ILpal *Palette)
  197. {
  198. if (Palette == NULL)
  199. return IL_FALSE;
  200. if (Palette->PalSize == 0 || Palette->Palette == NULL)
  201. return IL_FALSE;
  202. switch (Palette->PalType)
  203. {
  204. case IL_PAL_RGB24:
  205. case IL_PAL_RGB32:
  206. case IL_PAL_RGBA32:
  207. case IL_PAL_BGR24:
  208. case IL_PAL_BGR32:
  209. case IL_PAL_BGRA32:
  210. return IL_TRUE;
  211. }
  212. return IL_FALSE;
  213. }
  214. //! Closes Palette and frees all memory associated with it.
  215. ILAPI void ILAPIENTRY ilClosePal(ILpal *Palette)
  216. {
  217. if (Palette == NULL)
  218. return;
  219. if (!ilIsValid_PAL(Palette))
  220. return;
  221. ifree(Palette->Palette);
  222. ifree(Palette);
  223. return;
  224. }
  225. ILimage *iGetBaseImage()
  226. {
  227. return ImageStack[ilGetCurName()];
  228. }
  229. //! Sets the current mipmap level
  230. ILboolean ILAPIENTRY ilActiveMipmap(ILuint Number)
  231. {
  232. ILuint Current;
  233.     ILimage *iTempImage;
  234. if (iCurImage == NULL) {
  235. ilSetError(IL_ILLEGAL_OPERATION);
  236. return IL_FALSE;
  237. }
  238. if (Number == 0) {
  239. return IL_TRUE;
  240. }
  241.     iTempImage = iCurImage;
  242. iCurImage = iCurImage->Mipmaps;
  243. if (iCurImage == NULL) {
  244. iCurImage = iTempImage;
  245. ilSetError(IL_ILLEGAL_OPERATION);
  246. return IL_FALSE;
  247. }
  248. for (Current = 1; Current < Number; Current++) {
  249. iCurImage = iCurImage->Mipmaps;
  250. if (iCurImage == NULL) {
  251. ilSetError(IL_ILLEGAL_OPERATION);
  252. iCurImage = iTempImage;
  253. return IL_FALSE;
  254. }
  255. }
  256. ParentImage = IL_FALSE;
  257. return IL_TRUE;
  258. }
  259. //! Used for setting the current image if it is an animation.
  260. ILboolean ILAPIENTRY ilActiveImage(ILuint Number)
  261. {
  262. ILuint Current;
  263.     ILimage *iTempImage;
  264.     
  265. if (iCurImage == NULL) {
  266. ilSetError(IL_ILLEGAL_OPERATION);
  267. return IL_FALSE;
  268. }
  269. if (Number == 0) {
  270. return IL_TRUE;
  271. }
  272.     iTempImage = iCurImage;
  273. iCurImage = iCurImage->Next;
  274. if (iCurImage == NULL) {
  275. iCurImage = iTempImage;
  276. ilSetError(IL_ILLEGAL_OPERATION);
  277. return IL_FALSE;
  278. }
  279. Number--;  // Skip 0 (parent image)
  280. for (Current = 0; Current < Number; Current++) {
  281. iCurImage = iCurImage->Next;
  282. if (iCurImage == NULL) {
  283. ilSetError(IL_ILLEGAL_OPERATION);
  284. iCurImage = iTempImage;
  285. return IL_FALSE;
  286. }
  287. }
  288. ParentImage = IL_FALSE;
  289. return IL_TRUE;
  290. }
  291. //! Used for setting the current face if it is a cubemap.
  292. ILboolean ILAPIENTRY ilActiveFace(ILuint Number)
  293. {
  294. ILuint Current;
  295.     ILimage *iTempImage;
  296. if (iCurImage == NULL) {
  297. ilSetError(IL_ILLEGAL_OPERATION);
  298. return IL_FALSE;
  299. }
  300. if (Number == 0) {
  301. return IL_TRUE;
  302. }
  303.     iTempImage = iCurImage;
  304. iCurImage = iCurImage->Faces;
  305. if (iCurImage == NULL) {
  306. iCurImage = iTempImage;
  307. ilSetError(IL_ILLEGAL_OPERATION);
  308. return IL_FALSE;
  309. }
  310. //Number--;  // Skip 0 (parent image)
  311. for (Current = 1; Current < Number; Current++) {
  312. iCurImage = iCurImage->Faces;
  313. if (iCurImage == NULL) {
  314. ilSetError(IL_ILLEGAL_OPERATION);
  315. iCurImage = iTempImage;
  316. return IL_FALSE;
  317. }
  318. }
  319. ParentImage = IL_FALSE;
  320. return IL_TRUE;
  321. }
  322. //! Used for setting the current layer if layers exist.
  323. ILboolean ILAPIENTRY ilActiveLayer(ILuint Number)
  324. {
  325. ILuint Current;
  326.     ILimage *iTempImage;
  327. if (iCurImage == NULL) {
  328. ilSetError(IL_ILLEGAL_OPERATION);
  329. return IL_FALSE;
  330. }
  331. if (Number == 0) {
  332. return IL_TRUE;
  333. }
  334.     iTempImage = iCurImage;
  335. iCurImage = iCurImage->Layers;
  336. if (iCurImage == NULL) {
  337. iCurImage = iTempImage;
  338. ilSetError(IL_ILLEGAL_OPERATION);
  339. return IL_FALSE;
  340. }
  341. //Number--;  // Skip 0 (parent image)
  342. for (Current = 1; Current < Number; Current++) {
  343. iCurImage = iCurImage->Layers;
  344. if (iCurImage == NULL) {
  345. ilSetError(IL_ILLEGAL_OPERATION);
  346. iCurImage = iTempImage;
  347. return IL_FALSE;
  348. }
  349. }
  350. ParentImage = IL_FALSE;
  351. return IL_TRUE;
  352. }
  353. ILuint ILAPIENTRY ilCreateSubImage(ILenum Type, ILuint Num)
  354. {
  355. ILimage *SubImage;
  356. ILuint Count ;  // Create one before we go in the loop.
  357. if (iCurImage == NULL) {
  358. ilSetError(IL_ILLEGAL_OPERATION);
  359. return 0;
  360. }
  361. if (Num == 0)  {
  362. return 0;
  363. }
  364. switch (Type)
  365. {
  366. case IL_SUB_NEXT:
  367. if (iCurImage->Next)
  368. ilCloseImage(iCurImage->Next);
  369. iCurImage->Next = ilNewImage(1, 1, 1, 1, 1);
  370. SubImage = iCurImage->Next;
  371. break;
  372. case IL_SUB_MIPMAP:
  373. if (iCurImage->Mipmaps)
  374. ilCloseImage(iCurImage->Mipmaps);
  375. iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1);
  376. SubImage = iCurImage->Mipmaps;
  377. break;
  378. case IL_SUB_LAYER:
  379. if (iCurImage->Layers)
  380. ilCloseImage(iCurImage->Layers);
  381. iCurImage->Layers = ilNewImage(1, 1, 1, 1, 1);
  382. SubImage = iCurImage->Layers;
  383. break;
  384. default:
  385. ilSetError(IL_INVALID_ENUM);
  386. return IL_FALSE;
  387. }
  388. if (SubImage == NULL) {
  389. return 0;
  390. }
  391. for (Count = 1; Count < Num; Count++) {
  392. SubImage->Next = ilNewImage(1, 1, 1, 1, 1);
  393. SubImage = SubImage->Next;
  394. if (SubImage == NULL)
  395. return Count;
  396. }
  397. return Count;
  398. }
  399. // Returns the current index.
  400. ILAPI ILuint ILAPIENTRY ilGetCurName()
  401. {
  402. if (iCurImage == NULL || ImageStack == NULL || StackSize == 0)
  403. return 0;
  404. return CurName;
  405. }
  406. // Returns the current image.
  407. ILAPI ILimage* ILAPIENTRY ilGetCurImage()
  408. {
  409. return iCurImage;
  410. }
  411. // To be only used when the original image is going to be set back almost immediately.
  412. ILAPI void ILAPIENTRY ilSetCurImage(ILimage *Image)
  413. {
  414. iCurImage = Image;
  415. return;
  416. }
  417. // Completely replaces the current image and the version in the image stack.
  418. ILAPI void ILAPIENTRY ilReplaceCurImage(ILimage *Image)
  419. {
  420. if (iCurImage) {
  421. ilActiveImage(0);
  422. ilCloseImage(iCurImage);
  423. }
  424. ImageStack[ilGetCurName()] = Image;
  425. iCurImage = Image;
  426. ParentImage = IL_TRUE;
  427. return;
  428. }
  429. // Like realloc but sets new memory to 0.
  430. void* ILAPIENTRY ilRecalloc(void *Ptr, ILuint OldSize, ILuint NewSize)
  431. {
  432. void *Temp = ialloc(NewSize);
  433. ILuint CopySize = (OldSize < NewSize) ? OldSize : NewSize;
  434. if (Temp != NULL) {
  435. if (Ptr != NULL) {
  436. memcpy(Temp, Ptr, CopySize);
  437. ifree(Ptr);
  438. }
  439. Ptr = Temp;
  440. if (OldSize < NewSize)
  441. imemclear((ILubyte*)Temp + OldSize, NewSize - OldSize);
  442. }
  443. return Temp;
  444. }
  445. // Internal function to enlarge the image stack by I_STACK_INCREMENT members.
  446. ILboolean iEnlargeStack()
  447. {
  448. // 02-05-2001:  Moved from ilGenImages().
  449. // Puts the cleanup function on the exit handler once.
  450. if (!OnExit) {
  451. #ifdef _MEM_DEBUG
  452. AddToAtexit();  // So iFreeMem doesn't get called after unfreed information.
  453. #endif//_MEM_DEBUG
  454. #if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
  455. atexit((void*)ilShutDown);
  456. #endif
  457. OnExit = IL_TRUE;
  458. }
  459. if (!(ImageStack = (ILimage**)ilRecalloc(ImageStack, StackSize * sizeof(ILimage*), (StackSize + I_STACK_INCREMENT) * sizeof(ILimage*)))) {
  460. return IL_FALSE;
  461. }
  462. StackSize += I_STACK_INCREMENT;
  463. return IL_TRUE;
  464. }
  465. static ILboolean IsInit = IL_FALSE;
  466. /** Call at startup.
  467.  *
  468.  * What exactly this function does can depends on whether DevIL has been built with modular support or static.
  469.  */
  470. void ILAPIENTRY ilInit()
  471. {
  472. // if it is already initialized skip initialization
  473. if (IsInit == IL_TRUE ) 
  474. return;
  475. INIT_LOGGING_IFNEEDED;
  476. INIT_LTDL_IFNEEDED;
  477. /* Some gettext (internationalization support)  */
  478. BIND_TEXTDOMAIN_IFNEEDED;
  479. /* OK, let's load modules and do the stuff */
  480. //Modules * mods = CREATE_MODULES_IFNEEDED;
  481. CREATE_MODULES_IFNEEDED(mods);
  482. /* Then let's fill in the formats */
  483. /* This is PARSED by the ./configure script during build, so don't write those lines in funny ways
  484.  * unless you have malicious intentions. 
  485.  * Doing like
  486.  * SET_FORMAT(& Formats[IL_BMP], mods, BMP, "bmp"); 
  487.  * should be OK 
  488.  */
  489. SET_FORMAT(& Formats[IL_BMP], mods, BMP, "bmp");
  490. SET_FORMAT(& Formats[IL_CUT], mods, CUT, "cut");
  491. SET_FORMAT(& Formats[IL_CHEAD], mods, CHEAD, "h");
  492. SET_FORMAT(& Formats[IL_DCX], mods, DCX, "dcx");
  493. SET_FORMAT(& Formats[IL_DDS], mods, DDS, "dds");
  494. SET_FORMAT(& Formats[IL_DOOM], mods, DOOM, "wad");
  495. SET_FORMAT(& Formats[IL_EXR], mods, EXR, "exr");
  496. SET_FORMAT(& Formats[IL_FITS], mods, FITS, "fits fit");
  497. SET_FORMAT(& Formats[IL_GIF], mods, GIF, "gif");
  498. SET_FORMAT(& Formats[IL_HDR], mods, HDR, "hdr");
  499. SET_FORMAT(& Formats[IL_ICNS], mods, ICNS, "icns");
  500. SET_FORMAT(& Formats[IL_ICON], mods, ICON, "ico cur");
  501. SET_FORMAT(& Formats[IL_IFF], mods, IFF, "iff ilbm lbm");
  502. SET_FORMAT(& Formats[IL_ILBM], mods, ILBM, "ilbm");
  503. SET_FORMAT(& Formats[IL_JPEG], mods, JPEG, "jpeg jpg jpe");
  504. SET_FORMAT(& Formats[IL_JP2], mods, JP2, "jp2");
  505. SET_FORMAT(& Formats[IL_LIF], mods, LIF, "lif");
  506. SET_FORMAT(& Formats[IL_MDL], mods, MDL, "mdl");
  507. SET_FORMAT(& Formats[IL_MNG], mods, MNG, "mng");
  508. SET_FORMAT(& Formats[IL_PCX], mods, PCX, "pcx");
  509. SET_FORMAT(& Formats[IL_PCD], mods, PCD, "pcd");
  510. SET_FORMAT(& Formats[IL_PIC], mods, PIC, "pic");
  511. SET_FORMAT(& Formats[IL_PIX], mods, PIX, "pix");
  512. SET_FORMAT(& Formats[IL_PNG], mods, PNG, "png");
  513. SET_FORMAT(& Formats[IL_PNM], mods, PNM, "pnm pbm pgm ppm");
  514. SET_FORMAT(& Formats[IL_PSD], mods, PSD, "psd");
  515. SET_FORMAT(& Formats[IL_PSP], mods, PSP, "psp");
  516. SET_FORMAT(& Formats[IL_PXR], mods, PXR, "pxr");
  517. SET_FORMAT(& Formats[IL_RAW], mods, RAW, "raw");
  518. SET_FORMAT(& Formats[IL_ROT], mods, ROT, "rot");
  519. SET_FORMAT(& Formats[IL_SGI], mods, SGI, "sgi bw rgb rgba");
  520. SET_FORMAT(& Formats[IL_SUN], mods, SUN, "sun ras rs im1 im8 im24 im32");
  521. SET_FORMAT(& Formats[IL_TEXTURE], mods, TEXTURE, "texture");
  522. SET_FORMAT(& Formats[IL_TGA], mods, TGA, "tga vda icb vst");
  523. SET_FORMAT(& Formats[IL_TIFF], mods, TIFF, "tiff tif");
  524. SET_FORMAT(& Formats[IL_TPL], mods, TPL, "tpl");
  525. SET_FORMAT(& Formats[IL_UTX], mods, UTX, "utx");
  526. SET_FORMAT(& Formats[IL_VTF], mods, VTF, "vtf");
  527. SET_FORMAT(& Formats[IL_WAL], mods, WAL, "wal");
  528. SET_FORMAT(& Formats[IL_WBMP], mods, WBMP, "wbmp");
  529. SET_FORMAT(& Formats[IL_WDP], mods, WDP, "wdp");
  530. SET_FORMAT(& Formats[IL_XPM], mods, XPM, "xpm");
  531. SET_FORMAT(& Formats[IL_BLP], mods, BLP, "blp");
  532. SET_FORMAT(& Formats[IL_IWI], mods, IWI, "iwi");
  533. SET_FORMAT(& Formats[IL_FTX], mods, FTX, "ftx");
  534. SET_FORMAT(& Formats[IL_DICOM], mods, DICOM, "dicom dcm");
  535. /* The original ilInit continues... */
  536. //ilSetMemory(NULL, NULL);  Now useless 3/4/2006 (due to modification in il_alloc.c)
  537. ilSetError(IL_NO_ERROR);
  538. ilDefaultStates();  // Set states to their defaults.
  539. // Sets default file-reading callbacks.
  540. ilResetRead();
  541. ilResetWrite();
  542. #if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
  543. atexit((void*)ilRemoveRegistered);
  544. #endif
  545. //_WIN32_WCE
  546. //ilShutDown();
  547. iSetImage0();  // Beware!  Clears all existing textures!
  548. iBindImageTemp();  // Go ahead and create the temporary image.
  549. IsInit = IL_TRUE;
  550. return;
  551. }
  552. // Frees any extra memory in the stack.
  553. // - Called on exit
  554. void ILAPIENTRY ilShutDown()
  555. {
  556. // if it is not initialized do not shutdown
  557. iFree* TempFree = (iFree*)FreeNames;
  558. ILuint i;
  559. if (!IsInit)
  560. return;
  561. if (!IsInit) {  // Prevent from being called when not initialized.
  562. ilSetError(IL_ILLEGAL_OPERATION);
  563. return;
  564. }
  565. while (TempFree != NULL) {
  566. FreeNames = (iFree*)TempFree->Next;
  567. ifree(TempFree);
  568. TempFree = FreeNames;
  569. }
  570. //for (i = 0; i < LastUsed; i++) {
  571. for (i = 0; i < StackSize; i++) {
  572. if (ImageStack[i] != NULL)
  573. ilCloseImage(ImageStack[i]);
  574. }
  575. if (ImageStack)
  576. ifree(ImageStack);
  577. ImageStack = NULL;
  578. LastUsed = 0;
  579. StackSize = 0;
  580. IL_LOG_IFNEEDED(_("Thank you for closing DevIL properly, bye bye."), IL_LOG_INFO);
  581. IsInit = IL_FALSE;
  582. return;
  583. }
  584. // Initializes the image stack's first entry (default image) -- ONLY CALL ONCE!
  585. void iSetImage0()
  586. {
  587. if (ImageStack == NULL)
  588. if (!iEnlargeStack())
  589. return;
  590. LastUsed = 1;
  591. CurName = 0;
  592. ParentImage = IL_TRUE;
  593. if (!ImageStack[0])
  594. ImageStack[0] = ilNewImage(1, 1, 1, 1, 1);
  595. iCurImage = ImageStack[0];
  596. ilDefaultImage();
  597. return;
  598. }
  599. ILAPI void ILAPIENTRY iBindImageTemp()
  600. {
  601. if (ImageStack == NULL || StackSize <= 1)
  602. if (!iEnlargeStack())
  603. return;
  604. if (LastUsed < 2)
  605. LastUsed = 2;
  606. CurName = 1;
  607. ParentImage = IL_TRUE;
  608. if (!ImageStack[1])
  609. ImageStack[1] = ilNewImage(1, 1, 1, 1, 1);
  610. iCurImage = ImageStack[1];
  611. return;
  612. }