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

Visual C++

  1. //-----------------------------------------------------------------------------
  2. //
  3. // ImageLib Sources
  4. // Copyright (C) 2000-2009 by Denton Woods
  5. // Last modified: 02/14/2009
  6. //
  7. // Filename: src-IL/src/il_blp.c
  8. //
  9. // Description: Reads from a Blizzard Texture (.blp).
  10. //                Specifications were found at http://www.wowwiki.com/BLP_files
  11. //   for BLP2 and from
  12. // http://web.archive.org/web/20080117120549/magos.thejefffiles.com/War3ModelEditor/MagosBlpFormat.txt
  13. //   for BLP1.
  14. //
  15. //-----------------------------------------------------------------------------
  16. //@TODO: Add support for the BLP1 format as well.
  17. #include "il_internal.h"
  18. #ifndef IL_NO_BLP
  19. #include "il_dds.h"
  20. typedef struct BLP1HEAD
  21. {
  22. ILubyte Sig[4];
  23. ILuint Compression; // Texture type: 0 = JPG, 1 = Paletted
  24. ILuint Flags; // #8 - Uses alpha channel (?)
  25. ILuint Width; // Image width in pixels
  26. ILuint Height; // Image height in pixels
  27. ILuint PictureType; // 3 - Uncompressed index list + alpha list
  28. // 4 - Uncompressed index list + alpha list
  29. // 5 - Uncompressed index list
  30. ILuint PictureSubType; // 1 - ???
  31. ILuint MipOffsets[16]; // The file offsets of each mipmap, 0 for unused
  32. ILuint MipLengths[16]; // The length of each mipmap data block
  33. } BLP1HEAD;
  34. typedef struct BLP2HEAD
  35. {
  36. ILubyte Sig[4];         // "BLP2" signature
  37. ILuint Type;           // Texture type: 0 = JPG, 1 = DXTC
  38. ILubyte Compression;    // Compression mode: 1 = raw, 2 = DXTC
  39. ILubyte AlphaBits;      // 0, 1, or 8
  40. ILubyte AlphaType;      // 0, 1, 7 or 8
  41. ILubyte HasMips;        // 0 = no mips levels, 1 = has mips (number of levels determined by image size)
  42. ILuint Width;          // Image width in pixels
  43. ILuint Height;         // Image height in pixels
  44. ILuint MipOffsets[16]; // The file offsets of each mipmap, 0 for unused
  45. ILuint MipLengths[16]; // The length of each mipmap data block
  46. } BLP2HEAD;
  47. // Data formats
  48. #define BLP_TYPE_JPG 0
  49. #define BLP_TYPE_DXTC_RAW 1
  50. #define BLP_RAW 1
  51. #define BLP_DXTC 2
  52. #define BLP_RAW_PLUS_ALPHA1 3
  53. #define BLP_RAW_PLUS_ALPHA2 4
  54. #define BLP_RAW_NO_ALPHA 5
  55. ILboolean iIsValidBlp2(void);
  56. ILboolean iCheckBlp2(BLP2HEAD *Header);
  57. ILboolean iLoadBlpInternal(void);
  58. ILboolean iLoadBlp1(void);
  59. ILboolean iCheckBlp1(BLP1HEAD *Header);
  60. ILboolean iGetBlp1Head(BLP1HEAD *Header);
  61. //! Checks if the file specified in FileName is a valid BLP file.
  62. ILboolean ilIsValid_BLP(ILconst_string FileName)
  63. {
  64. ILHANDLE BlpFile;
  65. ILboolean bBlp = IL_FALSE;
  66. if (!iCheckExtension(FileName, IL_TEXT("blp"))) {
  67. ilSetError(IL_INVALID_EXTENSION);
  68. return bBlp;
  69. }
  70. BlpFile = iopenr(FileName);
  71. if (BlpFile == NULL) {
  72. ilSetError(IL_COULD_NOT_OPEN_FILE);
  73. return bBlp;
  74. }
  75. bBlp = ilIsValidF_BLP(BlpFile);
  76. icloser(BlpFile);
  77. return bBlp;
  78. }
  79. //! Checks if the ILHANDLE contains a valid BLP file at the current position.
  80. ILboolean ilIsValidF_BLP(ILHANDLE File)
  81. {
  82. ILuint FirstPos;
  83. ILboolean bRet;
  84. iSetInputFile(File);
  85. FirstPos = itell();
  86. bRet = iIsValidBlp2();
  87. iseek(FirstPos, IL_SEEK_SET);
  88. return bRet;
  89. }
  90. //! Checks if Lump is a valid BLP lump.
  91. ILboolean ilIsValidL_BLP(const void *Lump, ILuint Size)
  92. {
  93. iSetInputLump(Lump, Size);
  94. return iIsValidBlp2();
  95. }
  96. // Internal function used to get the BLP header from the current file.
  97. ILboolean iGetBlp2Head(BLP2HEAD *Header)
  98. {
  99. ILuint i;
  100. iread(Header->Sig, 1, 4);
  101. Header->Type = GetLittleUInt();
  102. Header->Compression = igetc();
  103. Header->AlphaBits = igetc();
  104. Header->AlphaType = igetc();
  105. Header->HasMips = igetc();
  106. Header->Width = GetLittleUInt();
  107. Header->Height = GetLittleUInt();
  108. for (i = 0; i < 16; i++)
  109. Header->MipOffsets[i] = GetLittleUInt();
  110. for (i = 0; i < 16; i++)
  111. Header->MipLengths[i] = GetLittleUInt();
  112. return IL_TRUE;
  113. }
  114. // Internal function to get the header and check it.
  115. ILboolean iIsValidBlp2(void)
  116. {
  117. BLP2HEAD Header;
  118. if (!iGetBlp2Head(&Header))
  119. return IL_FALSE;
  120. iseek(-148, IL_SEEK_CUR);
  121. return iCheckBlp2(&Header);
  122. }
  123. // Internal function used to check if the HEADER is a valid BLP header.
  124. ILboolean iCheckBlp2(BLP2HEAD *Header)
  125. {
  126. // The file signature is 'BLP2'.
  127. if (strncmp(Header->Sig, "BLP2", 4))
  128. return IL_FALSE;
  129. // Valid types are JPEG and DXTC.  JPEG is not common, though.
  130. //  WoW only uses DXTC.
  131. if (Header->Type != BLP_TYPE_JPG && Header->Type != BLP_TYPE_DXTC_RAW)
  132. return IL_FALSE;
  133. // For BLP_TYPE_DXTC_RAW, we can have RAW and DXTC compression.
  134. if (Header->Compression != BLP_RAW && Header->Compression != BLP_DXTC)
  135. return IL_FALSE;
  136. // Alpha bits can only be 0, 1 and 8.
  137. if (Header->AlphaBits != 0 && Header->AlphaBits != 1 && Header->AlphaBits != 8)
  138. return IL_FALSE;
  139. // Alpha type can only be 0, 1, 7 and 8.
  140. if (Header->AlphaType != 0 && Header->AlphaType != 1 && Header->AlphaType != 7 && Header->AlphaType != 8)
  141. return IL_FALSE;
  142. // Width or height of 0 makes no sense.
  143. if (Header->Width == 0 || Header->Height == 0)
  144. return IL_FALSE;
  145. return IL_TRUE;
  146. }
  147. //! Reads a BLP file
  148. ILboolean ilLoad_BLP(ILconst_string FileName)
  149. {
  150. ILHANDLE BlpFile;
  151. ILboolean bBlp = IL_FALSE;
  152. BlpFile = iopenr(FileName);
  153. if (BlpFile == NULL) {
  154. ilSetError(IL_COULD_NOT_OPEN_FILE);
  155. return bBlp;
  156. }
  157. bBlp = ilLoadF_BLP(BlpFile);
  158. icloser(BlpFile);
  159. return bBlp;
  160. }
  161. //! Reads an already-opened BLP file
  162. ILboolean ilLoadF_BLP(ILHANDLE File)
  163. {
  164. ILuint FirstPos;
  165. ILboolean bRet;
  166. iSetInputFile(File);
  167. FirstPos = itell();
  168. bRet = iLoadBlpInternal();
  169. iseek(FirstPos, IL_SEEK_SET);
  170. return bRet;
  171. }
  172. //! Reads from a memory "lump" that contains a BLP
  173. ILboolean ilLoadL_BLP(const void *Lump, ILuint Size)
  174. {
  175. iSetInputLump(Lump, Size);
  176. return iLoadBlpInternal();
  177. }
  178. // Internal function used to load the BLP.
  179. ILboolean iLoadBlpInternal(void)
  180. {
  181. BLP2HEAD Header;
  182. ILubyte *CompData;
  183. ILimage *Image;
  184. ILuint Mip, j, x, CompSize, AlphaSize, AlphaOff;
  185. ILint y;
  186. ILboolean BaseCreated = IL_FALSE;
  187. ILubyte *DataAndAlpha = NULL, *Palette = NULL, AlphaMask; //, *JpegHeader, *JpegData;
  188. if (iCurImage == NULL) {
  189. ilSetError(IL_ILLEGAL_OPERATION);
  190. return IL_FALSE;
  191. }
  192. if (!iGetBlp2Head(&Header)) {
  193. ilSetError(IL_INVALID_FILE_HEADER);
  194. return IL_FALSE;
  195. }
  196. if (!iCheckBlp2(&Header)) {
  197. goto check_blp1;
  198. }
  199. //@TODO: Remove this!
  200. if (Header.Type != BLP_TYPE_DXTC_RAW)
  201. return IL_FALSE;
  202. switch (Header.Compression)
  203. {
  204. case BLP_RAW:
  205. for (Mip = 0; Mip < 16; Mip++) {  // Possible maximum of 16 mipmaps
  206. if (BaseCreated) {
  207. if (Header.HasMips == 0)  // Does not have mipmaps, so we are done.
  208. break;
  209. if (Image->Width == 1 && Image->Height == 1)  // Already at the smallest mipmap (1x1), so we are done.
  210. break;
  211. if (Header.MipOffsets[Mip] == 0 || Header.MipLengths == 0)  // No more mipmaps in the file.
  212. break;
  213. }
  214. switch (Header.AlphaBits)
  215. {
  216. case 0:
  217. if (!BaseCreated) {  // Have not created the base image yet, so use ilTexImage.
  218. if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
  219. return IL_FALSE;
  220. Image = iCurImage;
  221. BaseCreated = IL_TRUE;
  222. Image->Pal.Palette = (ILubyte*)ialloc(256 * 4);  // 256 entries of ARGB8888 values (1024).
  223. if (Image->Pal.Palette == NULL)
  224. return IL_FALSE;
  225. Image->Pal.PalSize = 1024;
  226. Image->Pal.PalType = IL_PAL_BGRA32;  //@TODO: Find out if this is really BGRA data.
  227. if (iread(Image->Pal.Palette, 1, 1024) != 1024)  // Read in the palette.
  228. return IL_FALSE;
  229. }
  230. else {
  231. Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL);
  232. if (Image->Mipmaps == NULL)
  233. return IL_FALSE;
  234. // Copy the palette from the first image before we change our Image pointer.
  235. iCopyPalette(&Image->Mipmaps->Pal, &Image->Pal);
  236. // Move to the next mipmap in the linked list.
  237. Image = Image->Mipmaps;
  238. }
  239. // The origin should be in the upper left.
  240. Image->Origin = IL_ORIGIN_UPPER_LEFT;
  241. // These two should be the same (tells us how much data is in the file for this mipmap level).
  242. if (Header.MipLengths[Mip] != Image->SizeOfData) {
  243. ilSetError(IL_INVALID_FILE_HEADER);
  244. return IL_FALSE;
  245. }
  246. // Finally read in the image data.
  247. iseek(Header.MipOffsets[Mip], IL_SEEK_SET);
  248. if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData)
  249. return IL_FALSE;
  250. break;
  251. case 1:
  252. if (!BaseCreated) {  // Have not created the base image yet, so use ilTexImage.
  253. if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL))
  254. return IL_FALSE;
  255. Image = iCurImage;
  256. BaseCreated = IL_TRUE;
  257. Palette = (ILubyte*)ialloc(256 * 4);
  258. if (Palette == NULL)
  259. return IL_FALSE;
  260. // Read in the palette.
  261. if (iread(Palette, 1, 1024) != 1024) {
  262. ifree(Palette);
  263. return IL_FALSE;
  264. }
  265. // We only allocate this once and reuse this buffer with every mipmap (since successive ones are smaller).
  266. DataAndAlpha = (ILubyte*)ialloc(Image->Width * Image->Height);
  267. if (DataAndAlpha == NULL) {
  268. ifree(DataAndAlpha);
  269. ifree(Palette);
  270. return IL_FALSE;
  271. }
  272. }
  273. else {
  274. Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL);
  275. if (Image->Mipmaps == NULL)
  276. return IL_FALSE;
  277. // Move to the next mipmap in the linked list.
  278. Image = Image->Mipmaps;
  279. }
  280. // The origin should be in the upper left.
  281. Image->Origin = IL_ORIGIN_UPPER_LEFT;
  282. // Determine the size of the alpha data following the color indices.
  283. AlphaSize = Image->Width * Image->Height / 8;
  284. if (AlphaSize == 0)
  285. AlphaSize = 1;  // Should never be 0.
  286. // These two should be the same (tells us how much data is in the file for this mipmap level).
  287. if (Header.MipLengths[Mip] != Image->SizeOfData / 4 + AlphaSize) {
  288. ilSetError(IL_INVALID_FILE_HEADER);
  289. return IL_FALSE;
  290. }
  291. // Seek to the data and read it.
  292. iseek(Header.MipOffsets[Mip], IL_SEEK_SET);
  293. if (iread(DataAndAlpha, Image->Width * Image->Height, 1) != 1) {
  294. ifree(DataAndAlpha);
  295. ifree(Palette);
  296. return IL_FALSE;
  297. }
  298. // Convert the color-indexed data to BGRX.
  299. for (j = 0; j < Image->Width * Image->Height; j++) {
  300. Image->Data[j*4]   = Palette[DataAndAlpha[j]*4];
  301. Image->Data[j*4+1] = Palette[DataAndAlpha[j]*4+1];
  302. Image->Data[j*4+2] = Palette[DataAndAlpha[j]*4+2];
  303. }
  304. // Read in the alpha list.
  305. if (iread(DataAndAlpha, AlphaSize, 1) != 1) {
  306. ifree(DataAndAlpha);
  307. ifree(Palette);
  308. return IL_FALSE;
  309. }
  310. AlphaMask = 0x01;  // Lowest bit
  311. AlphaOff = 0;
  312. // The really strange thing about this alpha data is that it is upside-down when compared to the
  313. //   regular color-indexed data, so we have to flip it.
  314. for (y = Image->Height - 1; y >= 0; y--) {
  315. for (x = 0; x < Image->Width; x++) {
  316. if (AlphaMask == 0) {  // Shifting it past the highest bit makes it 0, since we only have 1 byte.
  317. AlphaOff++;        // Move along the alpha buffer.
  318. AlphaMask = 0x01;  // Reset the alpha mask.
  319. }
  320. // This is just 1-bit alpha, so it is either on or off.
  321. Image->Data[Image->Bps * y + x * 4 + 3] = DataAndAlpha[AlphaOff] & AlphaMask ? 0xFF : 0x00;
  322. AlphaMask <<= 1;
  323. }
  324. }
  325. break;
  326. default:
  327. //@TODO: Accept any other alpha values?
  328. ilSetError(IL_INVALID_FILE_HEADER);
  329. return IL_FALSE;
  330. }
  331. }
  332. // Done, so we can finally free these two.
  333. ifree(DataAndAlpha);
  334. ifree(Palette);
  335. break;
  336. case BLP_DXTC:
  337. for (Mip = 0; Mip < 16; Mip++) {  // Possible maximum of 16 mipmaps
  338. //@TODO: Other formats
  339. //if (Header.AlphaBits == 0)
  340. // if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL))
  341. // return IL_FALSE;
  342. if (!BaseCreated) {  // Have not created the base image yet, so use ilTexImage.
  343. if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL))
  344. return IL_FALSE;
  345. Image = iCurImage;
  346. BaseCreated = IL_TRUE;
  347. }
  348. else {
  349. if (Header.HasMips == 0)  // Does not have mipmaps, so we are done.
  350. break;
  351. if (Image->Width == 1 && Image->Height == 1)  // Already at the smallest mipmap (1x1), so we are done.
  352. break;
  353. if (Header.MipOffsets[Mip] == 0 || Header.MipLengths[Mip] == 0)  // No more mipmaps in the file.
  354. break;
  355. //@TODO: Other formats
  356. // ilNewImageFull automatically changes widths and heights of 0 to 1, so we do not have to worry about it.
  357. Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
  358. if (Image->Mipmaps == NULL)
  359. return IL_FALSE;
  360. Image = Image->Mipmaps;
  361. }
  362. // The origin should be in the upper left.
  363. Image->Origin = IL_ORIGIN_UPPER_LEFT;
  364. //@TODO: Only do the allocation once.
  365. CompData = (ILubyte*)ialloc(Header.MipLengths[Mip]);
  366. if (CompData == NULL)
  367. return IL_FALSE;
  368. // Read in the compressed mipmap data.
  369. iseek(Header.MipOffsets[Mip], IL_SEEK_SET);
  370. if (iread(CompData, 1, Header.MipLengths[Mip]) != Header.MipLengths[Mip]) {
  371. ifree(CompData);
  372. return IL_FALSE;
  373. }
  374. switch (Header.AlphaBits)
  375. {
  376. case 0:  // DXT1 without alpha
  377. case 1:  // DXT1 with alpha
  378. // Check to make sure that the MipLength reported is the size needed, so that
  379. //  DecompressDXT1 does not crash.
  380. CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 8;
  381. if (CompSize != Header.MipLengths[Mip]) {
  382. ilSetError(IL_INVALID_FILE_HEADER);
  383. ifree(CompData);
  384. return IL_FALSE;
  385. }
  386. if (!DecompressDXT1(Image, CompData)) {
  387. ifree(CompData);
  388. return IL_FALSE;
  389. }
  390. break;
  391. case 8:
  392. // Check to make sure that the MipLength reported is the size needed, so that
  393. //  DecompressDXT3/5 do not crash.
  394. CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 16;
  395. if (CompSize != Header.MipLengths[Mip]) {
  396. ifree(CompData);
  397. ilSetError(IL_INVALID_FILE_HEADER);
  398. return IL_FALSE;
  399. }
  400. switch (Header.AlphaType)
  401. {
  402. case 0:  // All three of
  403. case 1:  //  these refer to
  404. case 8:  //  DXT3...
  405. if (!DecompressDXT3(Image, CompData)) {
  406. ifree(CompData);
  407. return IL_FALSE;
  408. }
  409. break;
  410. case 7:  // DXT5 compression
  411. if (!DecompressDXT5(Image, CompData)) {
  412. ifree(CompData);
  413. return IL_FALSE;
  414. }
  415. break;
  416. //default:  // Should already be checked by iCheckBlp2.
  417. }
  418. break;
  419. //default:  // Should already be checked by iCheckBlp2.
  420. }
  421. //@TODO: Save DXTC data.
  422. ifree(CompData);
  423. }
  424. break;
  425. //default:
  426. }
  427. return ilFixImage();
  428. check_blp1:
  429. iseek(-148, IL_SEEK_CUR);  // Go back the size of the BLP2 header, since we tried reading it.
  430. return iLoadBlp1();
  431. }
  432. ILboolean iGetBlp1Head(BLP1HEAD *Header)
  433. {
  434. ILuint i;
  435. iread(Header->Sig, 1, 4);
  436. Header->Compression = GetLittleUInt();
  437. Header->Flags = GetLittleUInt();
  438. Header->Width = GetLittleUInt();
  439. Header->Height = GetLittleUInt();
  440. Header->PictureType = GetLittleUInt();
  441. Header->PictureSubType = GetLittleUInt();
  442. for (i = 0; i < 16; i++)
  443. Header->MipOffsets[i] = GetLittleUInt();
  444. for (i = 0; i < 16; i++)
  445. Header->MipLengths[i] = GetLittleUInt();
  446. return IL_TRUE;
  447. }
  448. ILboolean iCheckBlp1(BLP1HEAD *Header)
  449. {
  450. // The file signature is 'BLP1'.
  451. if (strncmp(Header->Sig, "BLP1", 4))
  452. return IL_FALSE;
  453. // Valid types are JPEG and RAW.  JPEG is not common, though.
  454. if (Header->Compression != BLP_TYPE_JPG && Header->Compression != BLP_RAW)
  455. return IL_FALSE;
  456. //@TODO: Find out what Flags is for.
  457. // PictureType determines whether this has an alpha list.
  458. if (Header->PictureType != BLP_RAW_PLUS_ALPHA1 && Header->PictureType != BLP_RAW_PLUS_ALPHA2
  459. && Header->PictureType != BLP_RAW_NO_ALPHA)
  460. return IL_FALSE;
  461. // Width or height of 0 makes no sense.
  462. if (Header->Width == 0 || Header->Height == 0)
  463. return IL_FALSE;
  464. return IL_TRUE;
  465. }
  466. ILboolean iLoadBlp1()
  467. {
  468. BLP1HEAD Header;
  469. ILubyte *DataAndAlpha, *Palette;
  470. ILuint i;
  471. ILimage *Image = iCurImage;
  472. ILboolean BaseCreated = IL_FALSE;
  473. #ifndef IL_NO_JPEG
  474. ILubyte *JpegHeader, *JpegData;
  475. ILuint JpegHeaderSize;
  476. #endif//IL_NO_JPEG
  477. if (!iGetBlp1Head(&Header))
  478. return IL_FALSE;
  479. if (!iCheckBlp1(&Header)) {
  480. ilSetError(IL_INVALID_FILE_HEADER);
  481. return IL_FALSE;
  482. }
  483. //@TODO: Remove this.
  484. i = 0;
  485. switch (Header.Compression)
  486. {
  487. case BLP_TYPE_JPG:
  488. #ifdef IL_NO_JPEG
  489. // We can only do the Jpeg decoding if we do not have IL_NO_JPEG defined.
  490. return IL_FALSE;
  491. #else
  492. JpegHeaderSize = GetLittleUInt();
  493. JpegHeader = (ILubyte*)ialloc(JpegHeaderSize);
  494. if (JpegHeader == NULL)
  495. return IL_FALSE;
  496. // Read the shared Jpeg header.
  497. if (iread(JpegHeader, 1, JpegHeaderSize) != JpegHeaderSize) {
  498. ifree(JpegHeader);
  499. return IL_FALSE;
  500. }
  501. //for (i = 0; i < 16; i++) {  // Possible maximum of 16 mipmaps
  502. //@TODO: Check return value?
  503. iseek(Header.MipOffsets[i], IL_SEEK_SET);
  504. JpegData = (ILubyte*)ialloc(JpegHeaderSize + Header.MipLengths[i]);
  505. if (JpegData == NULL) {
  506. ifree(JpegHeader);
  507. return IL_FALSE;
  508. }
  509. memcpy(JpegData, JpegHeader, JpegHeaderSize);
  510. if (iread(JpegData + JpegHeaderSize, Header.MipLengths[i], 1) != 1)
  511. return IL_FALSE;
  512. // Just send the data straight to the Jpeg loader.
  513. if (!ilLoadL_JPEG(JpegData, JpegHeaderSize + Header.MipLengths[i]))
  514. return IL_FALSE;
  515. // The image data is in BGR(A) order, even though it is Jpeg-compressed.
  516. if (Image->Format == IL_RGBA)
  517. Image->Format = IL_BGRA;
  518. if (Image->Format == IL_RGB)
  519. Image->Format = IL_BGR;
  520. ifree(JpegData);
  521. //}
  522. ifree(JpegHeader);
  523. #endif//IL_NO_JPEG
  524. break;
  525. case BLP_RAW:
  526. switch (Header.PictureType)
  527. {
  528. // There is no alpha list, so we just read like a normal indexed image.
  529. case BLP_RAW_NO_ALPHA:
  530. for (i = 0; i < 16; i++) {  // Possible maximum of 16 mipmaps
  531. if (!BaseCreated) {  // Have not created the base image yet, so use ilTexImage.
  532. if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
  533. return IL_FALSE;
  534. Image = iCurImage;
  535. BaseCreated = IL_TRUE;
  536. // We have a BGRA palette.
  537. Image->Pal.Palette = (ILubyte*)ialloc(256 * 4);
  538. if (Image->Pal.Palette == NULL)
  539. return IL_FALSE;
  540. Image->Pal.PalSize = 1024;
  541. Image->Pal.PalType = IL_PAL_BGRA32;
  542. // Read in the palette ...
  543. if (iread(Image->Pal.Palette, 1, 1024) != 1024)
  544. return IL_FALSE;
  545. }
  546. else {
  547. if (Image->Width == 1 && Image->Height == 1)  // Already at the smallest mipmap (1x1), so we are done.
  548. break;
  549. if (Header.MipOffsets[i] == 0 || Header.MipLengths[i] == 0)  // No more mipmaps in the file.
  550. break;
  551. Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOR_INDEX, IL_UNSIGNED_BYTE, NULL);
  552. if (Image->Mipmaps == NULL)
  553. return IL_FALSE;
  554. // Copy the palette from the first image before we change our Image pointer.
  555. Image->Mipmaps->Pal.Palette = (ILubyte*)ialloc(256 * 4);
  556. if (Image->Mipmaps->Pal.Palette == NULL)
  557. return IL_FALSE;
  558. Image->Mipmaps->Pal.PalSize = 1024;
  559. Image->Mipmaps->Pal.PalType = IL_PAL_BGRA32;
  560. memcpy(Image->Mipmaps->Pal.Palette, Image->Pal.Palette, 1024);
  561. // Move to the next mipmap in the linked list.
  562. Image = Image->Mipmaps;
  563. }
  564. // The origin should be in the upper left.
  565. Image->Origin = IL_ORIGIN_UPPER_LEFT;
  566. // Seek to the data and read it.
  567. iseek(Header.MipOffsets[i], IL_SEEK_SET);
  568. if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData)
  569. return IL_FALSE;
  570. }
  571. break;
  572. // These cases are identical and have an alpha list following the image data.
  573. case BLP_RAW_PLUS_ALPHA1:
  574. case BLP_RAW_PLUS_ALPHA2:
  575. // Create the image.
  576. if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL))
  577. return IL_FALSE;
  578. DataAndAlpha = (ILubyte*)ialloc(Header.Width * Header.Height);
  579. Palette = (ILubyte*)ialloc(256 * 4);
  580. if (DataAndAlpha == NULL || Palette == NULL) {
  581. ifree(DataAndAlpha);
  582. ifree(Palette);
  583. return IL_FALSE;
  584. }
  585. // Read in the data and the palette.
  586. if (iread(Palette, 1, 1024) != 1024) {
  587. ifree(Palette);
  588. return IL_FALSE;
  589. }
  590. // Seek to the data and read it.
  591. iseek(Header.MipOffsets[i], IL_SEEK_SET);
  592. if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) {
  593. ifree(DataAndAlpha);
  594. ifree(Palette);
  595. return IL_FALSE;
  596. }
  597. // Convert the color-indexed data to BGRX.
  598. for (i = 0; i < Header.Width * Header.Height; i++) {
  599. Image->Data[i*4]   = Palette[DataAndAlpha[i]*4];
  600. Image->Data[i*4+1] = Palette[DataAndAlpha[i]*4+1];
  601. Image->Data[i*4+2] = Palette[DataAndAlpha[i]*4+2];
  602. }
  603. // Read in the alpha list.
  604. if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) {
  605. ifree(DataAndAlpha);
  606. ifree(Palette);
  607. return IL_FALSE;
  608. }
  609. // Finally put the alpha data into the image data.
  610. for (i = 0; i < Header.Width * Header.Height; i++) {
  611. Image->Data[i*4+3] = DataAndAlpha[i];
  612. }
  613. ifree(DataAndAlpha);
  614. ifree(Palette);
  615. break;
  616. }
  617. break;
  618. //default:  // Should already be checked by iCheckBlp1.
  619. }
  620. // Set the origin (always upper left).
  621. Image->Origin = IL_ORIGIN_UPPER_LEFT;
  622. return ilFixImage();
  623. }
  624. #endif//IL_NO_BLP