SWF_Image.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "../renderer/Image.h"
  23. //#include "../../renderer/ImageTools/ImageProcess.h"
  24. #include "../renderer/jpeg-6/jpeglib.h"
  25. /*
  26. ========================
  27. idSWF::idDecompressJPEG
  28. These are the static callback functions the jpeg library calls
  29. ========================
  30. */
  31. void swf_jpeg_error_exit( jpeg_common_struct * cinfo ) {
  32. char buffer[JMSG_LENGTH_MAX] = {0};
  33. (*cinfo->err->format_message)( cinfo, buffer );
  34. throw idException( buffer );
  35. }
  36. void swf_jpeg_output_message( jpeg_common_struct * cinfo ) {
  37. char buffer[JMSG_LENGTH_MAX] = {0};
  38. (*cinfo->err->format_message)( cinfo, buffer );
  39. idLib::Printf( "%s\n", buffer );
  40. }
  41. void swf_jpeg_init_source( jpeg_decompress_struct * cinfo ) {
  42. }
  43. boolean swf_jpeg_fill_input_buffer( jpeg_decompress_struct * cinfo ) {
  44. return TRUE;
  45. }
  46. void swf_jpeg_skip_input_data( jpeg_decompress_struct * cinfo, long num_bytes ) {
  47. cinfo->src->next_input_byte += num_bytes;
  48. cinfo->src->bytes_in_buffer -= num_bytes;
  49. }
  50. void swf_jpeg_term_source( jpeg_decompress_struct * cinfo ) {
  51. }
  52. /*
  53. ========================
  54. idSWF::idDecompressJPEG::idDecompressJPEG
  55. ========================
  56. */
  57. idSWF::idDecompressJPEG::idDecompressJPEG() {
  58. jpeg_decompress_struct * cinfo = new (TAG_SWF) jpeg_decompress_struct;
  59. memset( cinfo, 0, sizeof( *cinfo ) );
  60. cinfo->err = new (TAG_SWF) jpeg_error_mgr;
  61. memset( cinfo->err, 0, sizeof( jpeg_error_mgr ) );
  62. jpeg_std_error( cinfo->err );
  63. cinfo->err->error_exit = swf_jpeg_error_exit;
  64. cinfo->err->output_message = swf_jpeg_output_message;
  65. jpeg_create_decompress( cinfo );
  66. vinfo = cinfo;
  67. }
  68. /*
  69. ========================
  70. idSWF::idDecompressJPEG::~idDecompressJPEG
  71. ========================
  72. */
  73. idSWF::idDecompressJPEG::~idDecompressJPEG() {
  74. jpeg_decompress_struct * cinfo = (jpeg_decompress_struct *)vinfo;
  75. jpeg_destroy_decompress( cinfo );
  76. delete cinfo->err;
  77. delete cinfo;
  78. }
  79. /*
  80. ========================
  81. idSWF::idDecompressJPEG::Load
  82. ========================
  83. */
  84. byte * idSWF::idDecompressJPEG::Load( const byte * input, int inputSize, int & width, int & height ) {
  85. jpeg_decompress_struct * cinfo = (jpeg_decompress_struct *)vinfo;
  86. try {
  87. width = 0;
  88. height = 0;
  89. jpeg_source_mgr src;
  90. memset( &src, 0, sizeof( src ) );
  91. src.next_input_byte = (JOCTET *)input;
  92. src.bytes_in_buffer = inputSize;
  93. src.init_source = swf_jpeg_init_source;
  94. src.fill_input_buffer = swf_jpeg_fill_input_buffer;
  95. src.skip_input_data = swf_jpeg_skip_input_data;
  96. src.resync_to_restart = jpeg_resync_to_restart;
  97. src.term_source = swf_jpeg_term_source;
  98. cinfo->src = &src;
  99. int result = 0;
  100. do {
  101. result = jpeg_read_header( cinfo, FALSE );
  102. } while ( result == JPEG_HEADER_TABLES_ONLY );
  103. if ( result == JPEG_SUSPENDED ) {
  104. return NULL;
  105. }
  106. jpeg_start_decompress( cinfo );
  107. if ( cinfo->output_components != 4 ) {
  108. // This shouldn't really be possible, unless the source image is some kind of strange grayscale format or something
  109. idLib::Warning( "JPEG output is not 4 components" );
  110. jpeg_abort_decompress( cinfo );
  111. cinfo->src = NULL; // value goes out of scope
  112. return NULL;
  113. }
  114. int outputSize = cinfo->output_width * cinfo->output_height * cinfo->output_components;
  115. byte * output = (byte *)Mem_Alloc( outputSize, TAG_SWF );
  116. memset( output, 255, outputSize );
  117. while ( cinfo->output_scanline < cinfo->output_height ) {
  118. JSAMPROW scanlines = output + cinfo->output_scanline * cinfo->output_width * cinfo->output_components;
  119. jpeg_read_scanlines( cinfo, &scanlines, 1 );
  120. }
  121. jpeg_finish_decompress( cinfo );
  122. width = cinfo->output_width;
  123. height = cinfo->output_height;
  124. cinfo->src = NULL; // value goes out of scope
  125. return output;
  126. } catch ( idException & ) {
  127. swf_jpeg_output_message( (jpeg_common_struct *)cinfo );
  128. return NULL;
  129. }
  130. }
  131. /*
  132. ========================
  133. idSWF::WriteSwfImageAtlas
  134. Now that all images have been found, allocate them in an atlas
  135. and write it out.
  136. ========================
  137. */
  138. void RectAllocator( const idList<idVec2i> &inputSizes, idList<idVec2i> &outputPositions, idVec2i &totalSize );
  139. float RectPackingFraction( const idList<idVec2i> &inputSizes, const idVec2i totalSize );
  140. void idSWF::WriteSwfImageAtlas( const char *filename ) {
  141. idList<idVec2i> inputSizes;
  142. inputSizes.SetNum( packImages.Num() );
  143. for ( int i = 0 ; i < packImages.Num() ; i++ ) {
  144. // these are in DXT blocks, not pixels
  145. inputSizes[i] = packImages[i].allocSize;
  146. }
  147. idList<idVec2i> outputPositions;
  148. idVec2i totalSize;
  149. // smart allocator
  150. RectAllocator( inputSizes, outputPositions, totalSize );
  151. float frac = RectPackingFraction( inputSizes, totalSize );
  152. idLib::Printf( "%5.2f packing fraction in %ix%i image\n", frac, totalSize.x*4, totalSize.y*4 );
  153. int atlasWidth = Max( 4, totalSize.x * 4 ) ;
  154. int atlasHeight = Max( 4, totalSize.y * 4 ) ;
  155. // we require multiple-of-128 widths to use the image data directly
  156. // without re-packing on the 360 and PS3. The growth checks in RectAllocator()
  157. // will always align, but a single image won't necessarily be.
  158. atlasWidth = ( atlasWidth + 127 ) & ~127;
  159. idTempArray<byte> swfAtlas( atlasWidth * atlasHeight * 4 );
  160. // fill everything with solid red
  161. for ( int i = 0; i < atlasWidth * atlasHeight; i++ ) {
  162. swfAtlas[i*4+0] = 255;
  163. swfAtlas[i*4+1] = 0;
  164. swfAtlas[i*4+2] = 0;
  165. swfAtlas[i*4+3] = 255;
  166. }
  167. // allocate the blocks and copy the texels
  168. for ( int i = 0 ; i < packImages.Num() ; i++ ) {
  169. imageToPack_t & pack = packImages[i];
  170. assert( pack.imageData != NULL );
  171. int blockWidth = pack.allocSize.x;
  172. int blockHeight = pack.allocSize.y;
  173. int x = outputPositions[i].x;
  174. int y = outputPositions[i].y;
  175. // get the range for each channel so we can maximize it
  176. // for better compression
  177. int minV[4] = { 255, 255, 255, 255 };
  178. int maxV[4] = { 0, 0, 0, 0 };
  179. for ( int j = 0 ; j < pack.trueSize.x * pack.trueSize.y * 4 ; j++ ) {
  180. int v = pack.imageData[ j ];
  181. int x = j & 3;
  182. if ( v < minV[x] ) {
  183. minV[x] = v;
  184. }
  185. if ( v > maxV[x] ) {
  186. maxV[x] = v;
  187. }
  188. }
  189. // idLib::Printf( "Color normalize: %3i:%3i %3i:%3i %3i:%3i %3i:%3i\n",
  190. // minV[0], maxV[0], minV[1], maxV[1], minV[2], maxV[2], minV[3], maxV[3] );
  191. // don't divide by zero
  192. for ( int x = 0 ; x < 4 ; x++ ) {
  193. if ( maxV[x] == 0 ) {
  194. maxV[x] = 1;
  195. }
  196. }
  197. // rescale the image
  198. //
  199. // Note that this must be done in RGBA space, before YCoCg conversion,
  200. // or the scale factors couldn't be combined with the normal swf coloring.
  201. //
  202. // If we create an idMaterial for each atlas element, we could add
  203. // a bias as well as a scale to enable us to take advantage of the
  204. // min values as well as the max, but very few gui images don't go to black,
  205. // and just doing a scale avoids changing more code.
  206. for ( int j = 0; j < pack.trueSize.x * pack.trueSize.y * 4; j++ ) {
  207. int v = pack.imageData[ j ];
  208. int x = j & 3;
  209. v = v * 255 / maxV[x];
  210. pack.imageData[ j ] = v;
  211. }
  212. assert( ( x + blockWidth )* 4 <= atlasWidth );
  213. assert( ( y + blockHeight )* 4 <= atlasHeight );
  214. // Extend the pixels with clamp-to-edge to the edge of the allocation block.
  215. // The GPU hardware addressing should completely ignore texels outside the true block
  216. // size, but the compressor works on complete blocks, regardless of the true rect size.
  217. x <<= 2;
  218. y <<= 2;
  219. for ( int dstY = 0; dstY < blockHeight<<2; dstY++ ) {
  220. int srcY = dstY-1;
  221. if ( srcY < 0 ) {
  222. srcY = 0;
  223. }
  224. if ( srcY >= pack.trueSize.y ) {
  225. srcY = pack.trueSize.y - 1;
  226. }
  227. for ( int dstX = 0 ; dstX < blockWidth<<2 ; dstX++ ) {
  228. int srcX = dstX-1;
  229. if ( srcX < 0 ) {
  230. srcX = 0;
  231. }
  232. if ( srcX >= pack.trueSize.x ) {
  233. srcX = pack.trueSize.x - 1;
  234. }
  235. ((int *)swfAtlas.Ptr())[ (y+dstY) * atlasWidth + (x+dstX) ] =
  236. ((int *)pack.imageData)[ srcY * pack.trueSize.x + srcX ];
  237. }
  238. }
  239. // save the information in the SWF dictionary
  240. idSWFDictionaryEntry * entry = FindDictionaryEntry( pack.characterID );
  241. assert( entry->material == NULL );
  242. entry->imageSize.x = pack.trueSize.x;
  243. entry->imageSize.y = pack.trueSize.y;
  244. entry->imageAtlasOffset.x = x + 1;
  245. entry->imageAtlasOffset.y = y + 1;
  246. for ( int i = 0; i < 4; i++ ) {
  247. entry->channelScale[i] = maxV[i] / 255.0f;
  248. }
  249. Mem_Free( pack.imageData );
  250. pack.imageData = NULL;
  251. }
  252. // the TGA is only for examination during development
  253. R_WriteTGA( filename, swfAtlas.Ptr(), atlasWidth, atlasHeight, false, "fs_basepath" );
  254. }
  255. /*
  256. ========================
  257. idSWF::LoadImage
  258. Loads RGBA data into an image at the specificied character id in the dictionary
  259. ========================
  260. */
  261. void idSWF::LoadImage( int characterID, const byte * imageData, int width, int height ) {
  262. idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_IMAGE );
  263. if ( entry == NULL ) {
  264. return;
  265. }
  266. // save the data off so we can do the image atlas allocation after we have collected
  267. // all the images that are used by the entire swf
  268. imageToPack_t pack;
  269. pack.characterID = characterID;
  270. pack.imageData = (byte *)Mem_Alloc( width*height*4, TAG_SWF );
  271. memcpy( pack.imageData, imageData, width*height*4 );
  272. pack.trueSize.x = width;
  273. pack.trueSize.y = height;
  274. for ( int i = 0 ; i < 2 ; i++ ) {
  275. int v = pack.trueSize[i];
  276. // Swf images are usually completely random in size, but perform all allocations in
  277. // DXT blocks of 4. If we choose to DCT / HDP encode the image block, we should probably
  278. // increae the block size to 8 or 16 to prevent neighbor effects.
  279. v = ( v + 3 ) >> 2;
  280. // Allways allocate a single pixel border around the images so there won't be any edge
  281. // bleeds. This can often be hidden in in the round-up to DXT size.
  282. if ( ( v << 2 ) - pack.trueSize[i] < 2 ) {
  283. v++;
  284. }
  285. pack.allocSize[i] = v;
  286. }
  287. packImages.Append( pack );
  288. entry->material = NULL;
  289. }
  290. /*
  291. ========================
  292. idSWF::JPEGTables
  293. Reads jpeg table data, there can only be one of these in the file, and it has to come before any DefineBits tags
  294. We don't have to worry about clearing the jpeg object because jpeglib will automagically overwrite any tables that are already set (I think?)
  295. ========================
  296. */
  297. void idSWF::JPEGTables( idSWFBitStream & bitstream ) {
  298. if ( bitstream.Length() == 0 ) {
  299. // no clue why this happens
  300. return;
  301. }
  302. int width, height;
  303. jpeg.Load( bitstream.ReadData( bitstream.Length() ), bitstream.Length(), width, height );
  304. }
  305. /*
  306. ========================
  307. idSWF::DefineBits
  308. Reads a partial jpeg image, using the tables set by the JPEGTables tag
  309. ========================
  310. */
  311. void idSWF::DefineBits( idSWFBitStream & bitstream ) {
  312. uint16 characterID = bitstream.ReadU16();
  313. int jpegSize = bitstream.Length() - sizeof( uint16 );
  314. int width, height;
  315. byte * imageData = jpeg.Load( bitstream.ReadData( jpegSize ), jpegSize, width, height );
  316. if ( imageData == NULL ) {
  317. return;
  318. }
  319. LoadImage( characterID, imageData, width, height );
  320. Mem_Free( imageData );
  321. }
  322. /*
  323. ========================
  324. idSWF::DefineBitsJPEG2
  325. Identical to DefineBits, except it uses a local JPEG table (not the one defined by JPEGTables)
  326. ========================
  327. */
  328. void idSWF::DefineBitsJPEG2( idSWFBitStream & bitstream ) {
  329. uint16 characterID = bitstream.ReadU16();
  330. idDecompressJPEG jpeg;
  331. int jpegSize = bitstream.Length() - sizeof( uint16 );
  332. int width, height;
  333. byte * imageData = jpeg.Load( bitstream.ReadData( jpegSize ), jpegSize, width, height );
  334. if ( imageData == NULL ) {
  335. return;
  336. }
  337. LoadImage( characterID, imageData, width, height );
  338. Mem_Free( imageData );
  339. }
  340. /*
  341. ========================
  342. idSWF::DefineBitsJPEG3
  343. Mostly identical to DefineBitsJPEG2, except it has an additional zlib compressed alpha map
  344. ========================
  345. */
  346. void idSWF::DefineBitsJPEG3( idSWFBitStream & bitstream ) {
  347. uint16 characterID = bitstream.ReadU16();
  348. uint32 jpegSize = bitstream.ReadU32();
  349. idDecompressJPEG jpeg;
  350. int width, height;
  351. byte * imageData = jpeg.Load( bitstream.ReadData( jpegSize ), jpegSize, width, height );
  352. if ( imageData == NULL ) {
  353. return;
  354. }
  355. {
  356. idTempArray<byte> alphaMap( width * height );
  357. int alphaSize = bitstream.Length() - jpegSize - sizeof( characterID ) - sizeof( jpegSize );
  358. if ( !Inflate( bitstream.ReadData( alphaSize ), alphaSize, alphaMap.Ptr(), (int)alphaMap.Size() ) ) {
  359. idLib::Warning( "DefineBitsJPEG3: Failed to inflate alpha data" );
  360. Mem_Free( imageData );
  361. return;
  362. }
  363. for ( int i = 0; i < width * height; i++ ) {
  364. imageData[i*4+3] = alphaMap[i];
  365. }
  366. }
  367. LoadImage( characterID, imageData, width, height );
  368. Mem_Free( imageData );
  369. }
  370. /*
  371. ========================
  372. idSWF::DefineBitsLossless
  373. ========================
  374. */
  375. void idSWF::DefineBitsLossless( idSWFBitStream & bitstream ) {
  376. uint16 characterID = bitstream.ReadU16();
  377. uint8 format = bitstream.ReadU8();
  378. uint16 width = bitstream.ReadU16();
  379. uint16 height = bitstream.ReadU16();
  380. idTempArray< byte > buf( width * height * 4 );
  381. byte * imageData = buf.Ptr();
  382. if ( format == 3 ) {
  383. uint32 paddedWidth = ( width + 3 ) & ~3;
  384. uint32 colorTableSize = ( bitstream.ReadU8() + 1 ) * 3;
  385. idTempArray<byte> colorMapData( colorTableSize + ( paddedWidth * height ) );
  386. uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
  387. if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, colorMapData.Ptr(), (int)colorMapData.Size() ) ) {
  388. idLib::Warning( "DefineBitsLossless: Failed to inflate color map data" );
  389. return;
  390. }
  391. byte * indices = colorMapData.Ptr() + colorTableSize;
  392. for ( int h = 0; h < height; h++ ) {
  393. for ( int w = 0; w < width; w++ ) {
  394. byte index = indices[w + (h*paddedWidth)];
  395. byte * pixel = &imageData[(w + (h*width)) * 4];
  396. pixel[0] = colorMapData[index * 3 + 0];
  397. pixel[1] = colorMapData[index * 3 + 1];
  398. pixel[2] = colorMapData[index * 3 + 2];
  399. pixel[3] = 0xFF;
  400. }
  401. }
  402. } else if ( format == 4 ) {
  403. uint32 paddedWidth = ( width + 1 ) & 1;
  404. idTempArray<uint16> bitmapData( paddedWidth * height * 2 );
  405. uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
  406. if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, (byte *)bitmapData.Ptr(), (int)bitmapData.Size() ) ) {
  407. idLib::Warning( "DefineBitsLossless: Failed to inflate bitmap data" );
  408. return;
  409. }
  410. for ( int h = 0; h < height; h++ ) {
  411. for ( int w = 0; w < width; w++ ) {
  412. uint16 pix15 = bitmapData[w + (h*paddedWidth)];
  413. idSwap::Big( pix15 );
  414. byte * pixel = &imageData[(w + (h*width)) * 4];
  415. pixel[0] = ( pix15 >> 10 ) & 0x1F;
  416. pixel[1] = ( pix15 >> 5 ) & 0x1F;
  417. pixel[2] = ( pix15 >> 0 ) & 0x1F;
  418. pixel[3] = 0xFF;
  419. }
  420. }
  421. } else if ( format == 5 ) {
  422. idTempArray<uint32> bitmapData( width * height );
  423. uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
  424. if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, (byte *)bitmapData.Ptr(), (int)bitmapData.Size() ) ) {
  425. idLib::Warning( "DefineBitsLossless: Failed to inflate bitmap data" );
  426. return;
  427. }
  428. for ( int h = 0; h < height; h++ ) {
  429. for ( int w = 0; w < width; w++ ) {
  430. uint32 pix24 = bitmapData[w + (h*width)];
  431. idSwap::Big( pix24 );
  432. byte * pixel = &imageData[(w + (h*width)) * 4];
  433. pixel[0] = ( pix24 >> 16 ) & 0xFF;
  434. pixel[1] = ( pix24 >> 8 ) & 0xFF;
  435. pixel[2] = ( pix24 >> 0 ) & 0xFF;
  436. pixel[3] = 0xFF;
  437. }
  438. }
  439. } else {
  440. idLib::Warning( "DefineBitsLossless: Unknown image format %d", format );
  441. memset( imageData, 0xFF, width * height * 4 );
  442. }
  443. LoadImage( characterID, imageData, width, height );
  444. }
  445. /*
  446. ========================
  447. idSWF::DefineBitsLossless2
  448. ========================
  449. */
  450. void idSWF::DefineBitsLossless2( idSWFBitStream & bitstream ) {
  451. uint16 characterID = bitstream.ReadU16();
  452. uint8 format = bitstream.ReadU8();
  453. uint16 width = bitstream.ReadU16();
  454. uint16 height = bitstream.ReadU16();
  455. idTempArray< byte > buf( width * height * 4 );
  456. byte * imageData = buf.Ptr();
  457. if ( format == 3 ) {
  458. uint32 paddedWidth = ( width + 3 ) & ~3;
  459. uint32 colorTableSize = ( bitstream.ReadU8() + 1 ) * 4;
  460. idTempArray<byte> colorMapData( colorTableSize + ( paddedWidth * height ) );
  461. uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
  462. if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, colorMapData.Ptr(), (int)colorMapData.Size() ) ) {
  463. idLib::Warning( "DefineBitsLossless2: Failed to inflate color map data" );
  464. return;
  465. }
  466. byte * indices = colorMapData.Ptr() + colorTableSize;
  467. for ( int h = 0; h < height; h++ ) {
  468. for ( int w = 0; w < width; w++ ) {
  469. byte index = indices[w + (h*paddedWidth)];
  470. byte * pixel = &imageData[(w + (h*width)) * 4];
  471. pixel[0] = colorMapData[index * 4 + 0];
  472. pixel[1] = colorMapData[index * 4 + 1];
  473. pixel[2] = colorMapData[index * 4 + 2];
  474. pixel[3] = colorMapData[index * 4 + 3];
  475. }
  476. }
  477. } else if ( format == 5 ) {
  478. idTempArray<uint32> bitmapData( width * height );
  479. uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
  480. if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, (byte *)bitmapData.Ptr(), (int)bitmapData.Size() ) ) {
  481. idLib::Warning( "DefineBitsLossless2: Failed to inflate bitmap data" );
  482. return;
  483. }
  484. for ( int h = 0; h < height; h++ ) {
  485. for ( int w = 0; w < width; w++ ) {
  486. uint32 pix32 = bitmapData[w + (h*width)];
  487. idSwap::Big( pix32 );
  488. byte * pixel = &imageData[(w + (h*width)) * 4];
  489. pixel[0] = ( pix32 >> 16 ) & 0xFF;
  490. pixel[1] = ( pix32 >> 8 ) & 0xFF;
  491. pixel[2] = ( pix32 >> 0 ) & 0xFF;
  492. pixel[3] = ( pix32 >> 24 ) & 0xFF;
  493. }
  494. }
  495. } else {
  496. idLib::Warning( "DefineBitsLossless2: Unknown image format %d", format );
  497. memset( imageData, 0xFF, width * height * 4 );
  498. }
  499. LoadImage( characterID, imageData, width, height );
  500. }