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

Visual C++

  1. //-----------------------------------------------------------------------------
  2. //
  3. // ImageLib Sources
  4. // Copyright (C) 2000-2009 by Denton Woods
  5. // Last modified: 02/01/2009
  6. //
  7. // Filename: src-IL/src/il_devil.c
  8. //
  9. // Description: Functions for working with the ILimage's and the current image
  10. //
  11. //-----------------------------------------------------------------------------
  12. #include "il_internal.h"
  13. #include <string.h>
  14. #include <limits.h>
  15. #include "il_manip.h"
  16. ILAPI ILboolean ILAPIENTRY ilInitImage(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data)
  17. {
  18. ILubyte BpcType = ilGetBpcType(Type);
  19. if (BpcType == 0) {
  20. ilSetError(IL_INVALID_PARAM);
  21. return IL_FALSE;
  22. }
  23. memset(Image, 0, sizeof(ILimage));
  24. ////
  25. if (Width  == 0) Width = 1;
  26. if (Height == 0) Height = 1;
  27. if (Depth  == 0) Depth = 1;
  28. Image->Width    = Width;
  29. Image->Height    = Height;
  30. Image->Depth    = Depth;
  31. Image->Bpp    = Bpp;
  32. Image->Bpc    = BpcType;
  33. Image->Bps    = Width * Bpp * Image->Bpc;
  34. Image->SizeOfPlane = Image->Bps * Height;
  35. Image->SizeOfData  = Image->SizeOfPlane * Depth;
  36. Image->Format    = Format;
  37. Image->Type     = Type;
  38. Image->Origin    = IL_ORIGIN_LOWER_LEFT;
  39. Image->Pal.PalType = IL_PAL_NONE;
  40. Image->DxtcFormat  = IL_DXT_NO_COMP;
  41. Image->DxtcData    = NULL;
  42. Image->Data = (ILubyte*)ialloc(Image->SizeOfData);
  43. if (Image->Data == NULL) {
  44. return IL_FALSE;
  45. }
  46. if (Data != NULL) {
  47. memcpy(Image->Data, Data, Image->SizeOfData);
  48. }
  49. return IL_TRUE;
  50. }
  51. // Creates a new ILimage based on the specifications given
  52. ILAPI ILimage* ILAPIENTRY ilNewImage(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc)
  53. {
  54. ILimage *Image;
  55. if (Bpp == 0 || Bpp > 4) {
  56. return NULL;
  57. }
  58. Image = (ILimage*)ialloc(sizeof(ILimage));
  59. if (Image == NULL) {
  60. return NULL;
  61. }
  62. if (!ilInitImage(Image, Width, Height, Depth, Bpp, ilGetFormatBpp(Bpp), ilGetTypeBpc(Bpc), NULL)) {
  63. if (Image->Data != NULL) {
  64. ifree(Image->Data);
  65. }
  66. ifree(Image);
  67. return NULL;
  68. }
  69. return Image;
  70. }
  71. // Same as above but allows specification of Format and Type
  72. ILAPI ILimage* ILAPIENTRY ilNewImageFull(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data)
  73. {
  74. ILimage *Image;
  75. if (Bpp == 0 || Bpp > 4) {
  76. return NULL;
  77. }
  78. Image = (ILimage*)ialloc(sizeof(ILimage));
  79. if (Image == NULL) {
  80. return NULL;
  81. }
  82. if (!ilInitImage(Image, Width, Height, Depth, Bpp, Format, Type, Data)) {
  83. if (Image->Data != NULL) {
  84. ifree(Image->Data);
  85. }
  86. ifree(Image);
  87. return NULL;
  88. }
  89. return Image;
  90. }
  91. //! Changes the current bound image to use these new dimensions (current data is destroyed).
  92. /*! param Width Specifies the new image width.  This cannot be 0.
  93. param Height Specifies the new image height.  This cannot be 0.
  94. param Depth Specifies the new image depth.  This cannot be 0.
  95. param Bpp Number of channels (ex. 3 for RGB)
  96. param Format Enum of the desired format.  Any format values are accepted.
  97. param Type Enum of the desired type.  Any type values are accepted.
  98. param Data Specifies data that should be copied to the new image. If this parameter is NULL, no data is copied, and the new image data consists of undefined values.
  99. exception IL_ILLEGAL_OPERATION No currently bound image.
  100. exception IL_INVALID_PARAM One of the parameters is incorrect, such as one of the dimensions being 0.
  101. exception IL_OUT_OF_MEMORY Could not allocate enough memory.
  102. return Boolean value of failure or success*/
  103. ILboolean ILAPIENTRY ilTexImage(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data)
  104. {
  105. return ilTexImage_(iCurImage, Width, Height, Depth, Bpp, Format, Type, Data);
  106. }
  107. // Internal version of ilTexImage.
  108. ILAPI ILboolean ILAPIENTRY ilTexImage_(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data)
  109. {
  110. if (Image == NULL) {
  111. ilSetError(IL_ILLEGAL_OPERATION);
  112. return IL_FALSE;
  113. }
  114. ////
  115. // Not sure if we should be getting rid of the palette...
  116. if (Image->Pal.Palette && Image->Pal.PalSize && Image->Pal.PalType != IL_PAL_NONE) {
  117. ifree(Image->Pal.Palette);
  118. }
  119. ilCloseImage(Image->Mipmaps);
  120. ilCloseImage(Image->Next);
  121. ilCloseImage(Image->Faces);
  122. ilCloseImage(Image->Layers);
  123. if (Image->AnimList) ifree(Image->AnimList);
  124. if (Image->Profile)  ifree(Image->Profile);
  125. if (Image->DxtcData) ifree(Image->DxtcData);
  126. if (Image->Data)  ifree(Image->Data);
  127. ////
  128. //@TODO: Also check against format?
  129. /*if (Width == 0 || Height == 0 || Depth == 0 || Bpp == 0) {
  130. ilSetError(IL_INVALID_PARAM);
  131. return IL_FALSE;
  132. }*/
  133. return ilInitImage(Image, Width, Height, Depth, Bpp, Format, Type, Data);
  134. }
  135. //! Uploads Data of the same size to replace the current image's data.
  136. /*! param Data New image data to update the currently bound image
  137. exception IL_ILLEGAL_OPERATION No currently bound image
  138. exception IL_INVALID_PARAM Data was NULL.
  139. return Boolean value of failure or success
  140. */
  141. ILboolean ILAPIENTRY ilSetData(void *Data)
  142. {
  143. if (iCurImage == NULL) {
  144. ilSetError(IL_ILLEGAL_OPERATION);
  145. return IL_FALSE;
  146. }
  147. return ilTexSubImage_(iCurImage, Data);
  148. }
  149. // Internal version of ilTexSubImage.
  150. ILAPI ILboolean ILAPIENTRY ilTexSubImage_(ILimage *Image, void *Data)
  151. {
  152. if (Image == NULL || Data == NULL) {
  153. ilSetError(IL_INVALID_PARAM);
  154. return IL_FALSE;
  155. }
  156. if (!Image->Data) {
  157. Image->Data = (ILubyte*)ialloc(Image->SizeOfData);
  158. if (Image->Data == NULL)
  159. return IL_FALSE;
  160. }
  161. memcpy(Image->Data, Data, Image->SizeOfData);
  162. return IL_TRUE;
  163. }
  164. //! Returns a pointer to the current image's data.
  165. /*! The pointer to the image data returned by this function is only valid until any
  166.     operations are done on the image.  After any operations, this function should be
  167. called again.  The pointer can be cast to other types for images that have more
  168. than one byte per channel for easier access to data.
  169. exception IL_ILLEGAL_OPERATION No currently bound image
  170. return ILubyte pointer to image data.*/
  171. ILubyte* ILAPIENTRY ilGetData(void)
  172. {
  173. if (iCurImage == NULL) {
  174. ilSetError(IL_ILLEGAL_OPERATION);
  175. return NULL;
  176. }
  177. return iCurImage->Data;
  178. }
  179. //! Returns a pointer to the current image's palette data.
  180. /*! The pointer to the image palette data returned by this function is only valid until
  181. any operations are done on the image.  After any operations, this function should be
  182. called again.
  183. exception IL_ILLEGAL_OPERATION No currently bound image
  184. return ILubyte pointer to image palette data.*/
  185. ILubyte* ILAPIENTRY ilGetPalette(void)
  186. {
  187. if (iCurImage == NULL) {
  188. ilSetError(IL_ILLEGAL_OPERATION);
  189. return NULL;
  190. }
  191. return iCurImage->Pal.Palette;
  192. }
  193. //ILfloat ClearRed = 0.0f, ClearGreen = 0.0f, ClearBlue = 0.0f, ClearAlpha = 0.0f;
  194. // Changed to the colour of the Universe
  195. // (http://www.newscientist.com/news/news.jsp?id=ns99991775)
  196. // *(http://www.space.com/scienceastronomy/universe_color_020308.html)*
  197. //ILfloat ClearRed = 0.269f, ClearGreen = 0.388f, ClearBlue = 0.342f, ClearAlpha = 0.0f;
  198. static ILfloat ClearRed   = 1.0f;
  199. static ILfloat ClearGreen = 0.972549f;
  200. static ILfloat ClearBlue  = 0.90588f;
  201. static ILfloat ClearAlpha = 0.0f;
  202. static ILfloat ClearLum   = 1.0f;
  203. void ILAPIENTRY ilClearColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha)
  204. {
  205. // Clamp to 0.0f - 1.0f.
  206. ClearRed = Red < 0.0f ? 0.0f : (Red > 1.0f ? 1.0f : Red);
  207. ClearGreen = Green < 0.0f ? 0.0f : (Green > 1.0f ? 1.0f : Green);
  208. ClearBlue = Blue < 0.0f ? 0.0f : (Blue > 1.0f ? 1.0f : Blue);
  209. ClearAlpha = Alpha < 0.0f ? 0.0f : (Alpha > 1.0f ? 1.0f : Alpha);
  210. if ((Red == Green) && (Red == Blue) && (Green == Blue)) {
  211. ClearLum = Red < 0.0f ? 0.0f : (Red > 1.0f ? 1.0f : Red);
  212. }
  213. else {
  214. ClearLum = 0.212671f * ClearRed + 0.715160f * ClearGreen + 0.072169f * ClearBlue;
  215. ClearLum = ClearLum < 0.0f ? 0.0f : (ClearLum > 1.0f ? 1.0f : ClearLum);
  216. }
  217. return;
  218. }
  219. ILAPI void ILAPIENTRY ilGetClear(void *Colours, ILenum Format, ILenum Type)
  220. {
  221. ILubyte  *BytePtr;
  222. ILushort *ShortPtr;
  223. ILuint *IntPtr;
  224. ILfloat  *FloatPtr;
  225. ILdouble *DblPtr;
  226. switch (Type)
  227. {
  228. case IL_BYTE:
  229. case IL_UNSIGNED_BYTE:
  230. BytePtr = (ILubyte*)Colours;
  231. switch (Format)
  232. {
  233. case IL_RGB:
  234. BytePtr[0] = (ILubyte)(ClearRed * UCHAR_MAX);
  235. BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX);
  236. BytePtr[2] = (ILubyte)(ClearBlue * UCHAR_MAX);
  237. break;
  238. case IL_RGBA:
  239. BytePtr[0] = (ILubyte)(ClearRed * UCHAR_MAX);
  240. BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX);
  241. BytePtr[2] = (ILubyte)(ClearBlue * UCHAR_MAX);
  242. BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX);
  243. break;
  244. case IL_BGR:
  245. BytePtr[2] = (ILubyte)(ClearRed * UCHAR_MAX);
  246. BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX);
  247. BytePtr[0] = (ILubyte)(ClearBlue * UCHAR_MAX);
  248. BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX);
  249. break;
  250. case IL_BGRA:
  251. BytePtr[2] = (ILubyte)(ClearRed * UCHAR_MAX);
  252. BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX);
  253. BytePtr[0] = (ILubyte)(ClearBlue * UCHAR_MAX);
  254. BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX);
  255. break;
  256. case IL_LUMINANCE:
  257. BytePtr[0] = (ILubyte)(ClearAlpha * UCHAR_MAX);
  258. break;
  259. case IL_LUMINANCE_ALPHA:
  260. BytePtr[0] = (ILubyte)(ClearLum * UCHAR_MAX);
  261. BytePtr[1] = (ILubyte)(ClearAlpha * UCHAR_MAX);
  262. case IL_COLOUR_INDEX:
  263. BytePtr[0] = (ILubyte)(ClearAlpha * UCHAR_MAX);
  264. break;
  265. default:
  266. ilSetError(IL_INTERNAL_ERROR);
  267. return;
  268. }
  269. break;
  270. case IL_SHORT:
  271. case IL_UNSIGNED_SHORT:
  272. ShortPtr = (ILushort*)Colours;
  273. switch (Format)
  274. {
  275. case IL_RGB:
  276. ShortPtr[0] = (ILushort)(ClearRed * USHRT_MAX);
  277. ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX);
  278. ShortPtr[2] = (ILushort)(ClearBlue * USHRT_MAX);
  279. break;
  280. case IL_RGBA:
  281. ShortPtr[0] = (ILushort)(ClearRed * USHRT_MAX);
  282. ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX);
  283. ShortPtr[2] = (ILushort)(ClearBlue * USHRT_MAX);
  284. ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX);
  285. break;
  286. case IL_BGR:
  287. ShortPtr[2] = (ILushort)(ClearRed * USHRT_MAX);
  288. ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX);
  289. ShortPtr[0] = (ILushort)(ClearBlue * USHRT_MAX);
  290. ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX);
  291. break;
  292. case IL_BGRA:
  293. ShortPtr[2] = (ILushort)(ClearRed * USHRT_MAX);
  294. ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX);
  295. ShortPtr[0] = (ILushort)(ClearBlue * USHRT_MAX);
  296. ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX);
  297. break;
  298. case IL_LUMINANCE:
  299. ShortPtr[0] = (ILushort)(ClearAlpha * USHRT_MAX);
  300. break;
  301. case IL_LUMINANCE_ALPHA:
  302. ShortPtr[0] = (ILushort)(ClearLum * USHRT_MAX);
  303. ShortPtr[1] = (ILushort)(ClearAlpha * USHRT_MAX);
  304. break;
  305. case IL_COLOUR_INDEX:
  306. ShortPtr[0] = (ILushort)(ClearAlpha * USHRT_MAX);
  307. break;
  308. default:
  309. ilSetError(IL_INTERNAL_ERROR);
  310. return;
  311. }
  312. break;
  313. case IL_INT:
  314. case IL_UNSIGNED_INT:
  315. IntPtr = (ILuint*)Colours;
  316. switch (Format)
  317. {
  318. case IL_RGB:
  319. IntPtr[0] = (ILuint)(ClearRed * UINT_MAX);
  320. IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX);
  321. IntPtr[2] = (ILuint)(ClearBlue * UINT_MAX);
  322. break;
  323. case IL_RGBA:
  324. IntPtr[0] = (ILuint)(ClearRed * UINT_MAX);
  325. IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX);
  326. IntPtr[2] = (ILuint)(ClearBlue * UINT_MAX);
  327. IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX);
  328. break;
  329. case IL_BGR:
  330. IntPtr[2] = (ILuint)(ClearRed * UINT_MAX);
  331. IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX);
  332. IntPtr[0] = (ILuint)(ClearBlue * UINT_MAX);
  333. IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX);
  334. break;
  335. case IL_BGRA:
  336. IntPtr[2] = (ILuint)(ClearRed * UINT_MAX);
  337. IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX);
  338. IntPtr[0] = (ILuint)(ClearBlue * UINT_MAX);
  339. IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX);
  340. break;
  341. case IL_LUMINANCE:
  342. IntPtr[0] = (ILuint)(ClearAlpha * UINT_MAX);
  343. break;
  344. case IL_LUMINANCE_ALPHA:
  345. IntPtr[0] = (ILuint)(ClearLum * UINT_MAX);
  346. IntPtr[1] = (ILuint)(ClearAlpha * UINT_MAX);
  347. break;
  348. case IL_COLOUR_INDEX:
  349. IntPtr[0] = (ILuint)(ClearAlpha * UINT_MAX);
  350. break;
  351. default:
  352. ilSetError(IL_INTERNAL_ERROR);
  353. return;
  354. }
  355. break;
  356. case IL_FLOAT:
  357. FloatPtr = (ILfloat*)Colours;
  358. switch (Format)
  359. {
  360. case IL_RGB:
  361. FloatPtr[0] = ClearRed;
  362. FloatPtr[1] = ClearGreen;
  363. FloatPtr[2] = ClearBlue;
  364. break;
  365. case IL_RGBA:
  366. FloatPtr[0] = ClearRed;
  367. FloatPtr[1] = ClearGreen;
  368. FloatPtr[2] = ClearBlue;
  369. FloatPtr[3] = ClearAlpha;
  370. break;
  371. case IL_BGR:
  372. FloatPtr[2] = ClearRed;
  373. FloatPtr[1] = ClearGreen;
  374. FloatPtr[0] = ClearBlue;
  375. FloatPtr[3] = ClearAlpha;
  376. break;
  377. case IL_BGRA:
  378. FloatPtr[2] = ClearRed;
  379. FloatPtr[1] = ClearGreen;
  380. FloatPtr[0] = ClearBlue;
  381. FloatPtr[3] = ClearAlpha;
  382. break;
  383. case IL_LUMINANCE:
  384. FloatPtr[0] = ClearAlpha;
  385. break;
  386. case IL_LUMINANCE_ALPHA:
  387. FloatPtr[0] = ClearLum;
  388. FloatPtr[0] = ClearAlpha;
  389. break;
  390. case IL_COLOUR_INDEX:
  391. FloatPtr[0] = ClearAlpha;
  392. break;
  393. default:
  394. ilSetError(IL_INTERNAL_ERROR);
  395. return;
  396. }
  397. break;
  398. case IL_DOUBLE:
  399. DblPtr = (ILdouble*)Colours;
  400. switch (Format)
  401. {
  402. case IL_RGB:
  403. DblPtr[0] = ClearRed;
  404. DblPtr[1] = ClearGreen;
  405. DblPtr[2] = ClearBlue;
  406. break;
  407. case IL_RGBA:
  408. DblPtr[0] = ClearRed;
  409. DblPtr[1] = ClearGreen;
  410. DblPtr[2] = ClearBlue;
  411. DblPtr[3] = ClearAlpha;
  412. break;
  413. case IL_BGR:
  414. DblPtr[2] = ClearRed;
  415. DblPtr[1] = ClearGreen;
  416. DblPtr[0] = ClearBlue;
  417. DblPtr[3] = ClearAlpha;
  418. break;
  419. case IL_BGRA:
  420. DblPtr[2] = ClearRed;
  421. DblPtr[1] = ClearGreen;
  422. DblPtr[0] = ClearBlue;
  423. DblPtr[3] = ClearAlpha;
  424. break;
  425. case IL_LUMINANCE:
  426. DblPtr[0] = ClearAlpha;
  427. break;
  428. case IL_LUMINANCE_ALPHA:
  429. DblPtr[0] = ClearLum;
  430. DblPtr[1] = ClearAlpha;
  431. break;
  432. case IL_COLOUR_INDEX:
  433. DblPtr[0] = ClearAlpha;
  434. break;
  435. default:
  436. ilSetError(IL_INTERNAL_ERROR);
  437. return;
  438. }
  439. break;
  440. default:
  441. ilSetError(IL_INTERNAL_ERROR);
  442. return;
  443. }
  444. return;
  445. }
  446. //! Clears the current bound image to the values specified in ilClearColour
  447. ILboolean ILAPIENTRY ilClearImage()
  448. {
  449. if (iCurImage == NULL) {
  450. ilSetError(IL_ILLEGAL_OPERATION);
  451. return IL_FALSE;
  452. }
  453. return ilClearImage_(iCurImage);
  454. }
  455. ILAPI ILboolean ILAPIENTRY ilClearImage_(ILimage *Image)
  456. {
  457. ILuint i, c, NumBytes;
  458. ILubyte  Colours[32];  // Maximum is sizeof(double) * 4 = 32
  459. ILubyte  *BytePtr;
  460. ILushort *ShortPtr;
  461. ILuint *IntPtr;
  462. ILfloat  *FloatPtr;
  463. ILdouble *DblPtr;
  464. NumBytes = Image->Bpp * Image->Bpc;
  465. ilGetClear(Colours, Image->Format, Image->Type);
  466. if (Image->Format != IL_COLOUR_INDEX) {
  467. switch (Image->Type)
  468. {
  469. case IL_BYTE:
  470. case IL_UNSIGNED_BYTE:
  471. BytePtr = (ILubyte*)Colours;
  472. for (c = 0; c < NumBytes; c += Image->Bpc) {
  473. for (i = c; i < Image->SizeOfData; i += NumBytes) {
  474. Image->Data[i] = BytePtr[c];
  475. }
  476. }
  477. break;
  478. case IL_SHORT:
  479. case IL_UNSIGNED_SHORT:
  480. ShortPtr = (ILushort*)Colours;
  481. for (c = 0; c < NumBytes; c += Image->Bpc) {
  482. for (i = c; i < Image->SizeOfData; i += NumBytes) {
  483. *((ILushort*)(Image->Data + i)) = ShortPtr[c / Image->Bpc];
  484. }
  485. }
  486. break;
  487. case IL_INT:
  488. case IL_UNSIGNED_INT:
  489. IntPtr = (ILuint*)Colours;
  490. for (c = 0; c < NumBytes; c += Image->Bpc) {
  491. for (i = c; i < Image->SizeOfData; i += NumBytes) {
  492. *((ILuint*)(Image->Data + i)) = IntPtr[c / Image->Bpc];
  493. }
  494. }
  495. break;
  496. case IL_FLOAT:
  497. FloatPtr = (ILfloat*)Colours;
  498. for (c = 0; c < NumBytes; c += Image->Bpc) {
  499. for (i = c; i < Image->SizeOfData; i += NumBytes) {
  500. *((ILfloat*)(Image->Data + i)) = FloatPtr[c / Image->Bpc];
  501. }
  502. }
  503. break;
  504. case IL_DOUBLE:
  505. DblPtr = (ILdouble*)Colours;
  506. for (c = 0; c < NumBytes; c += Image->Bpc) {
  507. for (i = c; i < Image->SizeOfData; i += NumBytes) {
  508. *((ILdouble*)(Image->Data + i)) = DblPtr[c / Image->Bpc];
  509. }
  510. }
  511. break;
  512. }
  513. }
  514. else {
  515. imemclear(Image->Data, Image->SizeOfData);
  516. if (Image->Pal.Palette)
  517. ifree(Image->Pal.Palette);
  518. Image->Pal.Palette = (ILubyte*)ialloc(4);
  519. if (Image->Pal.Palette == NULL) {
  520. return IL_FALSE;
  521. }
  522. Image->Pal.PalType = IL_PAL_RGBA32;
  523. Image->Pal.PalSize = 4;
  524. Image->Pal.Palette[0] = Colours[0] * UCHAR_MAX;
  525. Image->Pal.Palette[1] = Colours[1] * UCHAR_MAX;
  526. Image->Pal.Palette[2] = Colours[2] * UCHAR_MAX;
  527. Image->Pal.Palette[3] = Colours[3] * UCHAR_MAX;
  528. }
  529. return IL_TRUE;
  530. }
  531. //! Overlays the image found in Src on top of the current bound image at the coords specified.
  532. ILboolean ILAPIENTRY ilOverlayImage(ILuint Source, ILint XCoord, ILint YCoord, ILint ZCoord)
  533. {
  534. ILuint Width, Height, Depth;
  535. ILuint Dest;
  536. Dest = ilGetCurName();
  537. ilBindImage(Source);
  538. Width = iCurImage->Width;  Height = iCurImage->Height;  Depth = iCurImage->Depth;
  539. ilBindImage(Dest);
  540. return ilBlit(Source, XCoord, YCoord, ZCoord, 0, 0, 0, Width, Height, Depth);
  541. }
  542. //@NEXT DestX,DestY,DestZ must be set to ILuint
  543. ILboolean ILAPIENTRY ilBlit(ILuint Source, ILint DestX,  ILint DestY,   ILint DestZ, 
  544.                                            ILuint SrcX,  ILuint SrcY,   ILuint SrcZ,
  545.                                            ILuint Width, ILuint Height, ILuint Depth)
  546. {
  547. ILuint  x, y, z, ConvBps, ConvSizePlane;
  548. ILimage  *Dest,*Src;
  549. ILubyte  *Converted;
  550. ILuint DestName = ilGetCurName();
  551. ILuint c;
  552. ILuint StartX, StartY, StartZ;
  553. ILboolean DestFlipped = IL_FALSE;
  554. ILubyte  *SrcTemp;
  555. ILfloat Back;
  556. // Check if the desiination image really exists
  557. if (DestName == 0 || iCurImage == NULL) {
  558. ilSetError(IL_ILLEGAL_OPERATION);
  559. return IL_FALSE;
  560. }
  561. Dest = iCurImage;
  562. // set the destination image to upper left origin
  563. if (Dest->Origin == IL_ORIGIN_LOWER_LEFT) {  // Dest
  564. DestFlipped = IL_TRUE;
  565. ilFlipImage();
  566. }
  567. //DestOrigin = Dest->Origin;
  568. ilBindImage(Source);
  569. // Check if the source image really exists
  570. if (iCurImage == NULL) {
  571. ilSetError(IL_INVALID_PARAM);
  572. return IL_FALSE;
  573. }
  574. Src = iCurImage;
  575. //@TODO test if coordinates are inside the images (hard limit for source)
  576. // set the source image to upper left origin
  577. if (Src->Origin == IL_ORIGIN_LOWER_LEFT)
  578. {
  579. SrcTemp = iGetFlipped(iCurImage);
  580. if (SrcTemp == NULL)
  581. {
  582. ilBindImage(DestName);
  583. if (DestFlipped)
  584. ilFlipImage();
  585. return IL_FALSE;
  586. }
  587. }
  588. else
  589. {
  590. SrcTemp = iCurImage->Data;
  591. }
  592. // convert source image to match the destination image type and format
  593. Converted = (ILubyte*)ilConvertBuffer(Src->SizeOfData, Src->Format, Dest->Format, Src->Type, Dest->Type, NULL, SrcTemp);
  594. if (Converted == NULL)
  595. return IL_FALSE;
  596. ConvBps    = Dest->Bpp * Src->Width;
  597. ConvSizePlane = ConvBps   * Src->Height;
  598. //@NEXT in next version this would have to be removed since Dest* will be unsigned
  599. StartX = DestX >= 0 ? 0 : -DestX;
  600. StartY = DestY >= 0 ? 0 : -DestY;
  601. StartZ = DestZ >= 0 ? 0 : -DestZ;
  602. // Limit the copy of data inside of the destination image
  603. if (Width  + DestX > Dest->Width)  Width  = Dest->Width  - DestX;
  604. if (Height + DestY > Dest->Height) Height = Dest->Height - DestY;
  605. if (Depth  + DestZ > Dest->Depth)  Depth  = Dest->Depth  - DestZ;
  606. //@TODO: non funziona con rgba
  607. if (Src->Format == IL_RGBA || Src->Format == IL_BGRA || Src->Format == IL_LUMINANCE_ALPHA) {
  608. const ILuint bpp_without_alpha = Dest->Bpp - 1;
  609. for (z = 0; z < Depth; z++) {
  610. for (y = 0; y < Height; y++) {
  611. for (x = 0; x < Width; x++) {
  612. const ILuint  SrcIndex  = (z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp;
  613. const ILuint  DestIndex = (z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp;
  614. const ILuint  AlphaIdx = SrcIndex + bpp_without_alpha;
  615. ILfloat Front = 0;
  616. switch (Dest->Type)
  617. {
  618. case IL_BYTE:
  619. case IL_UNSIGNED_BYTE:
  620. Front = Converted[AlphaIdx]/((float)IL_MAX_UNSIGNED_BYTE);
  621. break;
  622. case IL_SHORT:
  623. case IL_UNSIGNED_SHORT:
  624. Front = ((ILshort*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_SHORT);
  625. break;
  626. case IL_INT:
  627. case IL_UNSIGNED_INT:
  628. Front = ((ILint*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_INT);
  629. break;
  630. case IL_FLOAT:
  631. Front = ((ILfloat*)Converted)[AlphaIdx];
  632. break;
  633. case IL_DOUBLE:
  634. Front = (ILfloat)(((ILdouble*)Converted)[AlphaIdx]);
  635. break;
  636. }
  637. Back = 1.0f - Front;
  638. // In case of Alpha channel, the data is blended. Keeps the original alpha.
  639. if (ilIsEnabled(IL_BLIT_BLEND)) {
  640. for (c = 0; c < bpp_without_alpha; c++)
  641. {
  642. Dest->Data[DestIndex + c] = 
  643. (ILubyte)(Converted[SrcIndex + c] * Front
  644. + Dest->Data[DestIndex + c] * Back);
  645. }
  646. }
  647. else {
  648. for (c = 0; c < Dest->Bpp; c++)
  649. {
  650. Dest->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c]);
  651. }
  652. }
  653. }
  654. }
  655. }
  656. } else {
  657. for( z = 0; z < Depth; z++ ) {
  658. for( y = 0; y < Height; y++ ) {
  659. for( x = 0; x < Width; x++ ) {
  660. for( c = 0; c < Dest->Bpp; c++ ) {
  661. Dest->Data[(z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp + c] =
  662.  Converted[(z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp + c];
  663. }
  664. }
  665. }
  666. }
  667. }
  668. if (SrcTemp != iCurImage->Data)
  669. ifree(SrcTemp);
  670. ilBindImage(DestName);
  671. if (DestFlipped)
  672. ilFlipImage();
  673. ifree(Converted);
  674. return IL_TRUE;
  675. }
  676. ILboolean iCopySubImage(ILimage *Dest, ILimage *Src)
  677. {
  678. ILimage *DestTemp, *SrcTemp;
  679. DestTemp = Dest;
  680. SrcTemp = Src;
  681. do {
  682. ilCopyImageAttr(DestTemp, SrcTemp);
  683. DestTemp->Data = (ILubyte*)ialloc(SrcTemp->SizeOfData);
  684. if (DestTemp->Data == NULL) {
  685. return IL_FALSE;
  686. }
  687. memcpy(DestTemp->Data, SrcTemp->Data, SrcTemp->SizeOfData);
  688. if (SrcTemp->Next) {
  689. DestTemp->Next = (ILimage*)icalloc(1, sizeof(ILimage));
  690. if (!DestTemp->Next) {
  691. return IL_FALSE;
  692. }
  693. }
  694. else {
  695. DestTemp->Next = NULL;
  696. }
  697. DestTemp = DestTemp->Next;
  698. SrcTemp = SrcTemp->Next;
  699. } while (SrcTemp);
  700. return IL_TRUE;
  701. }
  702. ILboolean iCopySubImages(ILimage *Dest, ILimage *Src)
  703. {
  704. if (Src->Faces) {
  705. Dest->Faces = (ILimage*)icalloc(1, sizeof(ILimage));
  706. if (!Dest->Faces) {
  707. return IL_FALSE;
  708. }
  709. if (!iCopySubImage(Dest->Faces, Src->Faces))
  710. return IL_FALSE;
  711. }
  712. if (Src->Layers) {
  713. Dest->Layers = (ILimage*)icalloc(1, sizeof(ILimage));
  714. if (!Dest->Layers) {
  715. return IL_FALSE;
  716. }
  717. if (!iCopySubImage(Dest->Layers, Src->Layers))
  718. return IL_FALSE;
  719. }
  720. if (Src->Mipmaps) {
  721. Dest->Mipmaps = (ILimage*)icalloc(1, sizeof(ILimage));
  722. if (!Dest->Mipmaps) {
  723. return IL_FALSE;
  724. }
  725. if (!iCopySubImage(Dest->Mipmaps, Src->Mipmaps))
  726. return IL_FALSE;
  727. }
  728. if (Src->Next) {
  729. Dest->Next = (ILimage*)icalloc(1, sizeof(ILimage));
  730. if (!Dest->Next) {
  731. return IL_FALSE;
  732. }
  733. if (!iCopySubImage(Dest->Next, Src->Next))
  734. return IL_FALSE;
  735. }
  736. return IL_TRUE;
  737. }
  738. // Copies everything but the Data from Src to Dest.
  739. ILAPI ILboolean ILAPIENTRY ilCopyImageAttr(ILimage *Dest, ILimage *Src)
  740. {
  741. if (Dest == NULL || Src == NULL) {
  742. ilSetError(IL_INVALID_PARAM);
  743. return IL_FALSE;
  744. }
  745. if (Dest->Pal.Palette && Dest->Pal.PalSize && Dest->Pal.PalType != IL_PAL_NONE) {
  746. ifree(Dest->Pal.Palette);
  747. Dest->Pal.Palette = NULL;
  748. }
  749. if (Dest->Faces) {
  750. ilCloseImage(Dest->Faces);
  751. Dest->Faces = NULL;
  752. }
  753. if (Dest->Layers) {
  754. ilCloseImage(Dest->Layers);
  755. Dest->Layers = NULL;
  756. }
  757. if (Dest->Mipmaps) {
  758. ilCloseImage(Dest->Mipmaps);
  759. Dest->Mipmaps = NULL;
  760. }
  761. if (Dest->Next) {
  762. ilCloseImage(Dest->Next);
  763. Dest->Next = NULL;
  764. }
  765. if (Dest->Profile) {
  766. ifree(Dest->Profile);
  767. Dest->Profile = NULL;
  768. Dest->ProfileSize = 0;
  769. }
  770. if (Dest->DxtcData) {
  771. ifree(Dest->DxtcData);
  772. Dest->DxtcData = NULL;
  773. Dest->DxtcFormat = IL_DXT_NO_COMP;
  774. Dest->DxtcSize = 0;
  775. }
  776. if (Src->AnimList && Src->AnimSize) {
  777. Dest->AnimList = (ILuint*)ialloc(Src->AnimSize * sizeof(ILuint));
  778. if (Dest->AnimList == NULL) {
  779. return IL_FALSE;
  780. }
  781. memcpy(Dest->AnimList, Src->AnimList, Src->AnimSize * sizeof(ILuint));
  782. }
  783. if (Src->Profile) {
  784. Dest->Profile = (ILubyte*)ialloc(Src->ProfileSize);
  785. if (Dest->Profile == NULL) {
  786. return IL_FALSE;
  787. }
  788. memcpy(Dest->Profile, Src->Profile, Src->ProfileSize);
  789. Dest->ProfileSize = Src->ProfileSize;
  790. }
  791. if (Src->Pal.Palette) {
  792. Dest->Pal.Palette = (ILubyte*)ialloc(Src->Pal.PalSize);
  793. if (Dest->Pal.Palette == NULL) {
  794. return IL_FALSE;
  795. }
  796. memcpy(Dest->Pal.Palette, Src->Pal.Palette, Src->Pal.PalSize);
  797. }
  798. else {
  799. Dest->Pal.Palette = NULL;
  800. }
  801. Dest->Pal.PalSize = Src->Pal.PalSize;
  802. Dest->Pal.PalType = Src->Pal.PalType;
  803. Dest->Width = Src->Width;
  804. Dest->Height = Src->Height;
  805. Dest->Depth = Src->Depth;
  806. Dest->Bpp = Src->Bpp;
  807. Dest->Bpc = Src->Bpc;
  808. Dest->Bps = Src->Bps;
  809. Dest->SizeOfPlane = Src->SizeOfPlane;
  810. Dest->SizeOfData = Src->SizeOfData;
  811. Dest->Format = Src->Format;
  812. Dest->Type = Src->Type;
  813. Dest->Origin = Src->Origin;
  814. Dest->Duration = Src->Duration;
  815. Dest->CubeFlags = Src->CubeFlags;
  816. Dest->AnimSize = Src->AnimSize;
  817. Dest->OffX = Src->OffX;
  818. Dest->OffY = Src->OffY;
  819. return IL_TRUE/*iCopySubImages(Dest, Src)*/;
  820. }
  821. //! Copies everything from Src to the current bound image.
  822. ILboolean ILAPIENTRY ilCopyImage(ILuint Src)
  823. {
  824. ILuint DestName = ilGetCurName();
  825. ILimage *DestImage = iCurImage, *SrcImage;
  826. if (iCurImage == NULL || DestName == 0) {
  827. ilSetError(IL_ILLEGAL_OPERATION);
  828. return IL_FALSE;
  829. }
  830. ilBindImage(Src);
  831. SrcImage = iCurImage;
  832. ilBindImage(DestName);
  833. ilTexImage(SrcImage->Width, SrcImage->Height, SrcImage->Depth, SrcImage->Bpp, SrcImage->Format, SrcImage->Type, SrcImage->Data);
  834. ilCopyImageAttr(DestImage, SrcImage);
  835. return IL_TRUE;
  836. }
  837. // Creates a copy of Src and returns it.
  838. ILAPI ILimage* ILAPIENTRY ilCopyImage_(ILimage *Src)
  839. {
  840. ILimage *Dest;
  841. if (Src == NULL) {
  842. ilSetError(IL_INVALID_PARAM);
  843. return NULL;
  844. }
  845. Dest = ilNewImage(Src->Width, Src->Height, Src->Depth, Src->Bpp, Src->Bpc);
  846. if (Dest == NULL) {
  847. return NULL;
  848. }
  849. if (ilCopyImageAttr(Dest, Src) == IL_FALSE)
  850. return NULL;
  851. memcpy(Dest->Data, Src->Data, Src->SizeOfData);
  852. return Dest;
  853. }
  854. ILuint ILAPIENTRY ilCloneCurImage()
  855. {
  856. ILuint Id;
  857. ILimage *CurImage;
  858. if (iCurImage == NULL) {
  859. ilSetError(IL_ILLEGAL_OPERATION);
  860. return 0;
  861. }
  862. ilGenImages(1, &Id);
  863. if (Id == 0)
  864. return 0;
  865. CurImage = iCurImage;
  866. ilBindImage(Id);
  867. ilTexImage(CurImage->Width, CurImage->Height, CurImage->Depth, CurImage->Bpp, CurImage->Format, CurImage->Type, CurImage->Data);
  868. ilCopyImageAttr(iCurImage, CurImage);
  869. iCurImage = CurImage;
  870. return Id;
  871. }
  872. // Like ilTexImage but doesn't destroy the palette.
  873. ILAPI ILboolean ILAPIENTRY ilResizeImage(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc)
  874. {
  875. if (Image == NULL) {
  876. ilSetError(IL_INVALID_PARAM);
  877. return IL_FALSE;
  878. }
  879. if (Image->Data != NULL)
  880. ifree(Image->Data);
  881. Image->Depth = Depth;
  882. Image->Width = Width;
  883. Image->Height = Height;
  884. Image->Bpp = Bpp;
  885. Image->Bpc = Bpc;
  886. Image->Bps = Bpp * Bpc * Width;
  887. Image->SizeOfPlane = Image->Bps * Height;
  888. Image->SizeOfData = Image->SizeOfPlane * Depth;
  889. Image->Data = (ILubyte*)ialloc(Image->SizeOfData);
  890. if (Image->Data == NULL) {
  891. return IL_FALSE;
  892. }
  893. return IL_TRUE;
  894. }