Team Fortress 2 Source Code as on 22/4/2020
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.

279 lines
6.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "tgaloader.h"
  7. #include "tier0/dbg.h"
  8. #pragma pack(1)
  9. typedef struct _TargaHeader {
  10. unsigned char id_length, colormap_type, image_type;
  11. unsigned short colormap_index, colormap_length;
  12. unsigned char colormap_size;
  13. unsigned short x_origin, y_origin, width, height;
  14. unsigned char pixel_size, attributes;
  15. } TargaHeader;
  16. #pragma pack()
  17. #define TGA_ATTRIBUTE_HFLIP 16
  18. #define TGA_ATTRIBUTE_VFLIP 32
  19. int fgetLittleShort (unsigned char **p)
  20. {
  21. byte b1, b2;
  22. b1 = *((*p)++);
  23. b2 = *((*p)++);
  24. return (short)(b1 + b2*256);
  25. }
  26. int fgetLittleLong (unsigned char **p)
  27. {
  28. byte b1, b2, b3, b4;
  29. b1 = *((*p)++);
  30. b2 = *((*p)++);
  31. b3 = *((*p)++);
  32. b4 = *((*p)++);
  33. return b1 + (b2<<8) + (b3<<16) + (b4<<24);
  34. }
  35. bool GetTGADimensions( int32 iBytes, char *pData, int * width, int *height )
  36. {
  37. TargaHeader header;
  38. unsigned char *p = (unsigned char *)pData;
  39. if (width) *width = 0;
  40. if (height) *height = 0;
  41. header.id_length = *(p++);
  42. header.colormap_type = *(p++);
  43. header.image_type = *(p++);
  44. header.colormap_index = fgetLittleShort(&p);
  45. header.colormap_length = fgetLittleShort(&p);
  46. header.colormap_size = *(p++);
  47. header.x_origin = fgetLittleShort(&p);
  48. header.y_origin = fgetLittleShort(&p);
  49. header.width = fgetLittleShort(&p);
  50. header.height = fgetLittleShort(&p);
  51. header.pixel_size = *(p++);
  52. header.attributes = *(p++);
  53. if ( header.image_type != 2 && header.image_type != 10 )
  54. {
  55. Msg( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
  56. return false;
  57. }
  58. if ( header.colormap_type !=0 || ( header.pixel_size != 32 && header.pixel_size != 24 ) )
  59. {
  60. Msg("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
  61. return false;
  62. }
  63. if (width) *width = header.width;
  64. if (height) *height = header.height;
  65. return true;
  66. }
  67. bool LoadTGA( int32 iBytes, char *pData, byte **rawImage, int * rawImageBytes, int * width, int *height )
  68. {
  69. TargaHeader header;
  70. unsigned char *p = (unsigned char *)pData;
  71. if (width) *width = 0;
  72. if (height) *height = 0;
  73. header.id_length = *(p++);
  74. header.colormap_type = *(p++);
  75. header.image_type = *(p++);
  76. header.colormap_index = fgetLittleShort(&p);
  77. header.colormap_length = fgetLittleShort(&p);
  78. header.colormap_size = *(p++);
  79. header.x_origin = fgetLittleShort(&p);
  80. header.y_origin = fgetLittleShort(&p);
  81. header.width = fgetLittleShort(&p);
  82. header.height = fgetLittleShort(&p);
  83. header.pixel_size = *(p++);
  84. header.attributes = *(p++);
  85. if ( header.image_type != 2 && header.image_type != 10 )
  86. {
  87. Msg( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
  88. return false;
  89. }
  90. if ( header.colormap_type !=0 || ( header.pixel_size != 32 && header.pixel_size != 24 ) )
  91. {
  92. Msg("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
  93. return false;
  94. }
  95. int columns = header.width;
  96. int rows = header.height;
  97. int numPixels = columns * rows;
  98. if (width) *width = header.width;
  99. if (height) *height = header.height;
  100. if (rawImageBytes) *rawImageBytes = header.width * header.height * 4;
  101. *rawImage = new byte[ numPixels * 4 ];
  102. byte *pixbuf = *rawImage;
  103. if ( header.id_length != 0 )
  104. p += header.id_length; // skip TARGA image comment.
  105. if ( header.image_type == 2 ) { // Uncompressed, RGB images
  106. for(int row = rows - 1; row >=0; row-- )
  107. {
  108. if ( header.attributes & TGA_ATTRIBUTE_VFLIP )
  109. pixbuf = *rawImage + (rows-row-1)*columns*4;
  110. else
  111. pixbuf = *rawImage + row*columns*4;
  112. for(int column=0; column < columns; column++)
  113. {
  114. unsigned char red,green,blue,alphabyte;
  115. switch ( header.pixel_size )
  116. {
  117. case 24:
  118. blue = *(p++);
  119. green = *(p++);
  120. red = *(p++);
  121. *pixbuf++ = red;
  122. *pixbuf++ = green;
  123. *pixbuf++ = blue;
  124. *pixbuf++ = 255;
  125. break;
  126. case 32:
  127. blue = *(p++);
  128. green = *(p++);
  129. red = *(p++);
  130. alphabyte = *(p++);
  131. *pixbuf++ = red;
  132. *pixbuf++ = green;
  133. *pixbuf++ = blue;
  134. *pixbuf++ = alphabyte;
  135. break;
  136. }
  137. }
  138. }
  139. }
  140. else if ( header.image_type == 10 )
  141. {
  142. // Runlength encoded RGB images
  143. unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
  144. for( int row = rows - 1; row >= 0; row--)
  145. {
  146. if ( header.attributes & TGA_ATTRIBUTE_VFLIP )
  147. pixbuf = *rawImage + (rows-row-1)*columns*4;
  148. else
  149. pixbuf = *rawImage + row*columns*4;
  150. for( int column=0; column < columns; ) {
  151. packetHeader=*(p++);
  152. packetSize = 1 + (packetHeader & 0x7f);
  153. if (packetHeader & 0x80) { // run-length packet
  154. switch ( header.pixel_size )
  155. {
  156. case 24:
  157. blue = *(p++);
  158. green = *(p++);
  159. red = *(p++);
  160. alphabyte = 255;
  161. break;
  162. case 32:
  163. default:
  164. blue = *(p++);
  165. green = *(p++);
  166. red = *(p++);
  167. alphabyte = *(p++);
  168. break;
  169. }
  170. for(j=0;j<packetSize;j++)
  171. {
  172. *pixbuf++=red;
  173. *pixbuf++=green;
  174. *pixbuf++=blue;
  175. *pixbuf++=alphabyte;
  176. column++;
  177. if (column==columns) { // run spans across rows
  178. column=0;
  179. if (row>0)
  180. row--;
  181. else
  182. goto breakOut;
  183. pixbuf = *rawImage + row*columns*4;
  184. }
  185. }
  186. }
  187. else
  188. { // non run-length packet
  189. for(j=0;j<packetSize;j++) {
  190. switch (header.pixel_size) {
  191. case 24:
  192. blue = *(p++);
  193. green = *(p++);
  194. red = *(p++);
  195. *pixbuf++ = red;
  196. *pixbuf++ = green;
  197. *pixbuf++ = blue;
  198. *pixbuf++ = 255;
  199. break;
  200. case 32:
  201. blue = *(p++);
  202. green = *(p++);
  203. red = *(p++);
  204. alphabyte = *(p++);
  205. *pixbuf++ = red;
  206. *pixbuf++ = green;
  207. *pixbuf++ = blue;
  208. *pixbuf++ = alphabyte;
  209. break;
  210. }
  211. column++;
  212. if (column==columns)
  213. { // pixel packet run spans across rows
  214. column=0;
  215. if (row>0)
  216. row--;
  217. else
  218. goto breakOut;
  219. pixbuf = *rawImage + row*columns*4;
  220. }
  221. }
  222. }
  223. }
  224. breakOut:;
  225. }
  226. }
  227. return true;
  228. }
  229. void WriteTGA( const char *pchFileName, void *rgba, int wide, int tall )
  230. {
  231. _TargaHeader header;
  232. memset( &header, 0x0, sizeof(header) );
  233. header.width = wide;
  234. header.height = tall;
  235. header.image_type = 2;
  236. header.pixel_size = 32;
  237. FILE *fp = fopen( pchFileName, "w+" );
  238. fwrite( &header, 1, sizeof(header), fp );
  239. fwrite( rgba, 1, wide*tall*4, fp );
  240. fclose(fp);
  241. }