Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2495 lines
71 KiB

  1. //======= Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifdef IS_WINDOWS_PC
  7. #include <windows.h>
  8. #endif
  9. #include "bitmap/imageformat.h"
  10. #include "basetypes.h"
  11. #include "tier0/dbg.h"
  12. #ifndef _PS3
  13. #include <malloc.h>
  14. #include <memory.h>
  15. #endif
  16. #include "mathlib/mathlib.h"
  17. #include "mathlib/vector.h"
  18. #include "tier1/utlmemory.h"
  19. #include "tier1/strtools.h"
  20. #include "mathlib/compressed_vector.h"
  21. #include "nvtc.h"
  22. #if defined( POSIX ) && !defined( _PS3 )
  23. typedef int32 *DWORD_PTR;
  24. #endif
  25. #include "bitmap/floatbitmap.h"
  26. #define STB_DXT_IMPLEMENTATION
  27. #include "bitmap/stb_dxt.h"
  28. // Should be last include
  29. #include "tier0/memdbgon.h"
  30. //-----------------------------------------------------------------------------
  31. // Various important function types for each color format
  32. //-----------------------------------------------------------------------------
  33. typedef void (*UserFormatToRGBA8888Func_t )( const uint8 *src, uint8 *dst, int numPixels );
  34. typedef void (*RGBA8888ToUserFormatFunc_t )( const uint8 *src, uint8 *dst, int numPixels );
  35. namespace ImageLoader
  36. {
  37. // Color Conversion functions
  38. static void RGBA8888ToRGBA32323232F( const uint8 *src, uint8 *dst, int numPixels );
  39. static void RGBA8888ToRGB323232F( const uint8 *src, uint8 *dst, int numPixels );
  40. static void RGBA8888ToRG3232F( const uint8 *src, uint8 *dst, int numPixels );
  41. static void RGBA8888ToR32F( const uint8 *src, uint8 *dst, int numPixels );
  42. static void RGBA8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  43. static void RGBA8888ToABGR8888( const uint8 *src, uint8 *dst, int numPixels );
  44. static void RGBA8888ToRGB888( const uint8 *src, uint8 *dst, int numPixels );
  45. static void RGBA8888ToBGR888( const uint8 *src, uint8 *dst, int numPixels );
  46. static void RGBA8888ToRGB565( const uint8 *src, uint8 *dst, int numPixels );
  47. static void RGBA8888ToI8( const uint8 *src, uint8 *dst, int numPixels );
  48. static void RGBA8888ToIA88( const uint8 *src, uint8 *dst, int numPixels );
  49. static void RGBA8888ToP8( const uint8 *src, uint8 *dst, int numPixels );
  50. static void RGBA8888ToA8( const uint8 *src, uint8 *dst, int numPixels );
  51. static void RGBA8888ToRGB888_BLUESCREEN( const uint8 *src, uint8 *dst, int numPixels );
  52. static void RGBA8888ToBGR888_BLUESCREEN( const uint8 *src, uint8 *dst, int numPixels );
  53. static void RGBA8888ToARGB8888( const uint8 *src, uint8 *dst, int numPixels );
  54. static void RGBA8888ToBGRA8888( const uint8 *src, uint8 *dst, int numPixels );
  55. static void RGBA8888ToBGRX8888( const uint8 *src, uint8 *dst, int numPixels );
  56. static void RGBA8888ToBGR565( const uint8 *src, uint8 *dst, int numPixels );
  57. static void RGBA8888ToBGRX5551( const uint8 *src, uint8 *dst, int numPixels );
  58. static void RGBA8888ToBGRA5551( const uint8 *src, uint8 *dst, int numPixels );
  59. static void RGBA8888ToBGRA4444( const uint8 *src, uint8 *dst, int numPixels );
  60. static void RGBA8888ToUV88( const uint8 *src, uint8 *dst, int numPixels );
  61. static void RGBA8888ToUVWQ8888( const uint8 *src, uint8 *dst, int numPixels );
  62. static void RGBA8888ToUVLX8888( const uint8 *src, uint8 *dst, int numPixels );
  63. static void RGBA8888ToRGBA16161616F( const uint8 *src, uint8 *dst, int numPixels );
  64. static void ABGR8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  65. static void RGB888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  66. static void BGR888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  67. static void RGB565ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  68. static void I8ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  69. static void IA88ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  70. static void P8ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  71. static void A8ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  72. static void RGB888_BLUESCREENToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  73. static void BGR888_BLUESCREENToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  74. static void ARGB8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  75. static void BGRA8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  76. static void BGRX8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  77. static void BGR565ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  78. static void BGRX5551ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  79. static void BGRA5551ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  80. static void BGRA4444ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  81. static void UV88ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  82. static void UVWQ8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  83. static void UVLX8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  84. static void RGBA16161616ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  85. //static void RGBA16161616FToRGBA8888( const uint8 *src, uint8 *dst, int numPixels );
  86. static UserFormatToRGBA8888Func_t GetUserFormatToRGBA8888Func_t( ImageFormat srcImageFormat )
  87. {
  88. switch( srcImageFormat )
  89. {
  90. case IMAGE_FORMAT_RGBA8888:
  91. return RGBA8888ToRGBA8888;
  92. case IMAGE_FORMAT_ABGR8888:
  93. return ABGR8888ToRGBA8888;
  94. case IMAGE_FORMAT_RGB888:
  95. return RGB888ToRGBA8888;
  96. case IMAGE_FORMAT_BGR888:
  97. return BGR888ToRGBA8888;
  98. case IMAGE_FORMAT_RGB565:
  99. return NULL;
  100. case IMAGE_FORMAT_I8:
  101. return I8ToRGBA8888;
  102. case IMAGE_FORMAT_IA88:
  103. return IA88ToRGBA8888;
  104. case IMAGE_FORMAT_A8:
  105. return A8ToRGBA8888;
  106. case IMAGE_FORMAT_RGB888_BLUESCREEN:
  107. return RGB888_BLUESCREENToRGBA8888;
  108. case IMAGE_FORMAT_BGR888_BLUESCREEN:
  109. return BGR888_BLUESCREENToRGBA8888;
  110. case IMAGE_FORMAT_ARGB8888:
  111. return ARGB8888ToRGBA8888;
  112. case IMAGE_FORMAT_BGRA8888:
  113. return BGRA8888ToRGBA8888;
  114. case IMAGE_FORMAT_BGRX8888:
  115. return BGRX8888ToRGBA8888;
  116. case IMAGE_FORMAT_BGR565:
  117. return BGR565ToRGBA8888;
  118. case IMAGE_FORMAT_BGRX5551:
  119. return BGRX5551ToRGBA8888;
  120. case IMAGE_FORMAT_BGRA5551:
  121. return BGRA5551ToRGBA8888;
  122. case IMAGE_FORMAT_BGRA4444:
  123. return BGRA4444ToRGBA8888;
  124. case IMAGE_FORMAT_UV88:
  125. return UV88ToRGBA8888;
  126. case IMAGE_FORMAT_UVWQ8888:
  127. return UVWQ8888ToRGBA8888;
  128. case IMAGE_FORMAT_UVLX8888:
  129. return UVLX8888ToRGBA8888;
  130. case IMAGE_FORMAT_RGBA16161616:
  131. return RGBA16161616ToRGBA8888;
  132. case IMAGE_FORMAT_RGBA16161616F:
  133. return NULL;
  134. case IMAGE_FORMAT_RGBA1010102:
  135. return NULL;
  136. case IMAGE_FORMAT_BGRA1010102:
  137. return NULL;
  138. case IMAGE_FORMAT_R16F:
  139. return NULL;
  140. #if defined( _X360 )
  141. case IMAGE_FORMAT_LINEAR_RGBA8888:
  142. return RGBA8888ToRGBA8888;
  143. case IMAGE_FORMAT_LINEAR_ABGR8888:
  144. return ABGR8888ToRGBA8888;
  145. case IMAGE_FORMAT_LINEAR_RGB888:
  146. return RGB888ToRGBA8888;
  147. case IMAGE_FORMAT_LINEAR_BGR888:
  148. return BGR888ToRGBA8888;
  149. case IMAGE_FORMAT_LINEAR_I8:
  150. return I8ToRGBA8888;
  151. case IMAGE_FORMAT_LINEAR_ARGB8888:
  152. return ARGB8888ToRGBA8888;
  153. case IMAGE_FORMAT_LINEAR_BGRA8888:
  154. return BGRA8888ToRGBA8888;
  155. case IMAGE_FORMAT_LINEAR_BGRX8888:
  156. return BGRX8888ToRGBA8888;
  157. case IMAGE_FORMAT_LINEAR_BGRX5551:
  158. return BGRX5551ToRGBA8888;
  159. case IMAGE_FORMAT_LINEAR_RGBA16161616:
  160. return RGBA16161616ToRGBA8888;
  161. case IMAGE_FORMAT_LINEAR_A8:
  162. return A8ToRGBA8888;
  163. #endif
  164. default:
  165. return NULL;
  166. }
  167. }
  168. static RGBA8888ToUserFormatFunc_t GetRGBA8888ToUserFormatFunc_t( ImageFormat dstImageFormat )
  169. {
  170. switch( dstImageFormat )
  171. {
  172. case IMAGE_FORMAT_RGBA32323232F:
  173. return RGBA8888ToRGBA32323232F;
  174. case IMAGE_FORMAT_RGB323232F:
  175. return RGBA8888ToRGB323232F;
  176. case IMAGE_FORMAT_RG3232F:
  177. return RGBA8888ToRG3232F;
  178. case IMAGE_FORMAT_R32F:
  179. return RGBA8888ToR32F;
  180. case IMAGE_FORMAT_RGBA8888:
  181. return RGBA8888ToRGBA8888;
  182. case IMAGE_FORMAT_ABGR8888:
  183. return RGBA8888ToABGR8888;
  184. case IMAGE_FORMAT_RGB888:
  185. return RGBA8888ToRGB888;
  186. case IMAGE_FORMAT_BGR888:
  187. return RGBA8888ToBGR888;
  188. case IMAGE_FORMAT_RGB565:
  189. return NULL;
  190. case IMAGE_FORMAT_I8:
  191. return RGBA8888ToI8;
  192. case IMAGE_FORMAT_IA88:
  193. return RGBA8888ToIA88;
  194. case IMAGE_FORMAT_A8:
  195. return RGBA8888ToA8;
  196. case IMAGE_FORMAT_RGB888_BLUESCREEN:
  197. return RGBA8888ToRGB888_BLUESCREEN;
  198. case IMAGE_FORMAT_BGR888_BLUESCREEN:
  199. return RGBA8888ToBGR888_BLUESCREEN;
  200. case IMAGE_FORMAT_ARGB8888:
  201. return RGBA8888ToARGB8888;
  202. case IMAGE_FORMAT_BGRA8888:
  203. return RGBA8888ToBGRA8888;
  204. case IMAGE_FORMAT_BGRX8888:
  205. return RGBA8888ToBGRX8888;
  206. case IMAGE_FORMAT_BGR565:
  207. return RGBA8888ToBGR565;
  208. case IMAGE_FORMAT_BGRX5551:
  209. return RGBA8888ToBGRX5551;
  210. case IMAGE_FORMAT_BGRA5551:
  211. return RGBA8888ToBGRA5551;
  212. case IMAGE_FORMAT_BGRA4444:
  213. return RGBA8888ToBGRA4444;
  214. case IMAGE_FORMAT_UV88:
  215. return RGBA8888ToUV88;
  216. case IMAGE_FORMAT_UVWQ8888:
  217. return RGBA8888ToUVWQ8888;
  218. case IMAGE_FORMAT_UVLX8888:
  219. return RGBA8888ToUVLX8888;
  220. case IMAGE_FORMAT_RGBA16161616F:
  221. return RGBA8888ToRGBA16161616F;
  222. #if defined( _X360 )
  223. case IMAGE_FORMAT_LINEAR_RGBA8888:
  224. return RGBA8888ToRGBA8888;
  225. case IMAGE_FORMAT_LINEAR_ABGR8888:
  226. return RGBA8888ToABGR8888;
  227. case IMAGE_FORMAT_LINEAR_RGB888:
  228. return RGBA8888ToRGB888;
  229. case IMAGE_FORMAT_LINEAR_BGR888:
  230. return RGBA8888ToBGR888;
  231. case IMAGE_FORMAT_LINEAR_I8:
  232. return RGBA8888ToI8;
  233. case IMAGE_FORMAT_LINEAR_ARGB8888:
  234. return RGBA8888ToARGB8888;
  235. case IMAGE_FORMAT_LINEAR_BGRA8888:
  236. return RGBA8888ToBGRA8888;
  237. case IMAGE_FORMAT_LINEAR_BGRX8888:
  238. return RGBA8888ToBGRX8888;
  239. case IMAGE_FORMAT_LINEAR_BGRX5551:
  240. return RGBA8888ToBGRX5551;
  241. case IMAGE_FORMAT_LINEAR_A8:
  242. return RGBA8888ToA8;
  243. #endif
  244. default:
  245. return NULL;
  246. }
  247. }
  248. #pragma pack(1)
  249. struct DXTColBlock
  250. {
  251. uint16 col0;
  252. uint16 col1;
  253. // no bit fields - use bytes
  254. uint8 row[4];
  255. };
  256. struct DXTAlphaBlock3BitLinear
  257. {
  258. uint8 alpha0;
  259. uint8 alpha1;
  260. uint8 stuff[6];
  261. };
  262. #pragma pack()
  263. /*
  264. static unsigned int RescaleBitNumber( unsigned int nSrcValue, unsigned int nSrcBits, unsigned int nScaleToBits )
  265. {
  266. unsigned int nMaxSrc = ( 1 << nSrcBits ) - 1;
  267. float flValue = float( nSrcValue & nMaxSrc ) / float( nMaxSrc );
  268. unsigned int nMaxDest = ( 1 << nScaleToBits ) - 1;
  269. return ( unsigned int ) ( flValue * nMaxDest );
  270. }
  271. -- produces same results as bit-propagation below
  272. */
  273. static unsigned int RescaleBitNumber( unsigned int nSrcValue, unsigned int nSrcBits, unsigned int nScaleToBits )
  274. {
  275. unsigned int nMaxSrc = ( 1 << nSrcBits ) - 1;
  276. if ( nScaleToBits > nSrcBits )
  277. {
  278. return
  279. ( nSrcValue & nMaxSrc ) << ( nScaleToBits - nSrcBits ) |
  280. ( nSrcValue & nMaxSrc ) >> ( nSrcBits - ( nScaleToBits - nSrcBits ) );
  281. }
  282. else
  283. {
  284. return ( nSrcValue & nMaxSrc ) >> ( nSrcBits - nScaleToBits );
  285. }
  286. }
  287. static inline void GetColorBlockColorsBGRA8888( DXTColBlock *pBlock, BGRA8888_t *col_0,
  288. BGRA8888_t *col_1, BGRA8888_t *col_2,
  289. BGRA8888_t *col_3, uint16 & wrd )
  290. {
  291. // input data is assumed to be x86 order
  292. // swap to target platform for proper dxt decoding
  293. uint16 color0 = LittleShort( pBlock->col0 );
  294. uint16 color1 = LittleShort( pBlock->col1 );
  295. // shift to full precision
  296. col_0->a = 0xff;
  297. col_0->r = RescaleBitNumber( ((BGR565_t*)&color0)->r, 5, 8 );
  298. col_0->g = RescaleBitNumber( ((BGR565_t*)&color0)->g, 6, 8 );
  299. col_0->b = RescaleBitNumber( ((BGR565_t*)&color0)->b, 5, 8 );
  300. col_1->a = 0xff;
  301. col_1->r = RescaleBitNumber( ((BGR565_t*)&color1)->r, 5, 8 );
  302. col_1->g = RescaleBitNumber( ((BGR565_t*)&color1)->g, 6, 8 );
  303. col_1->b = RescaleBitNumber( ((BGR565_t*)&color1)->b, 5, 8 );
  304. if ( color0 > color1 )
  305. {
  306. // Four-color block: derive the other two colors.
  307. // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
  308. // These two bit codes correspond to the 2-bit fields
  309. // stored in the 64-bit block.
  310. wrd = ((uint16)col_0->r * 2 + (uint16)col_1->r )/3;
  311. // no +1 for rounding
  312. // as bits have been shifted to 888
  313. col_2->r = (BYTE)wrd;
  314. wrd = ((uint16)col_0->g * 2 + (uint16)col_1->g )/3;
  315. col_2->g = (BYTE)wrd;
  316. wrd = ((uint16)col_0->b * 2 + (uint16)col_1->b )/3;
  317. col_2->b = (BYTE)wrd;
  318. col_2->a = 0xff;
  319. wrd = ((uint16)col_0->r + (uint16)col_1->r *2 )/3;
  320. col_3->r = (BYTE)wrd;
  321. wrd = ((uint16)col_0->g + (uint16)col_1->g *2 )/3;
  322. col_3->g = (BYTE)wrd;
  323. wrd = ((uint16)col_0->b + (uint16)col_1->b *2 )/3;
  324. col_3->b = (BYTE)wrd;
  325. col_3->a = 0xff;
  326. }
  327. else
  328. {
  329. // Three-color block: derive the other color.
  330. // 00 = color_0, 01 = color_1, 10 = color_2,
  331. // 11 = transparent.
  332. // These two bit codes correspond to the 2-bit fields
  333. // stored in the 64-bit block.
  334. // explicit for each component, unlike some refrasts...????
  335. wrd = ((uint16)col_0->r + (uint16)col_1->r )/2;
  336. col_2->r = (BYTE)wrd;
  337. wrd = ((uint16)col_0->g + (uint16)col_1->g )/2;
  338. col_2->g = (BYTE)wrd;
  339. wrd = ((uint16)col_0->b + (uint16)col_1->b )/2;
  340. col_2->b = (BYTE)wrd;
  341. col_2->a = 0xff;
  342. col_3->r = 0x00; // random color to indicate alpha
  343. col_3->g = 0xff;
  344. col_3->b = 0xff;
  345. col_3->a = 0x00;
  346. }
  347. }
  348. template <class CDestPixel>
  349. static inline void DecodeColorBlock( CDestPixel *pOutputImage, DXTColBlock *pColorBlock, int width,
  350. BGRA8888_t *col_0, BGRA8888_t *col_1,
  351. BGRA8888_t *col_2, BGRA8888_t *col_3 )
  352. {
  353. // width is width of image in pixels
  354. uint32 bits;
  355. int r,n;
  356. // bit masks = 00000011, 00001100, 00110000, 11000000
  357. const uint32 masks[] = { 3 << 0, 3 << 2, 3 << 4, 3 << 6 };
  358. const int shift[] = { 0, 2, 4, 6 };
  359. // r steps through lines in y
  360. for ( r=0; r < 4; r++, pOutputImage += width-4 ) // no width*4 as uint32 ptr inc will *4
  361. {
  362. // width * 4 bytes per pixel per line
  363. // each j dxtc row is 4 lines of pixels
  364. // n steps through pixels
  365. for ( n=0; n < 4; n++ )
  366. {
  367. bits = pColorBlock->row[r] & masks[n];
  368. bits >>= shift[n];
  369. switch( bits )
  370. {
  371. case 0:
  372. *pOutputImage = *col_0;
  373. pOutputImage++; // increment to next output pixel
  374. break;
  375. case 1:
  376. *pOutputImage = *col_1;
  377. pOutputImage++;
  378. break;
  379. case 2:
  380. *pOutputImage = *col_2;
  381. pOutputImage++;
  382. break;
  383. case 3:
  384. *pOutputImage = *col_3;
  385. pOutputImage++;
  386. break;
  387. default:
  388. Assert( 0 );
  389. pOutputImage++;
  390. break;
  391. }
  392. }
  393. }
  394. }
  395. template <class CDestPixel>
  396. static inline void DecodeAlpha3BitLinear( CDestPixel *pImPos, DXTAlphaBlock3BitLinear *pAlphaBlock, int width, int nChannelSelect = 3 )
  397. {
  398. static BYTE gBits[4][4];
  399. static uint16 gAlphas[8];
  400. static BGRA8888_t gACol[4][4];
  401. gAlphas[0] = pAlphaBlock->alpha0;
  402. gAlphas[1] = pAlphaBlock->alpha1;
  403. // 8-alpha or 6-alpha block?
  404. if( gAlphas[0] > gAlphas[1] )
  405. {
  406. // 8-alpha block: derive the other 6 alphas.
  407. // 000 = alpha_0, 001 = alpha_1, others are interpolated
  408. gAlphas[2] = ( 6 * gAlphas[0] + gAlphas[1]) / 7; // bit code 010
  409. gAlphas[3] = ( 5 * gAlphas[0] + 2 * gAlphas[1]) / 7; // Bit code 011
  410. gAlphas[4] = ( 4 * gAlphas[0] + 3 * gAlphas[1]) / 7; // Bit code 100
  411. gAlphas[5] = ( 3 * gAlphas[0] + 4 * gAlphas[1]) / 7; // Bit code 101
  412. gAlphas[6] = ( 2 * gAlphas[0] + 5 * gAlphas[1]) / 7; // Bit code 110
  413. gAlphas[7] = ( gAlphas[0] + 6 * gAlphas[1]) / 7; // Bit code 111
  414. }
  415. else
  416. {
  417. // 6-alpha block: derive the other alphas.
  418. // 000 = alpha_0, 001 = alpha_1, others are interpolated
  419. gAlphas[2] = (4 * gAlphas[0] + gAlphas[1]) / 5; // Bit code 010
  420. gAlphas[3] = (3 * gAlphas[0] + 2 * gAlphas[1]) / 5; // Bit code 011
  421. gAlphas[4] = (2 * gAlphas[0] + 3 * gAlphas[1]) / 5; // Bit code 100
  422. gAlphas[5] = ( gAlphas[0] + 4 * gAlphas[1]) / 5; // Bit code 101
  423. gAlphas[6] = 0; // Bit code 110
  424. gAlphas[7] = 255; // Bit code 111
  425. }
  426. // Decode 3-bit fields into array of 16 BYTES with same value
  427. // first two rows of 4 pixels each:
  428. // pRows = (Alpha3BitRows*) & ( pAlphaBlock->stuff[0] );
  429. const uint32 mask = 0x00000007; // bits = 00 00 01 11
  430. uint32 bits = *( (uint32*) & ( pAlphaBlock->stuff[0] ));
  431. gBits[0][0] = (BYTE)( bits & mask );
  432. bits >>= 3;
  433. gBits[0][1] = (BYTE)( bits & mask );
  434. bits >>= 3;
  435. gBits[0][2] = (BYTE)( bits & mask );
  436. bits >>= 3;
  437. gBits[0][3] = (BYTE)( bits & mask );
  438. bits >>= 3;
  439. gBits[1][0] = (BYTE)( bits & mask );
  440. bits >>= 3;
  441. gBits[1][1] = (BYTE)( bits & mask );
  442. bits >>= 3;
  443. gBits[1][2] = (BYTE)( bits & mask );
  444. bits >>= 3;
  445. gBits[1][3] = (BYTE)( bits & mask );
  446. // now for last two rows:
  447. bits = *( (uint32*) & ( pAlphaBlock->stuff[3] )); // last 3 bytes
  448. gBits[2][0] = (BYTE)( bits & mask );
  449. bits >>= 3;
  450. gBits[2][1] = (BYTE)( bits & mask );
  451. bits >>= 3;
  452. gBits[2][2] = (BYTE)( bits & mask );
  453. bits >>= 3;
  454. gBits[2][3] = (BYTE)( bits & mask );
  455. bits >>= 3;
  456. gBits[3][0] = (BYTE)( bits & mask );
  457. bits >>= 3;
  458. gBits[3][1] = (BYTE)( bits & mask );
  459. bits >>= 3;
  460. gBits[3][2] = (BYTE)( bits & mask );
  461. bits >>= 3;
  462. gBits[3][3] = (BYTE)( bits & mask );
  463. // decode the codes into alpha values
  464. int row, pix;
  465. for ( row = 0; row < 4; row++ )
  466. {
  467. for ( pix=0; pix < 4; pix++ )
  468. {
  469. gACol[row][pix].a = (BYTE) gAlphas[ gBits[row][pix] ];
  470. Assert( gACol[row][pix].r == 0 );
  471. Assert( gACol[row][pix].g == 0 );
  472. Assert( gACol[row][pix].b == 0 );
  473. }
  474. }
  475. // Write out alpha values to the image bits
  476. for ( row=0; row < 4; row++, pImPos += width-4 )
  477. {
  478. for ( pix = 0; pix < 4; pix++ )
  479. {
  480. // zero the alpha bits of image pixel
  481. switch ( nChannelSelect )
  482. {
  483. case 0:
  484. pImPos->r = ( *(( BGRA8888_t *) &(gACol[row][pix])) ).a;
  485. pImPos->g = 0; // Danger...stepping on the other color channels
  486. pImPos->b = 0;
  487. pImPos->a = 0;
  488. break;
  489. case 1:
  490. pImPos->g = ( *(( BGRA8888_t *) &(gACol[row][pix])) ).a;
  491. break;
  492. case 2:
  493. pImPos->b = ( *(( BGRA8888_t *) &(gACol[row][pix])) ).a;
  494. break;
  495. default:
  496. case 3:
  497. pImPos->a = ( *(( BGRA8888_t *) &(gACol[row][pix])) ).a;
  498. break;
  499. }
  500. pImPos++;
  501. }
  502. }
  503. }
  504. template <class CDestPixel>
  505. static void ConvertFromDXT1( const uint8 *src, CDestPixel *dst, int width, int height )
  506. {
  507. Assert( sizeof( BGRA8888_t ) == 4 );
  508. Assert( sizeof( RGBA8888_t ) == 4 );
  509. Assert( sizeof( RGB888_t ) == 3 );
  510. Assert( sizeof( BGR888_t ) == 3 );
  511. Assert( sizeof( BGR565_t ) == 2 );
  512. Assert( sizeof( BGRA5551_t ) == 2 );
  513. Assert( sizeof( BGRA4444_t ) == 2 );
  514. int realWidth = 0;
  515. int realHeight = 0;
  516. CDestPixel *realDst = NULL;
  517. // Deal with the case where we have a dimension smaller than 4.
  518. if ( width < 4 || height < 4 )
  519. {
  520. realWidth = width;
  521. realHeight = height;
  522. // round up to the nearest four
  523. width = ( width + 3 ) & ~3;
  524. height = ( height + 3 ) & ~3;
  525. realDst = dst;
  526. dst = ( CDestPixel * )stackalloc( width * height * sizeof( CDestPixel ) );
  527. Assert( dst );
  528. }
  529. Assert( !( width % 4 ) );
  530. Assert( !( height % 4 ) );
  531. int xblocks, yblocks;
  532. xblocks = width >> 2;
  533. yblocks = height >> 2;
  534. CDestPixel *pDstScan = dst;
  535. uint32 *pSrcScan = ( uint32 * )src;
  536. DXTColBlock *pBlock;
  537. BGRA8888_t col_0, col_1, col_2, col_3;
  538. uint16 wrdDummy;
  539. int i, j;
  540. for ( j = 0; j < yblocks; j++ )
  541. {
  542. // 8 bytes per block
  543. pBlock = ( DXTColBlock * )( ( uint8 * )pSrcScan + j * xblocks * 8 );
  544. for ( i=0; i < xblocks; i++, pBlock++ )
  545. {
  546. GetColorBlockColorsBGRA8888( pBlock, &col_0, &col_1, &col_2, &col_3, wrdDummy );
  547. // now decode the color block into the bitmap bits
  548. // inline func:
  549. pDstScan = dst + i*4 + j*4*width;
  550. DecodeColorBlock<CDestPixel>( pDstScan, pBlock, width, &col_0, &col_1, &col_2, &col_3 );
  551. }
  552. }
  553. // Deal with the case where we have a dimension smaller than 4.
  554. if ( realDst )
  555. {
  556. int x, y;
  557. for ( y = 0; y < realHeight; y++ )
  558. {
  559. for ( x = 0; x < realWidth; x++ )
  560. {
  561. realDst[x+(y*realWidth)] = dst[x+(y*width)];
  562. }
  563. }
  564. }
  565. }
  566. template <class CDestPixel>
  567. static void ConvertFromDXT5( const uint8 *src, CDestPixel *dst, int width, int height )
  568. {
  569. int realWidth = 0;
  570. int realHeight = 0;
  571. CDestPixel *realDst = NULL;
  572. // Deal with the case where we have a dimension smaller than 4.
  573. if ( width < 4 || height < 4 )
  574. {
  575. realWidth = width;
  576. realHeight = height;
  577. // round up to the nearest four
  578. width = ( width + 3 ) & ~3;
  579. height = ( height + 3 ) & ~3;
  580. realDst = dst;
  581. dst = ( CDestPixel * )stackalloc( width * height * sizeof( CDestPixel ) );
  582. Assert( dst );
  583. }
  584. Assert( !( width % 4 ) );
  585. Assert( !( height % 4 ) );
  586. int xblocks, yblocks;
  587. xblocks = width >> 2;
  588. yblocks = height >> 2;
  589. CDestPixel *pDstScan = dst;
  590. uint32 *pSrcScan = ( uint32 * )src;
  591. DXTColBlock *pBlock;
  592. DXTAlphaBlock3BitLinear *pAlphaBlock;
  593. BGRA8888_t col_0, col_1, col_2, col_3;
  594. uint16 wrd;
  595. int i,j;
  596. for ( j=0; j < yblocks; j++ )
  597. {
  598. // 8 bytes per block
  599. // 1 block for alpha, 1 block for color
  600. pBlock = (DXTColBlock*) ( (uint8 *)pSrcScan + j * xblocks * 16 );
  601. for ( i=0; i < xblocks; i++, pBlock ++ )
  602. {
  603. // inline
  604. // Get alpha block
  605. pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
  606. // inline func:
  607. // Get color block & colors
  608. pBlock++;
  609. GetColorBlockColorsBGRA8888( pBlock, &col_0, &col_1, &col_2, &col_3, wrd );
  610. pDstScan = dst + i*4 + j*4*width;
  611. // Decode the color block into the bitmap bits
  612. // inline func:
  613. DecodeColorBlock<CDestPixel>( pDstScan, pBlock, width, &col_0, &col_1, &col_2, &col_3 );
  614. // Overwrite the previous alpha bits with the alpha block
  615. // info
  616. DecodeAlpha3BitLinear( pDstScan, pAlphaBlock, width );
  617. }
  618. }
  619. // Deal with the case where we have a dimension smaller than 4.
  620. if ( realDst )
  621. {
  622. int x, y;
  623. for( y = 0; y < realHeight; y++ )
  624. {
  625. for( x = 0; x < realWidth; x++ )
  626. {
  627. realDst[x+(y*realWidth)] = dst[x+(y*width)];
  628. }
  629. }
  630. }
  631. }
  632. template <class CDestPixel>
  633. static void ConvertFromDXT5IgnoreAlpha( const uint8 *src, CDestPixel *dst, int width, int height )
  634. {
  635. int realWidth = 0;
  636. int realHeight = 0;
  637. CDestPixel *realDst = NULL;
  638. // Deal with the case where we have a dimension smaller than 4.
  639. if ( width < 4 || height < 4 )
  640. {
  641. realWidth = width;
  642. realHeight = height;
  643. // round up to the nearest four
  644. width = ( width + 3 ) & ~3;
  645. height = ( height + 3 ) & ~3;
  646. realDst = dst;
  647. dst = ( CDestPixel * )stackalloc( width * height * sizeof( CDestPixel ) );
  648. Assert( dst );
  649. }
  650. Assert( !( width % 4 ) );
  651. Assert( !( height % 4 ) );
  652. int xblocks, yblocks;
  653. xblocks = width >> 2;
  654. yblocks = height >> 2;
  655. CDestPixel *pDstScan = dst;
  656. uint32 *pSrcScan = ( uint32 * )src;
  657. DXTColBlock *pBlock;
  658. BGRA8888_t col_0, col_1, col_2, col_3;
  659. uint16 wrd;
  660. int i,j;
  661. for ( j=0; j < yblocks; j++ )
  662. {
  663. // 8 bytes per block
  664. // 1 block for alpha, 1 block for color
  665. pBlock = (DXTColBlock*) ( (uint8 *)pSrcScan + j * xblocks * 16 );
  666. for( i=0; i < xblocks; i++, pBlock ++ )
  667. {
  668. // inline func:
  669. // Get color block & colors
  670. pBlock++;
  671. GetColorBlockColorsBGRA8888( pBlock, &col_0, &col_1, &col_2, &col_3, wrd );
  672. pDstScan = dst + i*4 + j*4*width;
  673. // Decode the color block into the bitmap bits
  674. // inline func:
  675. DecodeColorBlock<CDestPixel>( pDstScan, pBlock, width, &col_0, &col_1, &col_2, &col_3 );
  676. }
  677. }
  678. // Deal with the case where we have a dimension smaller than 4.
  679. if( realDst )
  680. {
  681. int x, y;
  682. for( y = 0; y < realHeight; y++ )
  683. {
  684. for( x = 0; x < realWidth; x++ )
  685. {
  686. realDst[x+(y*realWidth)] = dst[x+(y*width)];
  687. }
  688. }
  689. }
  690. }
  691. template <class CDestPixel>
  692. static void ConvertFromATIxN( const uint8 *src, CDestPixel *dst, int width, int height, bool bATI2N )
  693. {
  694. int realWidth = 0;
  695. int realHeight = 0;
  696. CDestPixel *realDst = NULL;
  697. // Deal with the case where we have a dimension smaller than 4.
  698. if ( width < 4 || height < 4 )
  699. {
  700. realWidth = width;
  701. realHeight = height;
  702. // round up to the nearest four
  703. width = ( width + 3 ) & ~3;
  704. height = ( height + 3 ) & ~3;
  705. realDst = dst;
  706. dst = ( CDestPixel * )stackalloc( width * height * sizeof( CDestPixel ) );
  707. Assert( dst );
  708. }
  709. Assert( !( width % 4 ) );
  710. Assert( !( height % 4 ) );
  711. int xblocks, yblocks;
  712. xblocks = width >> 2;
  713. yblocks = height >> 2;
  714. CDestPixel *pDstScan = dst;
  715. uint32 *pSrcScan = ( uint32 * )src;
  716. DXTAlphaBlock3BitLinear *pBlock;
  717. int nBytesPerBlock = bATI2N ? 16 : 8;
  718. int i,j;
  719. for ( j=0; j < yblocks; j++ )
  720. {
  721. // 8 bytes per block
  722. // 1 block for x, 1 block for y
  723. pBlock = (DXTAlphaBlock3BitLinear*) ( (uint8 *)pSrcScan + j * xblocks * nBytesPerBlock );
  724. for ( i=0; i < xblocks; i++, pBlock++ )
  725. {
  726. pDstScan = dst + i*4 + j*4*width;
  727. DecodeAlpha3BitLinear( pDstScan, pBlock, width, 0 );
  728. if ( bATI2N )
  729. {
  730. pBlock++;
  731. DecodeAlpha3BitLinear( pDstScan, pBlock, width, 1 );
  732. }
  733. }
  734. }
  735. // Deal with the case where we have a dimension smaller than 4.
  736. if ( realDst )
  737. {
  738. int x, y;
  739. for( y = 0; y < realHeight; y++ )
  740. {
  741. for( x = 0; x < realWidth; x++ )
  742. {
  743. realDst[x+(y*realWidth)] = dst[x+(y*width)];
  744. }
  745. }
  746. }
  747. }
  748. static uint32 GetDXTCEncodeType( ImageFormat imageFormat )
  749. {
  750. switch ( imageFormat )
  751. {
  752. case IMAGE_FORMAT_DXT1:
  753. return S3TC_ENCODE_RGB_FULL;
  754. case IMAGE_FORMAT_DXT1_ONEBITALPHA:
  755. return S3TC_ENCODE_RGB_FULL | S3TC_ENCODE_RGB_ALPHA_COMPARE;
  756. case IMAGE_FORMAT_DXT3:
  757. return S3TC_ENCODE_RGB_FULL | S3TC_ENCODE_ALPHA_EXPLICIT;
  758. case IMAGE_FORMAT_DXT5:
  759. return S3TC_ENCODE_RGB_FULL | S3TC_ENCODE_ALPHA_INTERPOLATED;
  760. default:
  761. return 0;
  762. }
  763. }
  764. // Use AMD compressor to convert RGBA input to ATI1N, ATI2N or DXT5_GA format
  765. bool ConvertToATIxN( const uint8 *src, ImageFormat srcImageFormat,
  766. uint8 *dst, ImageFormat dstImageFormat,
  767. int width, int height, int srcStride, int dstStride, bool bDXT5GA = false )
  768. {
  769. Assert( !"ATIxN is no longer supported." );
  770. return false;
  771. }
  772. bool ConvertToDXT( const uint8 *src, ImageFormat srcImageFormat,
  773. uint8 *dst, ImageFormat dstImageFormat,
  774. int width, int height, int srcStride, int dstStride )
  775. {
  776. #if !defined( _X360 ) && !defined( POSIX )
  777. // from rgb(a) to dxtN
  778. if( srcStride != 0 || dstStride != 0 )
  779. return false;
  780. DDSURFACEDESC descIn;
  781. DDSURFACEDESC descOut;
  782. memset( &descIn, 0, sizeof(descIn) );
  783. memset( &descOut, 0, sizeof(descOut) );
  784. float weight[3] = {0.3086f, 0.6094f, 0.0820f};
  785. uint32 dwEncodeType = GetDXTCEncodeType( dstImageFormat );
  786. // Setup descIn
  787. descIn.dwSize = sizeof(descIn);
  788. descIn.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE |
  789. /*DDSD_PITCH | */ DDSD_PIXELFORMAT;
  790. descIn.dwWidth = width;
  791. descIn.dwHeight = height;
  792. descIn.lPitch = width * ImageLoader::SizeInBytes( srcImageFormat );
  793. descIn.lpSurface = ( LPVOID *) src;
  794. descIn.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
  795. switch ( srcImageFormat )
  796. {
  797. case IMAGE_FORMAT_RGBA8888:
  798. descIn.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
  799. descIn.ddpfPixelFormat.dwRGBBitCount = 32;
  800. descIn.ddpfPixelFormat.dwRBitMask = 0x0000ff;
  801. descIn.ddpfPixelFormat.dwGBitMask = 0x00ff00;
  802. descIn.ddpfPixelFormat.dwBBitMask = 0xff0000;
  803. // must set this anyway or S3TC will lock up!!!
  804. descIn.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
  805. break;
  806. case IMAGE_FORMAT_BGRA8888:
  807. descIn.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
  808. descIn.ddpfPixelFormat.dwRGBBitCount = 32;
  809. descIn.ddpfPixelFormat.dwRBitMask = 0xFF0000;
  810. descIn.ddpfPixelFormat.dwGBitMask = 0x00ff00;
  811. descIn.ddpfPixelFormat.dwBBitMask = 0x0000FF;
  812. // must set this anyway or S3TC will lock up!!!
  813. descIn.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
  814. break;
  815. case IMAGE_FORMAT_BGRX8888:
  816. descIn.ddpfPixelFormat.dwFlags = DDPF_RGB;
  817. descIn.ddpfPixelFormat.dwRGBBitCount = 32;
  818. descIn.ddpfPixelFormat.dwRBitMask = 0xFF0000;
  819. descIn.ddpfPixelFormat.dwGBitMask = 0x00ff00;
  820. descIn.ddpfPixelFormat.dwBBitMask = 0x0000FF;
  821. // must set this anyway or S3TC will lock up!!!
  822. descIn.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
  823. break;
  824. case IMAGE_FORMAT_RGB888:
  825. descIn.ddpfPixelFormat.dwFlags = DDPF_RGB;
  826. descIn.ddpfPixelFormat.dwRGBBitCount = 24;
  827. descIn.ddpfPixelFormat.dwRBitMask = 0x0000ff;
  828. descIn.ddpfPixelFormat.dwGBitMask = 0x00ff00;
  829. descIn.ddpfPixelFormat.dwBBitMask = 0xff0000;
  830. descIn.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
  831. break;
  832. default:
  833. return false;
  834. }
  835. // Setup descOut
  836. descOut.dwSize = sizeof( descOut );
  837. // Encode the texture
  838. S3TCencode( &descIn, NULL, &descOut, dst, dwEncodeType, weight );
  839. return true;
  840. #else
  841. Assert( 0 );
  842. return false;
  843. #endif
  844. }
  845. bool ConvertToDXTRuntime( const uint8 *src, ImageFormat srcImageFormat,
  846. uint8 *dst, ImageFormat dstImageFormat,
  847. int width, int height )
  848. {
  849. // from rgba to dxtN using stb_dxt.h (source format must always be RGBA8888, dest format must be DXT1_RUNTIME or DXT5_RUNTIME
  850. Assert( ( srcImageFormat == IMAGE_FORMAT_RGBA8888 || srcImageFormat == IMAGE_FORMAT_BGRA8888 ) && ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME || dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME ) );
  851. const uint64 *sourcePixels = reinterpret_cast<const uint64 *>(src);
  852. uint32 *dest32 = reinterpret_cast<uint32 *>(dst);
  853. int width64 = width >> 1;
  854. if ( srcImageFormat == IMAGE_FORMAT_BGRA8888 )
  855. {
  856. for ( int y = 0; y < height; y += 4 )
  857. {
  858. if ( width == 1 )
  859. {
  860. uint32 pixelBlock[16];
  861. const uint32 *sourcePixels32 = reinterpret_cast<const uint32 *>(src);
  862. pixelBlock[0] = sourcePixels32[0];
  863. for ( int i = 1; i < 16; i++ )
  864. {
  865. pixelBlock[i] = 0;
  866. }
  867. // compress the pixelBlock into dest32
  868. stb_compress_dxt_block( reinterpret_cast<uint8 *>(dest32), reinterpret_cast<uint8 *>(pixelBlock), (dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME) ? 1 : 0, STB_DXT_NORMAL );
  869. dest32 += ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ) ? 2 : 4;
  870. }
  871. else if ( width == 2 )
  872. {
  873. // copy a 4x4 block of pixels from the source image into 'pixelBlock'
  874. uint64 pixelBlock[8];
  875. pixelBlock[0] = sourcePixels[0];
  876. pixelBlock[2] = sourcePixels[width64];
  877. pixelBlock[1] = pixelBlock[3] = pixelBlock[4] = pixelBlock[5] = pixelBlock[6] = pixelBlock[7] = sourcePixels[0];
  878. // compress the pixelBlock into dest32
  879. stb_compress_dxt_block( reinterpret_cast<uint8 *>(dest32), reinterpret_cast<uint8 *>(pixelBlock), (dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME) ? 1 : 0, STB_DXT_NORMAL );
  880. dest32 += ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ) ? 2 : 4;
  881. }
  882. else
  883. {
  884. for ( int x = 0; x < width64; x += 2 )
  885. {
  886. // copy a 4x4 block of pixels from the source image into 'pixelBlock'
  887. uint64 pixelBlock[8];
  888. pixelBlock[0] = sourcePixels[x];
  889. pixelBlock[1] = sourcePixels[x + 1];
  890. pixelBlock[2] = sourcePixels[x + width64];
  891. pixelBlock[3] = sourcePixels[x + width64 + 1];
  892. pixelBlock[4] = sourcePixels[x + (width64 * 2)];
  893. pixelBlock[5] = sourcePixels[x + (width64 * 2) + 1];
  894. pixelBlock[6] = sourcePixels[x + (width64 * 3)];
  895. pixelBlock[7] = sourcePixels[x + (width64 * 3) + 1];
  896. // compress the pixelBlock into dest32
  897. stb_compress_dxt_block( reinterpret_cast<uint8 *>(dest32), reinterpret_cast<uint8 *>(pixelBlock), (dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME) ? 1 : 0, STB_DXT_NORMAL );
  898. dest32 += ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ) ? 2 : 4;
  899. }
  900. }
  901. sourcePixels += (width64 << 2);
  902. }
  903. }
  904. else if ( srcImageFormat == IMAGE_FORMAT_RGBA8888 )
  905. {
  906. for ( int y = 0; y < height; y += 4 )
  907. {
  908. if ( width == 1 )
  909. {
  910. uint32 pixelBlock[16];
  911. const uint32 *sourcePixels32 = reinterpret_cast<const uint32 *>(src);
  912. pixelBlock[0] = ( sourcePixels32[0] & 0x00FF00FF ) || ( ( sourcePixels32[0] & 0xFF000000 ) >> 16 ) || ( ( sourcePixels32[0] & 0x0000FF00 ) << 16 );
  913. for ( int i = 1; i < 16; i++ )
  914. {
  915. pixelBlock[i] = 0;
  916. }
  917. // compress the pixelBlock into dest32
  918. stb_compress_dxt_block( reinterpret_cast<uint8 *>(dest32), reinterpret_cast<uint8 *>(pixelBlock), (dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME) ? 1 : 0, STB_DXT_NORMAL );
  919. dest32 += ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ) ? 2 : 4;
  920. }
  921. else if ( width == 2 )
  922. {
  923. // copy a 4x4 block of pixels from the source image into 'pixelBlock'
  924. uint64 pixelBlock[8];
  925. pixelBlock[0] = ( sourcePixels[0] & 0x00FF00FF00FF00FFLL ) | ( ( sourcePixels[0] & 0xFF000000FF000000LL ) >> 16 ) | ( ( sourcePixels[0] & 0x0000FF000000FF00LL ) << 16 );
  926. pixelBlock[2] = ( sourcePixels[width64] & 0x00FF00FF00FF00FFLL ) | ( ( sourcePixels[width64] & 0xFF000000FF000000LL ) >> 16 ) | ( ( sourcePixels[width64] & 0x0000FF000000FF00LL ) << 16 );
  927. pixelBlock[1] = pixelBlock[3] = pixelBlock[4] = pixelBlock[5] = pixelBlock[6] = pixelBlock[7] = pixelBlock[0];
  928. // compress the pixelBlock into dest32
  929. stb_compress_dxt_block( reinterpret_cast<uint8 *>(dest32), reinterpret_cast<uint8 *>(pixelBlock), (dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME) ? 1 : 0, STB_DXT_NORMAL );
  930. dest32 += ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ) ? 2 : 4;
  931. }
  932. else
  933. {
  934. for ( int x = 0; x < width64; x += 2 )
  935. {
  936. // copy a 4x4 block of pixels from the source image into 'pixelBlock'
  937. uint64 pixelBlock[8];
  938. pixelBlock[0] = ( sourcePixels[x] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x] & 0x000000FF000000FFLL ) << 16 );
  939. pixelBlock[1] = ( sourcePixels[x + 1] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x + 1] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x + 1] & 0x000000FF000000FFLL ) << 16 );
  940. pixelBlock[2] = ( sourcePixels[x + width64] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x + width64] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x + width64] & 0x000000FF000000FFLL ) << 16 );
  941. pixelBlock[3] = ( sourcePixels[x + width64 + 1] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x + width64 + 1] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x + width64 + 1] & 0x000000FF000000FFLL ) << 16 );
  942. pixelBlock[4] = ( sourcePixels[x + (width64 * 2)] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x + (width64 * 2)] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x + (width64 * 2)] & 0x000000FF000000FFLL ) << 16 );
  943. pixelBlock[5] = ( sourcePixels[x + (width64 * 2) + 1] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x + (width64 * 2) + 1] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x + (width64 * 2) + 1] & 0x000000FF000000FFLL ) << 16 );
  944. pixelBlock[6] = ( sourcePixels[x + (width64 * 3)] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x + (width64 * 3)] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x + (width64 * 3)] & 0x000000FF000000FFLL ) << 16 );
  945. pixelBlock[7] = ( sourcePixels[x + (width64 * 3) + 1] & 0xFF00FF00FF00FF00LL ) | ( ( sourcePixels[x + (width64 * 3) + 1] & 0x00FF000000FF0000LL ) >> 16 ) | ( ( sourcePixels[x + (width64 * 3) + 1] & 0x000000FF000000FFLL ) << 16 );
  946. // compress the pixelBlock into dest32
  947. stb_compress_dxt_block( reinterpret_cast<uint8 *>(dest32), reinterpret_cast<uint8 *>(pixelBlock), (dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME) ? 1 : 0, STB_DXT_NORMAL );
  948. dest32 += ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ) ? 2 : 4;
  949. }
  950. }
  951. sourcePixels += (width64 << 2);
  952. }
  953. }
  954. return true;
  955. }
  956. // HDRFIXME: This assumes that the 16-bit integer values are 4.12 fixed-point.
  957. void ConvertImageFormat_RGBA16161616_To_RGB323232F( unsigned short *pSrcImage, float *pDstImage, int width, int height )
  958. {
  959. int srcSize = width * height * 4;
  960. unsigned short *pSrcEnd = pSrcImage + srcSize;
  961. unsigned short *pSrcScan = pSrcImage;
  962. float *pDstScan = pDstImage;
  963. for ( ; pSrcScan < pSrcEnd; pSrcScan += 4, pDstScan += 3 )
  964. {
  965. pDstScan[0] = ( ( float )pSrcScan[0] ) * ( 1.0f / ( ( float )( 1 << 12 ) ) );
  966. pDstScan[1] = ( ( float )pSrcScan[1] ) * ( 1.0f / ( ( float )( 1 << 12 ) ) );
  967. pDstScan[2] = ( ( float )pSrcScan[2] ) * ( 1.0f / ( ( float )( 1 << 12 ) ) );
  968. }
  969. }
  970. // HDRFIXME: This assumes that the 16-bit integer values are 4.12 fixed-point.
  971. void ConvertImageFormat_RGB323232F_To_RGBA16161616( float *pSrcImage, unsigned short *pDstImage, int width, int height )
  972. {
  973. int srcSize = width * height * 3;
  974. float *pSrcEnd = pSrcImage + srcSize;
  975. float *pSrcScan = pSrcImage;
  976. unsigned short *pDstScan = pDstImage;
  977. for ( ; pSrcScan < pSrcEnd; pSrcScan += 3, pDstScan += 4 )
  978. {
  979. pDstScan[0] = ( unsigned short )MIN( 65535.0f, ( pSrcScan[0] * ( ( ( float )( 1 << 12 ) ) ) ) );
  980. pDstScan[1] = ( unsigned short )MIN( 65535.0f, ( pSrcScan[1] * ( ( ( float )( 1 << 12 ) ) ) ) );
  981. pDstScan[2] = ( unsigned short )MIN( 65535.0f, ( pSrcScan[2] * ( ( ( float )( 1 << 12 ) ) ) ) );
  982. pDstScan[3] = 65535;
  983. }
  984. }
  985. void ConvertImageFormat_RGBA16161616F_To_RGB323232F( float16 *pSrcImage, float *pDstImage, int width, int height )
  986. {
  987. int srcSize = width * height * 4;
  988. float16 *pSrcEnd = pSrcImage + srcSize;
  989. float16 *pSrcScan = pSrcImage;
  990. float *pDstScan = pDstImage;
  991. for( ; pSrcScan < pSrcEnd; pSrcScan += 4, pDstScan += 3 )
  992. {
  993. pDstScan[0] = pSrcScan[0].GetFloat();
  994. pDstScan[1] = pSrcScan[1].GetFloat();
  995. pDstScan[2] = pSrcScan[2].GetFloat();
  996. }
  997. }
  998. void ConvertImageFormat_RGBA16161616F_To_RGBA323232F( float16 *pSrcImage, float *pDstImage, int width, int height , size_t src_stride)
  999. {
  1000. size_t s_stride=src_stride/2;
  1001. for(int y=0; y<height; y++)
  1002. {
  1003. float16 const *pSrcScan=pSrcImage;
  1004. float *pDstScan = pDstImage;
  1005. for(int x=0; x<width; x++)
  1006. {
  1007. pDstScan[0] = pSrcScan[0].GetFloat();
  1008. pDstScan[1] = pSrcScan[1].GetFloat();
  1009. pDstScan[2] = pSrcScan[2].GetFloat();
  1010. pDstScan[3] = pSrcScan[3].GetFloat();
  1011. pDstScan+=4;
  1012. pSrcScan+=4;
  1013. }
  1014. pSrcImage += s_stride;
  1015. pDstImage+=4*width;
  1016. }
  1017. }
  1018. void ConvertImageFormat_RGB323232F_To_RGBA16161616F( float *pSrcImage, float16 *pDstImage, int width, int height )
  1019. {
  1020. int srcSize = width * height * 3;
  1021. float *pSrcEnd = pSrcImage + srcSize;
  1022. float *pSrcScan = pSrcImage;
  1023. float16 *pDstScan = pDstImage;
  1024. for( ; pSrcScan < pSrcEnd; pSrcScan += 3, pDstScan += 4 )
  1025. {
  1026. pDstScan[0].SetFloat( pSrcScan[0] );
  1027. pDstScan[1].SetFloat( pSrcScan[1] );
  1028. pDstScan[2].SetFloat( pSrcScan[2] );
  1029. }
  1030. }
  1031. void ConvertImageFormat_RGB323232F_To_RGBA8888( float *pSrcImage, uint8 *dst, int width, int height )
  1032. {
  1033. FloatBitMap_t flbm;
  1034. flbm.Init( width, height );
  1035. // Set the pixels
  1036. for ( int y = 0; y < height; ++ y )
  1037. {
  1038. for ( int x = 0; x < width; ++ x )
  1039. {
  1040. float *pf = &pSrcImage[ 3 * ( x + width * y ) ];
  1041. PixRGBAF fpix;
  1042. fpix.Red = pf[0];
  1043. fpix.Green = pf[1];
  1044. fpix.Blue = pf[2];
  1045. fpix.Alpha = 0.f;
  1046. flbm.WritePixelRGBAF( x, y, 0, fpix );
  1047. }
  1048. }
  1049. // memcpy( flbm.RGBAData, pSrcImage, width * height * 4 );
  1050. flbm.CompressTo8Bits( 8.0 );
  1051. // Now, get the pixels
  1052. for ( int y = 0; y < height; ++ y )
  1053. {
  1054. for ( int x = 0; x < width; ++ x )
  1055. {
  1056. PixRGBAF fpix = flbm.PixelRGBAF( x, y, 0 );
  1057. PixRGBA8 pix8 = PixRGBAF_to_8( fpix );
  1058. uint8 *pch = &dst[ 4 * ( x + width * y ) ];
  1059. pch[0] = pix8.Red;
  1060. pch[1] = pix8.Green;
  1061. pch[2] = pix8.Blue;
  1062. pch[3] = pix8.Alpha;
  1063. }
  1064. }
  1065. }
  1066. void ConvertImageFormat_RGB323232F_To_BGRA8888( float *pSrcImage, uint8 *dst, int width, int height )
  1067. {
  1068. FloatBitMap_t flbm;
  1069. flbm.Init( width, height );
  1070. // Set the pixels
  1071. for ( int y = 0; y < height; ++ y )
  1072. {
  1073. for ( int x = 0; x < width; ++ x )
  1074. {
  1075. float *pf = &pSrcImage[ 3 * ( x + width * y ) ];
  1076. PixRGBAF fpix;
  1077. fpix.Red = pf[0];
  1078. fpix.Green = pf[1];
  1079. fpix.Blue = pf[2];
  1080. fpix.Alpha = 0.f;
  1081. flbm.WritePixelRGBAF( x, y, 0, fpix );
  1082. }
  1083. }
  1084. // memcpy( flbm.RGBAData, pSrcImage, width * height * 4 );
  1085. flbm.CompressTo8Bits( 8.0 );
  1086. // Now, get the pixels
  1087. for ( int y = 0; y < height; ++ y )
  1088. {
  1089. for ( int x = 0; x < width; ++ x )
  1090. {
  1091. PixRGBAF fpix = flbm.PixelRGBAF( x, y, 0 );
  1092. PixRGBA8 pix8 = PixRGBAF_to_8( fpix );
  1093. uint8 *pch = &dst[ 4 * ( x + width * y ) ];
  1094. pch[0] = pix8.Blue;
  1095. pch[1] = pix8.Green;
  1096. pch[2] = pix8.Red;
  1097. pch[3] = pix8.Alpha;
  1098. }
  1099. }
  1100. }
  1101. // HDRFIXME: This assumes that the 16-bit integer values are 4.12 fixed-point.
  1102. void ConvertImageFormat_RGBA16161616_To_RGBA16161616F( unsigned short *pSrcImage, float *pDstImage, int width, int height )
  1103. {
  1104. int srcSize = width * height * 4;
  1105. unsigned short *pSrcEnd = pSrcImage + srcSize;
  1106. unsigned short *pSrcScan = pSrcImage;
  1107. float16 *pDstScan = ( float16 * )pDstImage;
  1108. for( ; pSrcScan < pSrcEnd; pSrcScan += 4, pDstScan += 4 )
  1109. {
  1110. pDstScan[0].SetFloat( pSrcScan[0] * ( 1.0f / ( float )( 1 << 16 ) ) );
  1111. pDstScan[1].SetFloat( pSrcScan[1] * ( 1.0f / ( float )( 1 << 16 ) ) );
  1112. pDstScan[2].SetFloat( pSrcScan[2] * ( 1.0f / ( float )( 1 << 16 ) ) );
  1113. pDstScan[3].SetFloat( pSrcScan[3] * ( 1.0f / ( float )( 1 << 16 ) ) );
  1114. }
  1115. }
  1116. void ConvertImageFormat_RGBA16161616F_To_RGBA16161616( float16 *pSrcImage, unsigned short *pDstImage, int width, int height )
  1117. {
  1118. int srcSize = width * height * 4;
  1119. float16 *pSrcEnd = pSrcImage + srcSize;
  1120. float16 *pSrcScan = pSrcImage;
  1121. unsigned short *pDstScan = pDstImage;
  1122. for( ; pSrcScan < pSrcEnd; pSrcScan += 4, pDstScan += 4 )
  1123. {
  1124. int i;
  1125. for( i = 0; i < 4; i++ )
  1126. {
  1127. float val;
  1128. val = pSrcScan[i].GetFloat();
  1129. val *= ( float )( 1 << 12 );
  1130. val = MAX( val, 0 );
  1131. val = MIN( val, 65535.0f );
  1132. pDstScan[i] = ( unsigned short )val;
  1133. }
  1134. }
  1135. }
  1136. bool ConvertImageFormat( const uint8 *src, ImageFormat srcImageFormat,
  1137. uint8 *dst, ImageFormat dstImageFormat,
  1138. int width, int height, int srcStride, int dstStride )
  1139. {
  1140. // HDRFIXME: WE NEED A BIGGER INTERMEDIATE FORMAT!!!!!
  1141. if ( srcImageFormat == IMAGE_FORMAT_RGBA16161616 )
  1142. {
  1143. if ( dstImageFormat == IMAGE_FORMAT_RGB323232F )
  1144. {
  1145. Assert( srcStride == 0 && dstStride == 0 );
  1146. ConvertImageFormat_RGBA16161616_To_RGB323232F( ( unsigned short * )src, ( float * )dst, width, height );
  1147. return true;
  1148. }
  1149. if ( dstImageFormat == IMAGE_FORMAT_RGBA16161616F )
  1150. {
  1151. Assert( srcStride == 0 && dstStride == 0 );
  1152. ConvertImageFormat_RGBA16161616_To_RGBA16161616F( ( unsigned short * )src, ( float * )dst, width, height );
  1153. return true;
  1154. }
  1155. }
  1156. else if ( srcImageFormat == IMAGE_FORMAT_RGBA16161616F )
  1157. {
  1158. if ( dstImageFormat == IMAGE_FORMAT_RGB323232F )
  1159. {
  1160. Assert( srcStride == 0 && dstStride == 0 );
  1161. ConvertImageFormat_RGBA16161616F_To_RGB323232F( ( float16 * )src, ( float * )dst, width, height );
  1162. return true;
  1163. }
  1164. if ( dstImageFormat == IMAGE_FORMAT_RGBA32323232F )
  1165. {
  1166. Assert( dstStride == 0 );
  1167. ConvertImageFormat_RGBA16161616F_To_RGBA323232F( ( float16 * )src, ( float * )dst, width, height, srcStride );
  1168. return true;
  1169. }
  1170. if ( dstImageFormat == IMAGE_FORMAT_RGBA16161616 )
  1171. {
  1172. Assert( srcStride == 0 && dstStride == 0 );
  1173. ConvertImageFormat_RGBA16161616F_To_RGBA16161616( ( float16 * )src, ( unsigned short * )dst, width, height );
  1174. return true;
  1175. }
  1176. }
  1177. else if ( srcImageFormat == IMAGE_FORMAT_RGB323232F )
  1178. {
  1179. if ( dstImageFormat == IMAGE_FORMAT_RGBA16161616 )
  1180. {
  1181. Assert( srcStride == 0 && dstStride == 0 );
  1182. ConvertImageFormat_RGB323232F_To_RGBA16161616( ( float * )src, ( unsigned short * )dst, width, height );
  1183. return true;
  1184. }
  1185. if ( dstImageFormat == IMAGE_FORMAT_RGBA16161616F )
  1186. {
  1187. Assert( srcStride == 0 && dstStride == 0 );
  1188. ConvertImageFormat_RGB323232F_To_RGBA16161616F( ( float * )src, ( float16 * )dst, width, height );
  1189. return true;
  1190. }
  1191. if ( dstImageFormat == IMAGE_FORMAT_RGBA8888 )
  1192. {
  1193. Assert( srcStride == 0 );
  1194. ConvertImageFormat_RGB323232F_To_RGBA8888( ( float * )src, dst, width, height );
  1195. return true;
  1196. }
  1197. if ( dstImageFormat == IMAGE_FORMAT_BGRA8888 )
  1198. {
  1199. Assert( srcStride == 0 );
  1200. ConvertImageFormat_RGB323232F_To_BGRA8888( ( float * )src, dst, width, height );
  1201. return true;
  1202. }
  1203. }
  1204. // Fast path for just copying a compressed texture
  1205. if ( ( ( dstImageFormat == IMAGE_FORMAT_DXT1 || dstImageFormat == IMAGE_FORMAT_LINEAR_DXT1 || dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ||
  1206. dstImageFormat == IMAGE_FORMAT_DXT3 || dstImageFormat == IMAGE_FORMAT_LINEAR_DXT3 ||
  1207. dstImageFormat == IMAGE_FORMAT_DXT5 || dstImageFormat == IMAGE_FORMAT_LINEAR_DXT5 || dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME ||
  1208. dstImageFormat == IMAGE_FORMAT_ATI1N ||
  1209. dstImageFormat == IMAGE_FORMAT_ATI2N ) && ( srcImageFormat == dstImageFormat ) ) ||
  1210. ( dstImageFormat == IMAGE_FORMAT_DXT5 && srcImageFormat == IMAGE_FORMAT_DXT5_RUNTIME ) ||
  1211. ( dstImageFormat == IMAGE_FORMAT_DXT1 && srcImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ) ||
  1212. ( dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME && srcImageFormat == IMAGE_FORMAT_DXT5 ) ||
  1213. ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME && srcImageFormat == IMAGE_FORMAT_DXT1 ) )
  1214. {
  1215. // Fast path for compressed textures . . stride doesn't make as much sense.
  1216. // Assert( srcStride == 0 && dstStride == 0 );
  1217. int memRequired;
  1218. memRequired = GetMemRequired( width, height, 1, srcImageFormat, false );
  1219. memcpy( dst, src, memRequired );
  1220. return true;
  1221. }
  1222. else if ( ( srcImageFormat == IMAGE_FORMAT_RGBA8888 ||
  1223. srcImageFormat == IMAGE_FORMAT_RGB888 || // RGBA source
  1224. srcImageFormat == IMAGE_FORMAT_BGRA8888 || //
  1225. srcImageFormat == IMAGE_FORMAT_BGRX8888 ) && // and
  1226. ( dstImageFormat == IMAGE_FORMAT_DXT1 || //
  1227. dstImageFormat == IMAGE_FORMAT_DXT3 || // DXT compressed dest
  1228. dstImageFormat == IMAGE_FORMAT_DXT5 ) )
  1229. {
  1230. return ConvertToDXT( src, srcImageFormat, dst, dstImageFormat, width, height, 0, 0 );
  1231. }
  1232. else if ( ( srcImageFormat == IMAGE_FORMAT_RGBA8888) &&
  1233. ( dstImageFormat == IMAGE_FORMAT_DXT1_RUNTIME ||
  1234. dstImageFormat == IMAGE_FORMAT_DXT5_RUNTIME ) )
  1235. {
  1236. return ConvertToDXTRuntime( src, srcImageFormat, dst, dstImageFormat, width, height );
  1237. }
  1238. else if ( ( srcImageFormat == IMAGE_FORMAT_ARGB8888 ) && // RGBA source and
  1239. ( dstImageFormat == IMAGE_FORMAT_ATI1N || dstImageFormat == IMAGE_FORMAT_ATI2N ) ) // ATI compressed dest
  1240. {
  1241. return ConvertToATIxN( src, srcImageFormat, dst, dstImageFormat, width, height, srcStride, dstStride );
  1242. }
  1243. else if ( ( dstImageFormat == IMAGE_FORMAT_RGBA8888 ||
  1244. dstImageFormat == IMAGE_FORMAT_BGRX8888 ||
  1245. dstImageFormat == IMAGE_FORMAT_BGRA8888 ||
  1246. dstImageFormat == IMAGE_FORMAT_BGRA4444 ||
  1247. dstImageFormat == IMAGE_FORMAT_BGRA5551 ||
  1248. dstImageFormat == IMAGE_FORMAT_BGRX5551 ||
  1249. dstImageFormat == IMAGE_FORMAT_BGR565 ||
  1250. dstImageFormat == IMAGE_FORMAT_BGR888 ||
  1251. dstImageFormat == IMAGE_FORMAT_RGB888 ) &&
  1252. ( srcImageFormat == IMAGE_FORMAT_DXT1 ||
  1253. srcImageFormat == IMAGE_FORMAT_DXT3 ||
  1254. srcImageFormat == IMAGE_FORMAT_DXT5 ||
  1255. srcImageFormat == IMAGE_FORMAT_ATI1N ||
  1256. srcImageFormat == IMAGE_FORMAT_ATI2N ) )
  1257. {
  1258. // from dxtN to rgb(a)
  1259. if ( srcStride != 0 || dstStride != 0 )
  1260. {
  1261. return false;
  1262. }
  1263. if ( srcImageFormat == IMAGE_FORMAT_DXT1 )
  1264. {
  1265. if ( dstImageFormat == IMAGE_FORMAT_RGBA8888 )
  1266. {
  1267. ConvertFromDXT1( src, ( RGBA8888_t * )dst, width, height );
  1268. return true;
  1269. }
  1270. if ( dstImageFormat == IMAGE_FORMAT_BGRA8888 ||
  1271. dstImageFormat == IMAGE_FORMAT_BGRX8888 )
  1272. {
  1273. ConvertFromDXT1( src, ( BGRA8888_t * )dst, width, height );
  1274. return true;
  1275. }
  1276. if ( dstImageFormat == IMAGE_FORMAT_RGB888 )
  1277. {
  1278. ConvertFromDXT1( src, ( RGB888_t * )dst, width, height );
  1279. return true;
  1280. }
  1281. if ( dstImageFormat == IMAGE_FORMAT_BGR888 )
  1282. {
  1283. ConvertFromDXT1( src, ( BGR888_t * )dst, width, height );
  1284. return true;
  1285. }
  1286. if ( dstImageFormat == IMAGE_FORMAT_BGR565 )
  1287. {
  1288. ConvertFromDXT1( src, ( BGR565_t * )dst, width, height );
  1289. return true;
  1290. }
  1291. if ( dstImageFormat == IMAGE_FORMAT_BGRA5551 ||
  1292. dstImageFormat == IMAGE_FORMAT_BGRX5551 )
  1293. {
  1294. ConvertFromDXT1( src, ( BGRA5551_t * )dst, width, height );
  1295. return true;
  1296. }
  1297. if ( dstImageFormat == IMAGE_FORMAT_BGRA4444 )
  1298. {
  1299. ConvertFromDXT1( src, ( BGRA4444_t * )dst, width, height );
  1300. return true;
  1301. }
  1302. }
  1303. else if ( srcImageFormat == IMAGE_FORMAT_ATI2N )
  1304. {
  1305. if ( dstImageFormat == IMAGE_FORMAT_BGRA8888 )
  1306. {
  1307. ConvertFromATIxN( src, ( BGRA8888_t * )dst, width, height, true );
  1308. return true;
  1309. }
  1310. }
  1311. else if ( srcImageFormat == IMAGE_FORMAT_ATI1N )
  1312. {
  1313. if ( dstImageFormat == IMAGE_FORMAT_BGRA8888 )
  1314. {
  1315. ConvertFromATIxN( src, ( BGRA8888_t * )dst, width, height, false );
  1316. return true;
  1317. }
  1318. }
  1319. else if ( srcImageFormat == IMAGE_FORMAT_DXT5 )
  1320. {
  1321. if ( dstImageFormat == IMAGE_FORMAT_RGBA8888 )
  1322. {
  1323. ConvertFromDXT5( src, ( RGBA8888_t * )dst, width, height );
  1324. return true;
  1325. }
  1326. if ( dstImageFormat == IMAGE_FORMAT_BGRA8888 ||
  1327. dstImageFormat == IMAGE_FORMAT_BGRX8888 )
  1328. {
  1329. ConvertFromDXT5( src, ( BGRA8888_t * )dst, width, height );
  1330. return true;
  1331. }
  1332. if ( dstImageFormat == IMAGE_FORMAT_RGB888 )
  1333. {
  1334. ConvertFromDXT5IgnoreAlpha( src, ( RGB888_t * )dst, width, height );
  1335. return true;
  1336. }
  1337. if ( dstImageFormat == IMAGE_FORMAT_BGR888 )
  1338. {
  1339. ConvertFromDXT5IgnoreAlpha( src, ( BGR888_t * )dst, width, height );
  1340. return true;
  1341. }
  1342. if ( dstImageFormat == IMAGE_FORMAT_BGR565 )
  1343. {
  1344. ConvertFromDXT5IgnoreAlpha( src, ( BGR565_t * )dst, width, height );
  1345. return true;
  1346. }
  1347. if ( dstImageFormat == IMAGE_FORMAT_BGRA5551 ||
  1348. dstImageFormat == IMAGE_FORMAT_BGRX5551 )
  1349. {
  1350. ConvertFromDXT5( src, ( BGRA5551_t * )dst, width, height );
  1351. return true;
  1352. }
  1353. if ( dstImageFormat == IMAGE_FORMAT_BGRA4444 )
  1354. {
  1355. ConvertFromDXT5( src, ( BGRA4444_t * )dst, width, height );
  1356. return true;
  1357. }
  1358. }
  1359. return false;
  1360. }
  1361. else if ( dstImageFormat == IMAGE_FORMAT_DXT1 ||
  1362. dstImageFormat == IMAGE_FORMAT_DXT3 ||
  1363. dstImageFormat == IMAGE_FORMAT_DXT5 ||
  1364. dstImageFormat == IMAGE_FORMAT_ATI1N ||
  1365. dstImageFormat == IMAGE_FORMAT_ATI2N ||
  1366. srcImageFormat == IMAGE_FORMAT_DXT1 ||
  1367. srcImageFormat == IMAGE_FORMAT_DXT3 ||
  1368. srcImageFormat == IMAGE_FORMAT_DXT5 ||
  1369. srcImageFormat == IMAGE_FORMAT_ATI1N ||
  1370. srcImageFormat == IMAGE_FORMAT_ATI2N )
  1371. {
  1372. // DxtN to DxtN
  1373. Assert( IsPC() );
  1374. return false;
  1375. }
  1376. else
  1377. {
  1378. // uncompressed textures
  1379. int line;
  1380. int srcPixelSize = SizeInBytes(srcImageFormat);
  1381. int dstPixelSize = SizeInBytes(dstImageFormat);
  1382. if ( srcStride == 0 )
  1383. {
  1384. srcStride = srcPixelSize * width;
  1385. }
  1386. if ( dstStride == 0 )
  1387. {
  1388. dstStride = dstPixelSize * width;
  1389. }
  1390. // Fast path...
  1391. if( ( srcImageFormat == dstImageFormat ) ||
  1392. ((srcImageFormat == IMAGE_FORMAT_BGRA8888) && (dstImageFormat == IMAGE_FORMAT_BGRX8888)) )
  1393. {
  1394. // I have no idea why this isn't true on all platforms but I didn't want to mess with stuff
  1395. if ( ( IsGameConsole() || (srcImageFormat == IMAGE_FORMAT_RGBA32323232F ) || ( srcImageFormat == IMAGE_FORMAT_RGBA8888 ) || ( srcImageFormat == IMAGE_FORMAT_BGRA8888 ) ) &&
  1396. ( srcStride == dstStride ) && ( width*srcPixelSize == srcStride ) )
  1397. {
  1398. // fastest path
  1399. memcpy( dst, src, height*srcStride );
  1400. return true;
  1401. }
  1402. for ( line = 0; line < height; ++line )
  1403. {
  1404. memcpy( dst, src, width*srcPixelSize );
  1405. dst += dstStride;
  1406. src += srcStride;
  1407. }
  1408. return true;
  1409. }
  1410. // fast version of BGRA to RGBA
  1411. if ( ( srcImageFormat == IMAGE_FORMAT_BGRA8888 ) && ( dstImageFormat == IMAGE_FORMAT_RGBA8888 ) && ( srcStride == dstStride ) )
  1412. {
  1413. BGRA8888ToRGBA8888( src, dst, width * height );
  1414. return true;
  1415. }
  1416. // format conversion
  1417. uint8 *lineBufRGBA8888 = (uint8 *)stackalloc(width*4);
  1418. UserFormatToRGBA8888Func_t userFormatToRGBA8888Func;
  1419. RGBA8888ToUserFormatFunc_t RGBA8888ToUserFormatFunc;
  1420. userFormatToRGBA8888Func = GetUserFormatToRGBA8888Func_t( srcImageFormat );
  1421. RGBA8888ToUserFormatFunc = GetRGBA8888ToUserFormatFunc_t( dstImageFormat );
  1422. if ( !userFormatToRGBA8888Func || !RGBA8888ToUserFormatFunc )
  1423. {
  1424. return false;
  1425. }
  1426. for ( line = 0; line < height; line++ )
  1427. {
  1428. userFormatToRGBA8888Func( src + line * srcStride, lineBufRGBA8888, width );
  1429. RGBA8888ToUserFormatFunc( lineBufRGBA8888, dst + line * dstStride, width );
  1430. }
  1431. return true;
  1432. }
  1433. }
  1434. //-----------------------------------------------------------------------------
  1435. // Color conversion routines
  1436. //-----------------------------------------------------------------------------
  1437. void ConvertIA88ImageToNormalMapRGBA8888( const uint8 *src, int width,
  1438. int height, uint8 *dst,
  1439. float bumpScale )
  1440. {
  1441. float heightScale = ( 1.0f / 255.0f ) * bumpScale;
  1442. float c, cx, cy;
  1443. float maxDim = ( width > height ) ? width : height;
  1444. float ooMaxDim = 1.0f / maxDim;
  1445. int s, t;
  1446. for( t = 0; t < height; t++ )
  1447. {
  1448. uint8 *dstPixel = &dst[t * width * 4];
  1449. for( s = 0; s < width; s++ )
  1450. {
  1451. c = src[( t * width + s ) * 2];
  1452. cx = src[( t * width + ((s+1)%width) ) * 2];
  1453. cy = src[( ((t+1)%height) * width + s ) * 2];
  1454. // \Z (out of screen)
  1455. // \
  1456. // \
  1457. // \
  1458. // \----------- X
  1459. // |
  1460. // |
  1461. // |
  1462. // |
  1463. // |
  1464. // Y
  1465. Vector xVect, yVect, normal;
  1466. xVect[0] = ooMaxDim;
  1467. xVect[1] = 0.0f;
  1468. xVect[2] = (cx - c) * heightScale;
  1469. yVect[0] = 0.0f;
  1470. yVect[1] = ooMaxDim;
  1471. yVect[2] = (cy - c) * heightScale;
  1472. CrossProduct( xVect, yVect, normal );
  1473. VectorNormalize( normal );
  1474. /* Repack the normalized vector into an RGB unsigned byte
  1475. vector in the normal map image. */
  1476. dstPixel[0] = ( uint8 )( 128 + 127*normal[0] );
  1477. dstPixel[1] = ( uint8 )( 128 + 127*normal[1] );
  1478. dstPixel[2] = ( uint8 )( 128 + 127*normal[2] );
  1479. dstPixel[3] = src[( ( t * width + s ) * 2 ) + 1];
  1480. dstPixel += 4;
  1481. }
  1482. }
  1483. }
  1484. void ConvertNormalMapRGBA8888ToDUDVMapUVWQ8888( const uint8 *src, int width, int height, uint8 *dst_ )
  1485. {
  1486. unsigned const char *lastPixel = src + width * height * 4;
  1487. char *dst = ( char * )dst_; // NOTE: this is signed!!!!
  1488. for( ; src < lastPixel; src += 4, dst += 4 )
  1489. {
  1490. dst[0] = ( char )( ( ( int )src[0] ) - 127 );
  1491. dst[1] = ( char )( ( ( int )src[1] ) - 127 );
  1492. dst[2] = ( char )( ( ( int )src[2] ) - 127 );
  1493. dst[3] = ( char )( ( ( int )src[3] ) - 127 );
  1494. }
  1495. }
  1496. void ConvertNormalMapRGBA8888ToDUDVMapUVLX8888( const uint8 *src, int width, int height, uint8 *dst_ )
  1497. {
  1498. unsigned const char *lastPixel = src + width * height * 4;
  1499. char *dst = ( char * )dst_; // NOTE: this is signed!!!!
  1500. for( ; src < lastPixel; src += 4, dst += 4 )
  1501. {
  1502. dst[0] = ( char )( ( ( int )src[0] ) - 127 );
  1503. dst[1] = ( char )( ( ( int )src[1] ) - 127 );
  1504. uint8 *pUDst = (uint8 *)dst;
  1505. pUDst[2] = src[3];
  1506. pUDst[3] = 0xFF;
  1507. }
  1508. }
  1509. // Route to ATI compressor to convert normal map to DXT5 GA format
  1510. void ConvertNormalMapARGB8888ToDXT5GA( const unsigned char *src, unsigned char *dst, int width, int height )
  1511. {
  1512. // Use ATI compressor to convert to DXT5 GA normal map format
  1513. ConvertToATIxN( src, IMAGE_FORMAT_ARGB8888, dst, IMAGE_FORMAT_DXT5, width, height, 0, 0, true );
  1514. }
  1515. void ConvertNormalMapRGBA8888ToDUDVMapUV88( const uint8 *src, int width, int height,
  1516. uint8 *dst_ )
  1517. {
  1518. unsigned const char *lastPixel = src + width * height * 4;
  1519. char *dst = ( char * )dst_; // NOTE: this is signed!!!!
  1520. for( ; src < lastPixel; src += 4, dst += 2 )
  1521. {
  1522. dst[0] = ( char )( ( ( int )src[0] ) - 127 );
  1523. dst[1] = ( char )( ( ( int )src[1] ) - 127 );
  1524. }
  1525. }
  1526. void NormalizeNormalMapRGBA8888( uint8 *src, int numTexels )
  1527. {
  1528. uint8 *lastPixel = src + numTexels * 4;
  1529. for( uint8 *pixel = src; pixel < lastPixel; pixel += 4 )
  1530. {
  1531. Vector tmpVect;
  1532. tmpVect[0] = ( ( float )pixel[0] - 128.0f ) * ( 1.0f / 127.0f );
  1533. tmpVect[1] = ( ( float )pixel[1] - 128.0f ) * ( 1.0f / 127.0f );
  1534. tmpVect[2] = ( ( float )pixel[2] - 128.0f ) * ( 1.0f / 127.0f );
  1535. VectorNormalize( tmpVect );
  1536. pixel[0] = ( uint8 )( 128 + 127 * tmpVect[0] );
  1537. pixel[1] = ( uint8 )( 128 + 127 * tmpVect[1] );
  1538. pixel[2] = ( uint8 )( 128 + 127 * tmpVect[2] );
  1539. }
  1540. }
  1541. //-----------------------------------------------------------------------------
  1542. // Image rotation
  1543. //-----------------------------------------------------------------------------
  1544. bool RotateImageLeft( const uint8 *src, uint8 *dst,
  1545. int widthHeight, ImageFormat imageFormat )
  1546. {
  1547. #define SRC(x,y) src[((x)+(y)*widthHeight)*sizeInBytes]
  1548. #define DST(x,y) dst[((x)+(y)*widthHeight)*sizeInBytes]
  1549. if( IsCompressed( imageFormat ) )
  1550. {
  1551. return false;
  1552. }
  1553. int x, y;
  1554. uint8 tmp[4][16];
  1555. int halfWidthHeight = widthHeight >> 1;
  1556. int sizeInBytes = SizeInBytes( imageFormat );
  1557. Assert( sizeInBytes <= 16 && sizeInBytes > 0 );
  1558. for( y = 0; y < halfWidthHeight; y++ )
  1559. {
  1560. for( x = 0; x < halfWidthHeight; x++ )
  1561. {
  1562. memcpy( tmp[0], &SRC( x, y ), sizeInBytes );
  1563. memcpy( tmp[1], &SRC( y, widthHeight-x-1 ), sizeInBytes );
  1564. memcpy( tmp[2], &SRC( widthHeight-x-1, widthHeight-y-1 ), sizeInBytes );
  1565. memcpy( tmp[3], &SRC( widthHeight-y-1, x ), sizeInBytes );
  1566. memcpy( &DST( x, y ), tmp[3], sizeInBytes );
  1567. memcpy( &DST( y, widthHeight-x-1 ), tmp[0], sizeInBytes );
  1568. memcpy( &DST( widthHeight-x-1, widthHeight-y-1 ), tmp[1], sizeInBytes );
  1569. memcpy( &DST( widthHeight-y-1, x ), tmp[2], sizeInBytes );
  1570. }
  1571. }
  1572. #undef SRC
  1573. #undef DST
  1574. return true;
  1575. }
  1576. bool RotateImage180( const uint8 *src, uint8 *dst,
  1577. int widthHeight, ImageFormat imageFormat )
  1578. {
  1579. // OPTIMIZE: do this transformation directly.
  1580. if( RotateImageLeft( src, dst, widthHeight, imageFormat ) )
  1581. {
  1582. return RotateImageLeft( dst, dst, widthHeight, imageFormat );
  1583. }
  1584. return false;
  1585. }
  1586. bool FlipImageVertically( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride )
  1587. {
  1588. if( IsCompressed( imageFormat ) )
  1589. return false;
  1590. int nSizeInBytes = SizeInBytes( imageFormat );
  1591. int nRowBytes = nSizeInBytes * nWidth;
  1592. int nSrcStride = nRowBytes;
  1593. if ( nDstStride == 0 )
  1594. {
  1595. nDstStride = nRowBytes;
  1596. }
  1597. uint8 *pSrcRow = (uint8*)pSrc;
  1598. uint8 *pDstRow = (uint8*)pDst + ((nHeight-1) * nDstStride);
  1599. if ( pSrc == pDst )
  1600. {
  1601. uint8* pTemp = (uint8*)stackalloc( nRowBytes );
  1602. int nHalfHeight = nHeight >> 1;
  1603. for ( int i = 0; i < nHalfHeight; i++ )
  1604. {
  1605. memcpy( pTemp, pSrcRow, nRowBytes );
  1606. memcpy( pSrcRow, pDstRow, nRowBytes );
  1607. memcpy( pDstRow, pTemp, nRowBytes );
  1608. pSrcRow += nSrcStride;
  1609. pDstRow -= nDstStride;
  1610. }
  1611. }
  1612. else
  1613. {
  1614. for ( int i = 0; i < nHeight; i++ )
  1615. {
  1616. memcpy( pDstRow, pSrcRow, nRowBytes );
  1617. pSrcRow += nSrcStride;
  1618. pDstRow -= nDstStride;
  1619. }
  1620. }
  1621. return true;
  1622. }
  1623. bool FlipImageHorizontally( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride )
  1624. {
  1625. if( IsCompressed( imageFormat ) )
  1626. return false;
  1627. uint8 tmp[16];
  1628. int nSizeInBytes = SizeInBytes( imageFormat );
  1629. int nRowBytes = nSizeInBytes * nWidth;
  1630. Assert( nSizeInBytes <= 16 && nSizeInBytes > 0 );
  1631. int nSrcStride = nRowBytes;
  1632. if ( nDstStride == 0 )
  1633. {
  1634. nDstStride = nRowBytes;
  1635. }
  1636. int x, y;
  1637. uint8 *pSrcRow = (uint8*)pSrc;
  1638. uint8 *pDstRow = (uint8*)pDst;
  1639. if ( pSrc == pDst )
  1640. {
  1641. int nHalfWidth = nWidth >> 1;
  1642. for( y = 0; y < nHeight; y++ )
  1643. {
  1644. uint8 *pSrcPixel = pSrcRow;
  1645. uint8 *pDstPixel = pDstRow + nRowBytes - nSizeInBytes;
  1646. for( x = 0; x < nHalfWidth; x++ )
  1647. {
  1648. memcpy( tmp, pSrcPixel, nSizeInBytes );
  1649. memcpy( pSrcPixel, pDstPixel, nSizeInBytes );
  1650. memcpy( pDstPixel, tmp, nSizeInBytes );
  1651. pSrcPixel += nSizeInBytes;
  1652. pDstPixel -= nSizeInBytes;
  1653. }
  1654. pSrcRow += nSrcStride;
  1655. pDstRow += nDstStride;
  1656. }
  1657. }
  1658. else
  1659. {
  1660. for( y = 0; y < nHeight; y++ )
  1661. {
  1662. uint8 *pSrcPixel = pSrcRow;
  1663. uint8 *pDstPixel = pDstRow + nRowBytes - nSizeInBytes;
  1664. for( x = 0; x < nWidth; x++ )
  1665. {
  1666. memcpy( pDstPixel, pSrcPixel, nSizeInBytes );
  1667. pSrcPixel += nSizeInBytes;
  1668. pDstPixel -= nSizeInBytes;
  1669. }
  1670. pSrcRow += nSrcStride;
  1671. pDstRow += nDstStride;
  1672. }
  1673. }
  1674. return true;
  1675. }
  1676. //-----------------------------------------------------------------------------
  1677. // Image rotation
  1678. //-----------------------------------------------------------------------------
  1679. bool SwapAxes( uint8 *src, int widthHeight, ImageFormat imageFormat )
  1680. {
  1681. #define SRC(x,y) src[((x)+(y)*widthHeight)*sizeInBytes]
  1682. if( IsCompressed( imageFormat ) )
  1683. {
  1684. return false;
  1685. }
  1686. int x, y;
  1687. uint8 tmp[4];
  1688. int sizeInBytes = SizeInBytes( imageFormat );
  1689. Assert( sizeInBytes <= 4 && sizeInBytes > 0 );
  1690. for( y = 0; y < widthHeight; y++ )
  1691. {
  1692. for( x = 0; x < y; x++ )
  1693. {
  1694. memcpy( tmp, &SRC( x, y ), sizeInBytes );
  1695. memcpy( &SRC( x, y ), &SRC( y, x ), sizeInBytes );
  1696. memcpy( &SRC( y, x ), tmp, sizeInBytes );
  1697. }
  1698. }
  1699. #undef SRC
  1700. return true;
  1701. }
  1702. void RGBA8888ToRGBA16161616F( const uint8 *src, uint8 *dst, int numPixels )
  1703. {
  1704. float flOO255 = 1.0f / 255.0f;
  1705. float16 *pDest = (float16*)dst;
  1706. const uint8 *endSrc = src + numPixels * 4;
  1707. for ( ; src < endSrc; src += 4, pDest += 4 )
  1708. {
  1709. pDest[0].SetFloat( src[0] * flOO255 );
  1710. pDest[1].SetFloat( src[1] * flOO255 );
  1711. pDest[2].SetFloat( src[2] * flOO255 );
  1712. pDest[3].SetFloat( src[3] * flOO255 );
  1713. }
  1714. }
  1715. void RGBA8888ToRGBA32323232F( const uint8 *src, uint8 *dst, int numPixels )
  1716. {
  1717. float flOO255 = 1.0f / 255.0f;
  1718. float32 *pDest = (float32*)dst;
  1719. const uint8 *endSrc = src + numPixels * 4;
  1720. for ( ; src < endSrc; src += 4, pDest += 4 )
  1721. {
  1722. pDest[0] = src[0] * flOO255;
  1723. pDest[1] = src[1] * flOO255;
  1724. pDest[2] = src[2] * flOO255;
  1725. pDest[3] = src[3] * flOO255;
  1726. }
  1727. }
  1728. void RGBA8888ToRGB323232F( const uint8 *src, uint8 *dst, int numPixels )
  1729. {
  1730. float flOO255 = 1.0f / 255.0f;
  1731. float32 *pDest = (float32*)dst;
  1732. const uint8 *endSrc = src + numPixels * 4;
  1733. for ( ; src < endSrc; src += 4, pDest += 3 )
  1734. {
  1735. pDest[0] = src[0] * flOO255;
  1736. pDest[1] = src[1] * flOO255;
  1737. pDest[2] = src[2] * flOO255;
  1738. }
  1739. }
  1740. void RGBA8888ToRG3232F( const uint8 *src, uint8 *dst, int numPixels )
  1741. {
  1742. float flOO255 = 1.0f / 255.0f;
  1743. float32 *pDest = (float32*)dst;
  1744. const uint8 *endSrc = src + numPixels * 4;
  1745. for ( ; src < endSrc; src += 4, pDest += 2 )
  1746. {
  1747. pDest[0] = src[0] * flOO255;
  1748. pDest[1] = src[1] * flOO255;
  1749. }
  1750. }
  1751. void RGBA8888ToR32F( const uint8 *src, uint8 *dst, int numPixels )
  1752. {
  1753. float flOO255 = 1.0f / 255.0f;
  1754. float32 *pDest = (float32*)dst;
  1755. const uint8 *endSrc = src + numPixels * 4;
  1756. for ( ; src < endSrc; src += 4 )
  1757. {
  1758. *pDest++ = src[0] * flOO255;
  1759. }
  1760. }
  1761. void RGBA8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  1762. {
  1763. memcpy( dst, src, 4 * numPixels );
  1764. }
  1765. void RGBA8888ToABGR8888( const uint8 *src, uint8 *dst, int numPixels )
  1766. {
  1767. const uint8 *endSrc = src + numPixels * 4;
  1768. for ( ; src < endSrc; src += 4, dst += 4 )
  1769. {
  1770. dst[0] = src[3];
  1771. dst[1] = src[2];
  1772. dst[2] = src[1];
  1773. dst[3] = src[0];
  1774. }
  1775. }
  1776. void RGBA8888ToRGB888( const uint8 *src, uint8 *dst, int numPixels )
  1777. {
  1778. const uint8 *endSrc = src + numPixels * 4;
  1779. for ( ; src < endSrc; src += 4, dst += 3 )
  1780. {
  1781. dst[0] = src[0];
  1782. dst[1] = src[1];
  1783. dst[2] = src[2];
  1784. }
  1785. }
  1786. void RGBA8888ToBGR888( const uint8 *src, uint8 *dst, int numPixels )
  1787. {
  1788. const uint8 *endSrc = src + numPixels * 4;
  1789. for ( ; src < endSrc; src += 4, dst += 3 )
  1790. {
  1791. dst[0] = src[2];
  1792. dst[1] = src[1];
  1793. dst[2] = src[0];
  1794. }
  1795. }
  1796. void RGBA8888ToRGB565( const uint8 *src, uint8 *dst, int numPixels )
  1797. {
  1798. Assert( 0 );
  1799. const uint8 *endSrc = src + numPixels * 4;
  1800. for ( ; src < endSrc; src += 4, dst += 2 )
  1801. {
  1802. }
  1803. }
  1804. void RGBA8888ToI8( const uint8 *src, uint8 *dst, int numPixels )
  1805. {
  1806. const uint8 *endSrc = src + numPixels * 4;
  1807. for ( ; src < endSrc; src += 4, dst += 1 )
  1808. {
  1809. dst[0] = ( uint8 )( 0.299f * src[0] + 0.587f * src[1] + 0.114f * src[2] );
  1810. }
  1811. }
  1812. void RGBA8888ToIA88( const uint8 *src, uint8 *dst, int numPixels )
  1813. {
  1814. // fixme: need to find the proper rgb weighting
  1815. const uint8 *endSrc = src + numPixels * 4;
  1816. for ( ; src < endSrc; src += 4, dst += 2 )
  1817. {
  1818. dst[0] = ( uint8 )( 0.299f * src[0] + 0.587f * src[1] + 0.114f * src[2] );
  1819. dst[1] = src[3];
  1820. }
  1821. }
  1822. void RGBA8888ToP8( const uint8 *src, uint8 *dst, int numPixels )
  1823. {
  1824. Assert( 0 );
  1825. }
  1826. void RGBA8888ToA8( const uint8 *src, uint8 *dst, int numPixels )
  1827. {
  1828. const uint8 *endSrc = src + numPixels * 4;
  1829. for ( ; src < endSrc; src += 4, dst += 1 )
  1830. {
  1831. dst[0] = src[3];
  1832. }
  1833. }
  1834. void RGBA8888ToRGB888_BLUESCREEN( const uint8 *src, uint8 *dst, int numPixels )
  1835. {
  1836. const uint8 *endSrc = src + numPixels * 4;
  1837. for ( ; src < endSrc; src += 4, dst += 3 )
  1838. {
  1839. if( src[3] == 0 )
  1840. {
  1841. dst[0] = 0;
  1842. dst[1] = 0;
  1843. dst[2] = 255;
  1844. }
  1845. else
  1846. {
  1847. dst[0] = src[0];
  1848. dst[1] = src[1];
  1849. dst[2] = src[2];
  1850. }
  1851. }
  1852. }
  1853. void RGBA8888ToBGR888_BLUESCREEN( const uint8 *src, uint8 *dst, int numPixels )
  1854. {
  1855. const uint8 *endSrc = src + numPixels * 4;
  1856. for ( ; src < endSrc; src += 4, dst += 3 )
  1857. {
  1858. if( src[3] == 0 )
  1859. {
  1860. dst[2] = 0;
  1861. dst[1] = 0;
  1862. dst[0] = 255;
  1863. }
  1864. else
  1865. {
  1866. dst[2] = src[0];
  1867. dst[1] = src[1];
  1868. dst[0] = src[2];
  1869. }
  1870. }
  1871. }
  1872. void RGBA8888ToARGB8888( const uint8 *src, uint8 *dst, int numPixels )
  1873. {
  1874. const uint8 *endSrc = src + numPixels * 4;
  1875. for ( ; src < endSrc; src += 4, dst += 4 )
  1876. {
  1877. dst[0] = src[3];
  1878. dst[1] = src[0];
  1879. dst[2] = src[1];
  1880. dst[3] = src[2];
  1881. }
  1882. }
  1883. void RGBA8888ToBGRA8888( const uint8 *src, uint8 *dst, int numPixels )
  1884. {
  1885. const uint8 *endSrc = src + numPixels * 4;
  1886. for ( ; src < endSrc; src += 4, dst += 4 )
  1887. {
  1888. dst[0] = src[2];
  1889. dst[1] = src[1];
  1890. dst[2] = src[0];
  1891. dst[3] = src[3];
  1892. }
  1893. }
  1894. void RGBA8888ToBGRX8888( const uint8 *src, uint8 *dst, int numPixels )
  1895. {
  1896. const uint8 *endSrc = src + numPixels * 4;
  1897. for ( ; src < endSrc; src += 4, dst += 4 )
  1898. {
  1899. dst[0] = src[2];
  1900. dst[1] = src[1];
  1901. dst[2] = src[0];
  1902. }
  1903. }
  1904. void RGBA8888ToBGR565( const uint8 *src, uint8 *dst, int numPixels )
  1905. {
  1906. unsigned short* pDstShort = (unsigned short*)dst;
  1907. const uint8 *endSrc = src + numPixels * 4;
  1908. for ( ; src < endSrc; src += 4, pDstShort ++ )
  1909. {
  1910. *pDstShort = ((src[0] >> 3) << 11) |
  1911. ((src[1] >> 2) << 5) |
  1912. (src[2] >> 3);
  1913. }
  1914. }
  1915. void RGBA8888ToBGRX5551( const uint8 *src, uint8 *dst, int numPixels )
  1916. {
  1917. unsigned short* pDstShort = (unsigned short*)dst;
  1918. const uint8 *endSrc = src + numPixels * 4;
  1919. for ( ; src < endSrc; src += 4, pDstShort ++ )
  1920. {
  1921. *pDstShort = ((src[0] >> 3) << 10) |
  1922. ((src[1] >> 3) << 5) |
  1923. (src[2] >> 3);
  1924. }
  1925. }
  1926. void RGBA8888ToBGRA5551( const uint8 *src, uint8 *dst, int numPixels )
  1927. {
  1928. unsigned short* pDstShort = (unsigned short*)dst;
  1929. const uint8 *endSrc = src + numPixels * 4;
  1930. for ( ; src < endSrc; src += 4, pDstShort ++ )
  1931. {
  1932. *pDstShort = ((src[0] >> 3) << 10) |
  1933. ((src[1] >> 3) << 5) |
  1934. (src[2] >> 3) |
  1935. (src[3] >> 7) << 15;
  1936. }
  1937. }
  1938. void RGBA8888ToBGRA4444( const uint8 *src, uint8 *dst, int numPixels )
  1939. {
  1940. unsigned short* pDstShort = (unsigned short*)dst;
  1941. const uint8 *endSrc = src + numPixels * 4;
  1942. for ( ; src < endSrc; src += 4, pDstShort ++ )
  1943. {
  1944. *pDstShort = ((src[0] >> 4) << 8) |
  1945. ((src[1] >> 4) << 4) |
  1946. (src[2] >> 4) |
  1947. ((src[3] >> 4) << 12);
  1948. }
  1949. }
  1950. void RGBA8888ToUV88( const uint8 *src, uint8 *dst, int numPixels )
  1951. {
  1952. const uint8 *endSrc = src + numPixels * 4;
  1953. for ( ; src < endSrc; src += 4, dst += 2 )
  1954. {
  1955. dst[0] = src[0];
  1956. dst[1] = src[1];
  1957. }
  1958. }
  1959. void RGBA8888ToUVWQ8888( const uint8 *src, uint8 *dst, int numPixels )
  1960. {
  1961. RGBA8888ToRGBA8888( src, dst, numPixels );
  1962. }
  1963. void RGBA8888ToUVLX8888( const uint8 *src, uint8 *dst, int numPixels )
  1964. {
  1965. RGBA8888ToRGBA8888( src, dst, numPixels );
  1966. }
  1967. void ABGR8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  1968. {
  1969. const uint8 *endSrc = src + numPixels * 4;
  1970. for ( ; src < endSrc; src += 4, dst += 4 )
  1971. {
  1972. dst[0] = src[3];
  1973. dst[1] = src[2];
  1974. dst[2] = src[1];
  1975. dst[3] = src[0];
  1976. }
  1977. }
  1978. void RGB888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  1979. {
  1980. const uint8 *endSrc = src + numPixels * 3;
  1981. for ( ; src < endSrc; src += 3, dst += 4 )
  1982. {
  1983. dst[0] = src[0];
  1984. dst[1] = src[1];
  1985. dst[2] = src[2];
  1986. dst[3] = 255;
  1987. }
  1988. }
  1989. void BGR888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  1990. {
  1991. const uint8 *endSrc = src + numPixels * 3;
  1992. for ( ; src < endSrc; src += 3, dst += 4 )
  1993. {
  1994. dst[0] = src[2];
  1995. dst[1] = src[1];
  1996. dst[2] = src[0];
  1997. dst[3] = 255;
  1998. }
  1999. }
  2000. void RGB565ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2001. {
  2002. Assert( 0 );
  2003. const uint8 *endSrc = src + numPixels * 2;
  2004. for ( ; src < endSrc; src += 2, dst += 4 )
  2005. {
  2006. }
  2007. }
  2008. void I8ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2009. {
  2010. const uint8 *endSrc = src + numPixels;
  2011. for ( ; src < endSrc; src += 1, dst += 4 )
  2012. {
  2013. dst[0] = src[0];
  2014. dst[1] = src[0];
  2015. dst[2] = src[0];
  2016. dst[3] = 255;
  2017. }
  2018. }
  2019. void IA88ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2020. {
  2021. const uint8 *endSrc = src + numPixels * 2;
  2022. for ( ; src < endSrc; src += 2, dst += 4 )
  2023. {
  2024. dst[0] = src[0];
  2025. dst[1] = src[0];
  2026. dst[2] = src[0];
  2027. dst[3] = src[1];
  2028. }
  2029. }
  2030. void P8ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2031. {
  2032. Assert( 0 );
  2033. }
  2034. void A8ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2035. {
  2036. const uint8 *endSrc = src + numPixels;
  2037. for ( ; src < endSrc; src += 1, dst += 4 )
  2038. {
  2039. dst[0] = src[0];
  2040. dst[1] = src[0];
  2041. dst[2] = src[0];
  2042. dst[3] = src[0];
  2043. }
  2044. }
  2045. void RGB888_BLUESCREENToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2046. {
  2047. const uint8 *endSrc = src + numPixels * 3;
  2048. for ( ; src < endSrc; src += 3, dst += 4 )
  2049. {
  2050. if( src[0] == 0 && src[1] == 0 && src[2] == 255 )
  2051. {
  2052. dst[0] = 0;
  2053. dst[1] = 0;
  2054. dst[2] = 0;
  2055. dst[3] = 0;
  2056. }
  2057. else
  2058. {
  2059. dst[0] = src[0];
  2060. dst[1] = src[1];
  2061. dst[2] = src[2];
  2062. dst[3] = 255;
  2063. }
  2064. }
  2065. }
  2066. void BGR888_BLUESCREENToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2067. {
  2068. const uint8 *endSrc = src + numPixels * 3;
  2069. for ( ; src < endSrc; src += 3, dst += 4 )
  2070. {
  2071. if( src[2] == 0 && src[1] == 0 && src[0] == 255 )
  2072. {
  2073. dst[0] = 0;
  2074. dst[1] = 0;
  2075. dst[2] = 0;
  2076. dst[3] = 0;
  2077. }
  2078. else
  2079. {
  2080. dst[2] = src[0];
  2081. dst[1] = src[1];
  2082. dst[0] = src[2];
  2083. dst[3] = 255;
  2084. }
  2085. }
  2086. }
  2087. void ARGB8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2088. {
  2089. const uint8 *endSrc = src + numPixels * 4;
  2090. for ( ; src < endSrc; src += 4, dst += 4 )
  2091. {
  2092. dst[0] = src[1];
  2093. dst[1] = src[2];
  2094. dst[2] = src[3];
  2095. dst[3] = src[0];
  2096. }
  2097. }
  2098. void BGRA8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2099. {
  2100. const uint8 *endSrc = src + numPixels * 4;
  2101. for ( ; src < endSrc; src += 4, dst += 4 )
  2102. {
  2103. dst[0] = src[2];
  2104. dst[1] = src[1];
  2105. dst[2] = src[0];
  2106. dst[3] = src[3];
  2107. }
  2108. }
  2109. void BGRX8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2110. {
  2111. const uint8 *endSrc = src + numPixels * 4;
  2112. for ( ; src < endSrc; src += 4, dst += 4 )
  2113. {
  2114. dst[0] = src[2];
  2115. dst[1] = src[1];
  2116. dst[2] = src[0];
  2117. dst[3] = 255;
  2118. }
  2119. }
  2120. void BGR565ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2121. {
  2122. unsigned short* pSrcShort = (unsigned short*)src;
  2123. unsigned short* pEndSrc = pSrcShort + numPixels;
  2124. for ( ; pSrcShort < pEndSrc; pSrcShort++, dst += 4 )
  2125. {
  2126. int blue = (*pSrcShort & 0x1F);
  2127. int green = (*pSrcShort >> 5) & 0x3F;
  2128. int red = (*pSrcShort >> 11) & 0x1F;
  2129. // Expand to 8 bits
  2130. dst[0] = (red << 3) | (red >> 2);
  2131. dst[1] = (green << 2) | (green >> 4);
  2132. dst[2] = (blue << 3) | (blue >> 2);
  2133. dst[3] = 255;
  2134. }
  2135. }
  2136. void BGRX5551ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2137. {
  2138. unsigned short* pSrcShort = (unsigned short*)src;
  2139. unsigned short* pEndSrc = pSrcShort + numPixels;
  2140. for ( ; pSrcShort < pEndSrc; pSrcShort++, dst += 4 )
  2141. {
  2142. int blue = (*pSrcShort & 0x1F);
  2143. int green = (*pSrcShort >> 5) & 0x1F;
  2144. int red = (*pSrcShort >> 10) & 0x1F;
  2145. // Expand to 8 bits
  2146. dst[0] = (red << 3) | (red >> 2);
  2147. dst[1] = (green << 3) | (green >> 2);
  2148. dst[2] = (blue << 3) | (blue >> 2);
  2149. dst[3] = 255;
  2150. }
  2151. }
  2152. void BGRA5551ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2153. {
  2154. unsigned short* pSrcShort = (unsigned short*)src;
  2155. unsigned short* pEndSrc = pSrcShort + numPixels;
  2156. for ( ; pSrcShort < pEndSrc; pSrcShort++, dst += 4 )
  2157. {
  2158. int blue = (*pSrcShort & 0x1F);
  2159. int green = (*pSrcShort >> 5) & 0x1F;
  2160. int red = (*pSrcShort >> 10) & 0x1F;
  2161. int alpha = *pSrcShort & ( 1 << 15 );
  2162. // Expand to 8 bits
  2163. dst[0] = (red << 3) | (red >> 2);
  2164. dst[1] = (green << 3) | (green >> 2);
  2165. dst[2] = (blue << 3) | (blue >> 2);
  2166. // garymcthack
  2167. if( alpha )
  2168. {
  2169. dst[3] = 255;
  2170. }
  2171. else
  2172. {
  2173. dst[3] = 0;
  2174. }
  2175. }
  2176. }
  2177. void BGRA4444ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2178. {
  2179. unsigned short* pSrcShort = (unsigned short*)src;
  2180. unsigned short* pEndSrc = pSrcShort + numPixels;
  2181. for ( ; pSrcShort < pEndSrc; pSrcShort++, dst += 4 )
  2182. {
  2183. int blue = (*pSrcShort & 0xF);
  2184. int green = (*pSrcShort >> 4) & 0xF;
  2185. int red = (*pSrcShort >> 8) & 0xF;
  2186. int alpha = (*pSrcShort >> 12) & 0xF;
  2187. // Expand to 8 bits
  2188. // FIXME: shouldn't this be (red << 4) | red?
  2189. dst[0] = (red << 4) | (red >> 4);
  2190. dst[1] = (green << 4) | (green >> 4);
  2191. dst[2] = (blue << 4) | (blue >> 4);
  2192. dst[3] = (alpha << 4) | (alpha >> 4);
  2193. }
  2194. }
  2195. void UV88ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2196. {
  2197. const uint8* pEndSrc = src + numPixels * 2;
  2198. for ( ; src < pEndSrc; src += 2, dst += 4 )
  2199. {
  2200. dst[0] = src[0];
  2201. dst[1] = src[1];
  2202. dst[2] = 0;
  2203. dst[3] = 0;
  2204. }
  2205. }
  2206. void UVWQ8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2207. {
  2208. RGBA8888ToRGBA8888( src, dst, numPixels );
  2209. }
  2210. void UVLX8888ToRGBA8888( const uint8 *src, uint8 *dst, int numPixels )
  2211. {
  2212. RGBA8888ToRGBA8888( src, dst, numPixels );
  2213. }
  2214. // HDRFIXME: This assumes that the 16-bit integer values are 4.12 fixed-point.
  2215. void RGBA16161616ToRGBA8888( const uint8 *src_, uint8 *dst, int numPixels )
  2216. {
  2217. unsigned short *src = ( unsigned short * )src_;
  2218. unsigned short *pEndSrc = src + numPixels * 4;
  2219. for ( ; src < pEndSrc; src += 4, dst += 4 )
  2220. {
  2221. dst[0] = MIN( 255, src[0] >> 4 );
  2222. dst[1] = MIN( 255, src[1] >> 4 );
  2223. dst[2] = MIN( 255, src[2] >> 4 );
  2224. dst[3] = MIN( 255, src[3] >> 8 );
  2225. }
  2226. }
  2227. } // ImageLoader namespace ends