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

Visual C++

  1. //-----------------------------------------------------------------------------
  2. //
  3. // ImageLib Sources
  4. // Copyright (C) 2000-2009 by Denton Woods
  5. // Last modified: 02/15/2009
  6. //
  7. // Filename: src-IL/src/il_rot.c
  8. //
  9. // Description: Reads from a Homeworld 2 - Relic Texture (.rot) file.
  10. //
  11. //-----------------------------------------------------------------------------
  12. // @TODO:
  13. // Note: I am not certain about which is DXT3 and which is DXT5.  According to
  14. //  http://forums.relicnews.com/showthread.php?t=20512, DXT3 is 1030, and DXT5
  15. //  is 1029.  However, neither way seems to work quite right for the alpha.
  16. #include "il_internal.h"
  17. #ifndef IL_NO_ROT
  18. #include "il_dds.h"
  19. ILboolean iLoadRotInternal(void);
  20. #define ROT_RGBA32 1024
  21. #define ROT_DXT1 1028
  22. #define ROT_DXT3 1029
  23. #define ROT_DXT5 1030
  24. //! Reads a ROT file
  25. ILboolean ilLoad_ROT(ILconst_string FileName)
  26. {
  27. ILHANDLE RotFile;
  28. ILboolean bRot = IL_FALSE;
  29. RotFile = iopenr(FileName);
  30. if (RotFile == NULL) {
  31. ilSetError(IL_COULD_NOT_OPEN_FILE);
  32. return bRot;
  33. }
  34. bRot = ilLoadF_ROT(RotFile);
  35. icloser(RotFile);
  36. return bRot;
  37. }
  38. //! Reads an already-opened ROT file
  39. ILboolean ilLoadF_ROT(ILHANDLE File)
  40. {
  41. ILuint FirstPos;
  42. ILboolean bRet;
  43. iSetInputFile(File);
  44. FirstPos = itell();
  45. bRet = iLoadRotInternal();
  46. iseek(FirstPos, IL_SEEK_SET);
  47. return bRet;
  48. }
  49. //! Reads from a memory "lump" that contains a ROT
  50. ILboolean ilLoadL_ROT(const void *Lump, ILuint Size)
  51. {
  52. iSetInputLump(Lump, Size);
  53. return iLoadRotInternal();
  54. }
  55. // Internal function used to load the ROT.
  56. ILboolean iLoadRotInternal(void)
  57. {
  58. ILubyte Form[4], FormName[4];
  59. ILuint FormLen, Width, Height, Format, Channels, CompSize;
  60. ILuint MipSize, MipLevel, MipWidth, MipHeight;
  61. ILenum FormatIL;
  62. ILimage *Image;
  63. ILboolean BaseCreated = IL_FALSE;
  64. ILubyte *CompData = NULL;
  65. if (iCurImage == NULL) {
  66. ilSetError(IL_ILLEGAL_OPERATION);
  67. return IL_FALSE;
  68. }
  69. // The first entry in the file must be 'FORM', 0x20 in a big endian integer and then 'HEAD'.
  70. iread(Form, 1, 4);
  71. FormLen = GetBigUInt();
  72. iread(FormName, 1, 4);
  73. if (strncmp(Form, "FORM", 4) || FormLen != 0x14 || strncmp(FormName, "HEAD", 4)) {
  74. ilSetError(IL_INVALID_FILE_HEADER);
  75. return IL_FALSE;
  76. }
  77. // Next follows the width, height and format in the header.
  78. Width = GetLittleUInt();
  79. Height = GetLittleUInt();
  80. Format = GetLittleUInt();
  81. //@TODO: More formats.
  82. switch (Format)
  83. {
  84. case ROT_RGBA32:  // 32-bit RGBA format
  85. Channels = 4;
  86. FormatIL = IL_RGBA;
  87. break;
  88. case ROT_DXT1:  // DXT1 (no alpha)
  89. Channels = 4;
  90. FormatIL = IL_RGBA;
  91. break;
  92. case ROT_DXT3:  // DXT3
  93. case ROT_DXT5:  // DXT5
  94. Channels = 4;
  95. FormatIL = IL_RGBA;
  96. // Allocates the maximum needed (the first width/height given in the file).
  97. CompSize = ((Width + 3) / 4) * ((Height + 3) / 4) * 16;
  98. CompData = ialloc(CompSize);
  99. if (CompData == NULL)
  100. return IL_FALSE;
  101. break;
  102. default:
  103. ilSetError(IL_INVALID_FILE_HEADER);
  104. return IL_FALSE;
  105. }
  106. if (Width == 0 || Height == 0) {
  107. ilSetError(IL_INVALID_FILE_HEADER);
  108. return IL_FALSE;
  109. }
  110. //@TODO: Find out what this is.
  111. GetLittleUInt();  // Skip this for the moment.  This appears to be the number of channels.
  112. // Next comes 'FORM', a length and 'MIPS'.
  113. iread(Form, 1, 4);
  114. FormLen = GetBigUInt();
  115. iread(FormName, 1, 4);
  116. //@TODO: Not sure if the FormLen has to be anything specific here.
  117. if (strncmp(Form, "FORM", 4) || strncmp(FormName, "MIPS", 4)) {
  118. ilSetError(IL_INVALID_FILE_HEADER);
  119. return IL_FALSE;
  120. }
  121. //@TODO: Can these mipmap levels be in any order?  Some things may be easier if the answer is no.
  122. Image = iCurImage;
  123. do {
  124. // Then we have 'FORM' again.
  125. iread(Form, 1, 4);
  126. // This is the size of the mipmap data.
  127. MipSize = GetBigUInt();
  128. iread(FormName, 1, 4);
  129. if (strncmp(Form, "FORM", 4)) {
  130. if (!BaseCreated) {  // Our file is malformed.
  131. ilSetError(IL_INVALID_FILE_HEADER);
  132. return IL_FALSE;
  133. }
  134. // We have reached the end of the mipmap data.
  135. break;
  136. }
  137. if (strncmp(FormName, "MLVL", 4)) {
  138. ilSetError(IL_INVALID_FILE_HEADER);
  139. return IL_FALSE;
  140. }
  141. // Next is the mipmap attributes (level number, width, height and length)
  142. MipLevel = GetLittleUInt();
  143. MipWidth = GetLittleUInt();
  144. MipHeight = GetLittleUInt();
  145. MipSize = GetLittleUInt();  // This is the same as the previous size listed -20 (for attributes).
  146. // Lower level mipmaps cannot be larger than the main image.
  147. if (MipWidth > Width || MipHeight > Height || MipSize > CompSize) {
  148. ilSetError(IL_INVALID_FILE_HEADER);
  149. return IL_FALSE;
  150. }
  151. // Just create our images here.
  152. if (!BaseCreated) {
  153. if (!ilTexImage(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL))
  154. return IL_FALSE;
  155. BaseCreated = IL_TRUE;
  156. }
  157. else {
  158. Image->Mipmaps = ilNewImageFull(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL);
  159. Image = Image->Mipmaps;
  160. }
  161. switch (Format)
  162. {
  163. case ROT_RGBA32:  // 32-bit RGBA format
  164. if (iread(Image->Data, Image->SizeOfData, 1) != 1)
  165. return IL_FALSE;
  166. break;
  167. case ROT_DXT1:
  168. // Allocates the size of the compressed data.
  169. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 8;
  170. if (CompSize != MipSize) {
  171. ilSetError(IL_INVALID_FILE_HEADER);
  172. return IL_FALSE;
  173. }
  174. CompData = ialloc(CompSize);
  175. if (CompData == NULL)
  176. return IL_FALSE;
  177. // Read in the DXT1 data...
  178. if (iread(CompData, CompSize, 1) != 1)
  179. return IL_FALSE;
  180. // ...and decompress it.
  181. if (!DecompressDXT1(Image, CompData)) {
  182. ifree(CompData);
  183. return IL_FALSE;
  184. }
  185. if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) {
  186. Image->DxtcSize = CompSize;
  187. Image->DxtcData = CompData;
  188. Image->DxtcFormat = IL_DXT1;
  189. CompData = NULL;
  190. }
  191. break;
  192. case ROT_DXT3:
  193. // Allocates the size of the compressed data.
  194. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16;
  195. if (CompSize != MipSize) {
  196. ilSetError(IL_INVALID_FILE_HEADER);
  197. return IL_FALSE;
  198. }
  199. CompData = ialloc(CompSize);
  200. if (CompData == NULL)
  201. return IL_FALSE;
  202. // Read in the DXT3 data...
  203. if (iread(CompData, MipSize, 1) != 1)
  204. return IL_FALSE;
  205. // ...and decompress it.
  206. if (!DecompressDXT3(Image, CompData)) {
  207. ifree(CompData);
  208. return IL_FALSE;
  209. }
  210. if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) {
  211. Image->DxtcSize = CompSize;
  212. Image->DxtcData = CompData;
  213. Image->DxtcFormat = IL_DXT3;
  214. CompData = NULL;
  215. }
  216. break;
  217. case ROT_DXT5:
  218. // Allocates the size of the compressed data.
  219. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16;
  220. if (CompSize != MipSize) {
  221. ilSetError(IL_INVALID_FILE_HEADER);
  222. return IL_FALSE;
  223. }
  224. CompData = ialloc(CompSize);
  225. if (CompData == NULL)
  226. return IL_FALSE;
  227. // Read in the DXT5 data...
  228. if (iread(CompData, MipSize, 1) != 1)
  229. return IL_FALSE;
  230. // ...and decompress it.
  231. if (!DecompressDXT5(Image, CompData)) {
  232. ifree(CompData);
  233. return IL_FALSE;
  234. }
  235. // Keeps a copy
  236. if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) {
  237. Image->DxtcSize = CompSize;
  238. Image->DxtcData = CompData;
  239. Image->DxtcFormat = IL_DXT5;
  240. CompData = NULL;
  241. }
  242. break;
  243. }
  244. ifree(CompData);  // Free it if it was not saved.
  245. } while (!ieof());  //@TODO: Is there any other condition that should end this?
  246. return ilFixImage();
  247. }
  248. #endif//IL_NO_ROT