2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
25 /* This is a Targa image file loading framework */
31 #include "SDL_endian.h"
33 #include "SDL_image.h"
38 * A TGA loader for the SDL library
39 * Supports: Reading 8, 15, 16, 24 and 32bpp images, with alpha or colourkey,
40 * uncompressed or RLE encoded.
42 * 2000-06-10 Mattias Engdegård <f91-men@nada.kth.se>: initial version
43 * 2000-06-26 Mattias Engdegård <f91-men@nada.kth.se>: read greyscale TGAs
44 * 2000-08-09 Mattias Engdegård <f91-men@nada.kth.se>: alpha inversion removed
48 Uint8 infolen; /* length of info field */
49 Uint8 has_cmap; /* 1 if image has colormap, 0 otherwise */
52 Uint8 cmap_start[2]; /* index of first colormap entry */
53 Uint8 cmap_len[2]; /* number of entries in colormap */
54 Uint8 cmap_bits; /* bits per colormap entry */
56 Uint8 yorigin[2]; /* image origin (ignored here) */
58 Uint8 width[2]; /* image size */
60 Uint8 pixel_bits; /* bits/pixel */
68 TGA_TYPE_RLE_INDEXED = 9,
69 TGA_TYPE_RLE_RGB = 10,
73 #define TGA_INTERLEAVE_MASK 0xc0
74 #define TGA_INTERLEAVE_NONE 0x00
75 #define TGA_INTERLEAVE_2WAY 0x40
76 #define TGA_INTERLEAVE_4WAY 0x80
78 #define TGA_ORIGIN_MASK 0x30
79 #define TGA_ORIGIN_LEFT 0x00
80 #define TGA_ORIGIN_RIGHT 0x10
81 #define TGA_ORIGIN_LOWER 0x00
82 #define TGA_ORIGIN_UPPER 0x20
84 /* read/write unaligned little-endian 16-bit ints */
85 #define LE16(p) ((p)[0] + ((p)[1] << 8))
86 #define SETLE16(p, v) ((p)[0] = (v), (p)[1] = (v) >> 8)
88 /* Load a TGA type image from an SDL datasource */
89 SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src)
92 const char *error = NULL;
100 SDL_Surface *img = NULL;
101 Uint32 rmask, gmask, bmask, amask;
110 /* The error message has been set in SDL_RWFromFile */
113 start = SDL_RWtell(src);
115 if(!SDL_RWread(src, &hdr, sizeof(hdr), 1)) {
116 error = "Error reading TGA data";
119 ncols = LE16(hdr.cmap_len);
121 case TGA_TYPE_RLE_INDEXED:
124 case TGA_TYPE_INDEXED:
125 if(!hdr.has_cmap || hdr.pixel_bits != 8 || ncols > 256)
130 case TGA_TYPE_RLE_RGB:
137 case TGA_TYPE_RLE_BW:
141 if(hdr.pixel_bits != 8)
143 /* Treat greyscale as 8bpp indexed images */
151 bpp = (hdr.pixel_bits + 7) >> 3;
152 rmask = gmask = bmask = amask = 0;
153 switch(hdr.pixel_bits) {
162 /* 15 and 16bpp both seem to use 5 bits/plane. The extra alpha bit
163 is ignored for now. */
173 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
174 int s = alpha ? 0 : 8;
175 amask = 0x000000ff >> s;
176 rmask = 0x0000ff00 >> s;
177 gmask = 0x00ff0000 >> s;
178 bmask = 0xff000000 >> s;
180 amask = alpha ? 0xff000000 : 0;
191 if((hdr.flags & TGA_INTERLEAVE_MASK) != TGA_INTERLEAVE_NONE
192 || hdr.flags & TGA_ORIGIN_RIGHT) {
196 SDL_RWseek(src, hdr.infolen, RW_SEEK_CUR); /* skip info field */
199 h = LE16(hdr.height);
200 img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
202 rmask, gmask, bmask, amask);
204 error = "Out of memory";
209 int palsiz = ncols * ((hdr.cmap_bits + 7) >> 3);
210 if(indexed && !grey) {
211 Uint8 *pal = malloc(palsiz), *p = pal;
212 SDL_Color *colors = img->format->palette->colors;
213 img->format->palette->ncolors = ncols;
214 SDL_RWread(src, pal, palsiz, 1);
215 for(i = 0; i < ncols; i++) {
216 switch(hdr.cmap_bits) {
220 Uint16 c = p[0] + (p[1] << 8);
222 colors[i].r = (c >> 7) & 0xf8;
223 colors[i].g = (c >> 2) & 0xf8;
224 colors[i].b = c << 3;
232 if(hdr.cmap_bits == 32 && *p++ < 128)
239 SDL_SetColorKey(img, SDL_SRCCOLORKEY, ckey);
241 /* skip unneeded colormap */
242 SDL_RWseek(src, palsiz, RW_SEEK_CUR);
247 SDL_Color *colors = img->format->palette->colors;
248 for(i = 0; i < 256; i++)
249 colors[i].r = colors[i].g = colors[i].b = i;
250 img->format->palette->ncolors = 256;
253 if(hdr.flags & TGA_ORIGIN_UPPER) {
258 dst = (Uint8 *)img->pixels + (h - 1) * img->pitch;
261 /* The RLE decoding code is slightly convoluted since we can't rely on
262 spans not to wrap across scan lines */
264 for(i = 0; i < h; i++) {
274 SDL_RWread(src, dst + x * bpp, n * bpp, 1);
285 memcpy(dst + x * bpp, &pixel, bpp);
292 SDL_RWread(src, &c, 1, 1);
294 SDL_RWread(src, &pixel, bpp, 1);
295 rep = (c & 0x7f) + 1;
302 SDL_RWread(src, dst, w * bpp, 1);
304 if(SDL_BYTEORDER == SDL_BIG_ENDIAN && bpp == 2) {
305 /* swap byte order */
307 Uint16 *p = (Uint16 *)dst;
308 for(x = 0; x < w; x++)
309 p[x] = SDL_Swap16(p[x]);
316 error = "Unsupported TGA format";
319 SDL_RWseek(src, start, RW_SEEK_SET);
321 SDL_FreeSurface(img);
329 /* dummy TGA load routine */
330 SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src)
335 #endif /* LOAD_TGA */
337 #endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */