IMG_tga.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. SDL_image: An example image loading library for use with SDL
  3. Copyright (C) 1999, 2000, 2001 Sam Lantinga
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. Sam Lantinga
  16. slouken@libsdl.org
  17. */
  18. /* $Id: IMG_tga.c,v 1.1 2004/07/21 16:24:11 paigoddess Exp $ */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include "SDL_endian.h"
  23. #include "SDL_image.h"
  24. /*
  25. * A TGA loader for the SDL library
  26. * Supports: Reading 8, 15, 16, 24 and 32bpp images, with alpha or colourkey,
  27. * uncompressed or RLE encoded.
  28. *
  29. * 2000-06-10 Mattias Engdegård <f91-men@nada.kth.se>: initial version
  30. * 2000-06-26 Mattias Engdegård <f91-men@nada.kth.se>: read greyscale TGAs
  31. * 2000-08-09 Mattias Engdegård <f91-men@nada.kth.se>: alpha inversion removed
  32. */
  33. struct TGAheader {
  34. Uint8 infolen; /* length of info field */
  35. Uint8 has_cmap; /* 1 if image has colormap, 0 otherwise */
  36. Uint8 type;
  37. Uint8 cmap_start[2]; /* index of first colormap entry */
  38. Uint8 cmap_len[2]; /* number of entries in colormap */
  39. Uint8 cmap_bits; /* bits per colormap entry */
  40. Uint8 yorigin[2]; /* image origin (ignored here) */
  41. Uint8 xorigin[2];
  42. Uint8 width[2]; /* image size */
  43. Uint8 height[2];
  44. Uint8 pixel_bits; /* bits/pixel */
  45. Uint8 flags;
  46. };
  47. enum tga_type {
  48. TGA_TYPE_INDEXED = 1,
  49. TGA_TYPE_RGB = 2,
  50. TGA_TYPE_BW = 3,
  51. TGA_TYPE_RLE_INDEXED = 9,
  52. TGA_TYPE_RLE_RGB = 10,
  53. TGA_TYPE_RLE_BW = 11
  54. };
  55. #define TGA_INTERLEAVE_MASK 0xc0
  56. #define TGA_INTERLEAVE_NONE 0x00
  57. #define TGA_INTERLEAVE_2WAY 0x40
  58. #define TGA_INTERLEAVE_4WAY 0x80
  59. #define TGA_ORIGIN_MASK 0x30
  60. #define TGA_ORIGIN_LEFT 0x00
  61. #define TGA_ORIGIN_RIGHT 0x10
  62. #define TGA_ORIGIN_LOWER 0x00
  63. #define TGA_ORIGIN_UPPER 0x20
  64. /* read/write unaligned little-endian 16-bit ints */
  65. #define LE16(p) ((p)[0] + ((p)[1] << 8))
  66. #define SETLE16(p, v) ((p)[0] = (v), (p)[1] = (v) >> 8)
  67. static void unsupported(void)
  68. {
  69. IMG_SetError("unsupported TGA format");
  70. }
  71. /* Load a TGA type image from an SDL datasource */
  72. SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src)
  73. {
  74. struct TGAheader hdr;
  75. int rle = 0;
  76. int alpha = 0;
  77. int indexed = 0;
  78. int grey = 0;
  79. int ckey = -1;
  80. int ncols, w, h;
  81. SDL_Surface *img;
  82. Uint32 rmask, gmask, bmask, amask;
  83. Uint8 *dst;
  84. int i;
  85. int bpp;
  86. int lstep;
  87. Uint32 pixel;
  88. int count, rep;
  89. if(!SDL_RWread(src, &hdr, sizeof(hdr), 1))
  90. goto error;
  91. ncols = LE16(hdr.cmap_len);
  92. switch(hdr.type) {
  93. case TGA_TYPE_RLE_INDEXED:
  94. rle = 1;
  95. /* fallthrough */
  96. case TGA_TYPE_INDEXED:
  97. if(!hdr.has_cmap || hdr.pixel_bits != 8 || ncols > 256)
  98. goto error;
  99. indexed = 1;
  100. break;
  101. case TGA_TYPE_RLE_RGB:
  102. rle = 1;
  103. /* fallthrough */
  104. case TGA_TYPE_RGB:
  105. indexed = 0;
  106. break;
  107. case TGA_TYPE_RLE_BW:
  108. rle = 1;
  109. /* fallthrough */
  110. case TGA_TYPE_BW:
  111. if(hdr.pixel_bits != 8)
  112. goto error;
  113. /* Treat greyscale as 8bpp indexed images */
  114. indexed = grey = 1;
  115. break;
  116. default:
  117. unsupported();
  118. return NULL;
  119. }
  120. bpp = (hdr.pixel_bits + 7) >> 3;
  121. rmask = gmask = bmask = amask = 0;
  122. switch(hdr.pixel_bits) {
  123. case 8:
  124. if(!indexed) {
  125. unsupported();
  126. return NULL;
  127. }
  128. break;
  129. case 15:
  130. case 16:
  131. /* 15 and 16bpp both seem to use 5 bits/plane. The extra alpha bit
  132. is ignored for now. */
  133. rmask = 0x7c00;
  134. gmask = 0x03e0;
  135. bmask = 0x001f;
  136. break;
  137. case 32:
  138. alpha = 1;
  139. /* fallthrough */
  140. case 24:
  141. if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
  142. int s = alpha ? 0 : 8;
  143. amask = 0x000000ff >> s;
  144. rmask = 0x0000ff00 >> s;
  145. gmask = 0x00ff0000 >> s;
  146. bmask = 0xff000000 >> s;
  147. } else {
  148. amask = alpha ? 0xff000000 : 0;
  149. rmask = 0x00ff0000;
  150. gmask = 0x0000ff00;
  151. bmask = 0x000000ff;
  152. }
  153. break;
  154. default:
  155. unsupported();
  156. return NULL;
  157. }
  158. if((hdr.flags & TGA_INTERLEAVE_MASK) != TGA_INTERLEAVE_NONE
  159. || hdr.flags & TGA_ORIGIN_RIGHT) {
  160. unsupported();
  161. return NULL;
  162. }
  163. SDL_RWseek(src, hdr.infolen, SEEK_CUR); /* skip info field */
  164. w = LE16(hdr.width);
  165. h = LE16(hdr.height);
  166. img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
  167. bpp * 8,
  168. rmask, gmask, bmask, amask);
  169. if(hdr.has_cmap) {
  170. int palsiz = ncols * ((hdr.cmap_bits + 7) >> 3);
  171. if(indexed && !grey) {
  172. Uint8 *pal = (Uint8*)malloc(palsiz), *p = pal;
  173. SDL_Color *colors = img->format->palette->colors;
  174. img->format->palette->ncolors = ncols;
  175. SDL_RWread(src, pal, palsiz, 1);
  176. for(i = 0; i < ncols; i++) {
  177. switch(hdr.cmap_bits) {
  178. case 15:
  179. case 16:
  180. {
  181. Uint16 c = p[0] + (p[1] << 8);
  182. p += 2;
  183. colors[i].r = (c >> 7) & 0xf8;
  184. colors[i].g = (c >> 2) & 0xf8;
  185. colors[i].b = c << 3;
  186. }
  187. break;
  188. case 24:
  189. case 32:
  190. colors[i].b = *p++;
  191. colors[i].g = *p++;
  192. colors[i].r = *p++;
  193. if(hdr.cmap_bits == 32 && *p++ < 128)
  194. ckey = i;
  195. break;
  196. }
  197. }
  198. free(pal);
  199. if(ckey >= 0)
  200. SDL_SetColorKey(img, SDL_SRCCOLORKEY, ckey);
  201. } else {
  202. /* skip unneeded colormap */
  203. SDL_RWseek(src, palsiz, SEEK_CUR);
  204. }
  205. }
  206. if(grey) {
  207. SDL_Color *colors = img->format->palette->colors;
  208. for(i = 0; i < 256; i++)
  209. colors[i].r = colors[i].g = colors[i].b = i;
  210. img->format->palette->ncolors = 256;
  211. }
  212. if(hdr.flags & TGA_ORIGIN_UPPER) {
  213. lstep = img->pitch;
  214. dst = (Uint8*)img->pixels;
  215. } else {
  216. lstep = -img->pitch;
  217. dst = (Uint8 *)img->pixels + (h - 1) * img->pitch;
  218. }
  219. /* The RLE decoding code is slightly convoluted since we can't rely on
  220. spans not to wrap across scan lines */
  221. count = rep = 0;
  222. for(i = 0; i < h; i++) {
  223. if(rle) {
  224. int x = 0;
  225. for(;;) {
  226. Uint8 c;
  227. if(count) {
  228. int n = count;
  229. if(n > w - x)
  230. n = w - x;
  231. SDL_RWread(src, dst + x * bpp, n * bpp, 1);
  232. count -= n;
  233. x += n;
  234. if(x == w)
  235. break;
  236. } else if(rep) {
  237. int n = rep;
  238. if(n > w - x)
  239. n = w - x;
  240. rep -= n;
  241. while(n--) {
  242. memcpy(dst + x * bpp, &pixel, bpp);
  243. x++;
  244. }
  245. if(x == w)
  246. break;
  247. }
  248. SDL_RWread(src, &c, 1, 1);
  249. if(c & 0x80) {
  250. SDL_RWread(src, &pixel, bpp, 1);
  251. rep = (c & 0x7f) + 1;
  252. } else {
  253. count = c + 1;
  254. }
  255. }
  256. } else {
  257. SDL_RWread(src, dst, w * bpp, 1);
  258. }
  259. if(SDL_BYTEORDER == SDL_BIG_ENDIAN && bpp == 2) {
  260. /* swap byte order */
  261. int x;
  262. Uint16 *p = (Uint16 *)dst;
  263. for(x = 0; x < w; x++)
  264. p[x] = SDL_Swap16(p[x]);
  265. }
  266. dst += lstep;
  267. }
  268. return img;
  269. error:
  270. IMG_SetError("Error reading TGA data");
  271. return NULL;
  272. }