1
//========================================================================
2
// GLFW - An OpenGL framework
6
// WWW: http://glfw.sourceforge.net
7
//------------------------------------------------------------------------
8
// Copyright (c) 2002-2006 Camilla Berglund
10
// This software is provided 'as-is', without any express or implied
11
// warranty. In no event will the authors be held liable for any damages
12
// arising from the use of this software.
14
// Permission is granted to anyone to use this software for any purpose,
15
// including commercial applications, and to alter it and redistribute it
16
// freely, subject to the following restrictions:
18
// 1. The origin of this software must not be misrepresented; you must not
19
// claim that you wrote the original software. If you use this software
20
// in a product, an acknowledgment in the product documentation would
21
// be appreciated but is not required.
23
// 2. Altered source versions must be plainly marked as such, and must not
24
// be misrepresented as being the original software.
26
// 3. This notice may not be removed or altered from any source
29
//========================================================================
31
//========================================================================
34
// TGA format image file loader. This module supports version 1 Targa
35
// images, with these restrictions:
36
// - Pixel format may only be 8, 24 or 32 bits
37
// - Colormaps must be no longer than 256 entries
39
//========================================================================
45
//************************************************************************
46
//**** GLFW internal functions & declarations ****
47
//************************************************************************
49
//========================================================================
50
// TGA file header information
51
//========================================================================
55
int cmaptype; // 1 byte
56
int imagetype; // 1 byte
57
int cmapfirstidx; // 2 bytes
58
int cmaplen; // 2 bytes
59
int cmapentrysize; // 1 byte
60
int xorigin; // 2 bytes
61
int yorigin; // 2 bytes
63
int height; // 2 bytes
64
int bitsperpixel; // 1 byte
65
int imageinfo; // 1 byte
66
int _alphabits; // (derived from imageinfo)
67
int _origin; // (derived from imageinfo)
70
#define _TGA_CMAPTYPE_NONE 0
71
#define _TGA_CMAPTYPE_PRESENT 1
73
#define _TGA_IMAGETYPE_NONE 0
74
#define _TGA_IMAGETYPE_CMAP 1
75
#define _TGA_IMAGETYPE_TC 2
76
#define _TGA_IMAGETYPE_GRAY 3
77
#define _TGA_IMAGETYPE_CMAP_RLE 9
78
#define _TGA_IMAGETYPE_TC_RLE 10
79
#define _TGA_IMAGETYPE_GRAY_RLE 11
81
#define _TGA_IMAGEINFO_ALPHA_MASK 0x0f
82
#define _TGA_IMAGEINFO_ALPHA_SHIFT 0
83
#define _TGA_IMAGEINFO_ORIGIN_MASK 0x30
84
#define _TGA_IMAGEINFO_ORIGIN_SHIFT 4
86
#define _TGA_ORIGIN_BL 0
87
#define _TGA_ORIGIN_BR 1
88
#define _TGA_ORIGIN_UL 2
89
#define _TGA_ORIGIN_UR 3
92
//========================================================================
93
// _glfwReadTGAHeader() - Read TGA file header (and check that it is
95
//========================================================================
97
static int _glfwReadTGAHeader( _GLFWstream *s, _tga_header_t *h )
99
unsigned char buf[ 18 ];
102
// Read TGA file header from file
103
pos = _glfwTellStream( s );
104
_glfwReadStream( s, buf, 18 );
106
// Interpret header (endian independent parsing)
107
h->idlen = (int) buf[0];
108
h->cmaptype = (int) buf[1];
109
h->imagetype = (int) buf[2];
110
h->cmapfirstidx = (int) buf[3] | (((int) buf[4]) << 8);
111
h->cmaplen = (int) buf[5] | (((int) buf[6]) << 8);
112
h->cmapentrysize = (int) buf[7];
113
h->xorigin = (int) buf[8] | (((int) buf[9]) << 8);
114
h->yorigin = (int) buf[10] | (((int) buf[11]) << 8);
115
h->width = (int) buf[12] | (((int) buf[13]) << 8);
116
h->height = (int) buf[14] | (((int) buf[15]) << 8);
117
h->bitsperpixel = (int) buf[16];
118
h->imageinfo = (int) buf[17];
120
// Extract alphabits and origin information
121
h->_alphabits = (int) (h->imageinfo & _TGA_IMAGEINFO_ALPHA_MASK) >>
122
_TGA_IMAGEINFO_ALPHA_SHIFT;
123
h->_origin = (int) (h->imageinfo & _TGA_IMAGEINFO_ORIGIN_MASK) >>
124
_TGA_IMAGEINFO_ORIGIN_SHIFT;
126
// Validate TGA header (is this a TGA file?)
127
if( (h->cmaptype == 0 || h->cmaptype == 1) &&
128
((h->imagetype >= 1 && h->imagetype <= 3) ||
129
(h->imagetype >= 9 && h->imagetype <= 11)) &&
130
(h->bitsperpixel == 8 || h->bitsperpixel == 24 ||
131
h->bitsperpixel == 32) )
134
_glfwSeekStream( s, h->idlen, SEEK_CUR );
136
// Indicate that the TGA header was valid
141
// Restore file position
142
_glfwSeekStream( s, pos, SEEK_SET );
144
// Indicate that the TGA header was invalid
149
//========================================================================
150
// _glfwReadTGA_RLE() - Read Run-Length Encoded data
151
//========================================================================
153
static void _glfwReadTGA_RLE( unsigned char *buf, int size, int bpp,
156
int repcount, bytes, k, n;
157
unsigned char pixel[ 4 ];
168
// Get repetition count
169
_glfwReadStream( s, &c, 1 );
170
repcount = (unsigned int) c;
171
bytes = ((repcount & 127) + 1) * bpp;
177
// Run-Length packet?
180
_glfwReadStream( s, pixel, bpp );
181
for( n = 0; n < (repcount & 127) + 1; n ++ )
183
for( k = 0; k < bpp; k ++ )
185
*buf ++ = pixel[ k ];
192
_glfwReadStream( s, buf, bytes );
201
//========================================================================
202
// _glfwReadTGA() - Read a TGA image from a file
203
//========================================================================
205
int _glfwReadTGA( _GLFWstream *s, GLFWimage *img, int flags )
208
unsigned char *cmap, *pix, tmp, *src, *dst;
209
int cmapsize, pixsize, pixsize2;
210
int bpp, bpp2, k, m, n, swapx, swapy;
213
if( !_glfwReadTGAHeader( s, &h ) )
218
// Is there a colormap?
219
cmapsize = (h.cmaptype == _TGA_CMAPTYPE_PRESENT ? 1 : 0) * h.cmaplen *
220
((h.cmapentrysize+7) / 8);
223
// Is it a colormap that we can handle?
224
if( (h.cmapentrysize != 24 && h.cmapentrysize != 32) ||
225
h.cmaplen == 0 || h.cmaplen > 256 )
230
// Allocate memory for colormap
231
cmap = (unsigned char *) malloc( cmapsize );
237
// Read colormap from file
238
_glfwReadStream( s, cmap, cmapsize );
245
// Size of pixel data
246
pixsize = h.width * h.height * ((h.bitsperpixel + 7) / 8);
248
// Bytes per pixel (pixel data - unexpanded)
249
bpp = (h.bitsperpixel + 7) / 8;
251
// Bytes per pixel (expanded pixels - not colormap indeces)
254
bpp2 = (h.cmapentrysize + 7) / 8;
261
// For colormaped images, the RGB/RGBA image data may use more memory
262
// than the stored pixel data
263
pixsize2 = h.width * h.height * bpp2;
265
// Allocate memory for pixel data
266
pix = (unsigned char *) malloc( pixsize2 );
276
// Read pixel data from file
277
if( h.imagetype >= _TGA_IMAGETYPE_CMAP_RLE )
279
_glfwReadTGA_RLE( pix, pixsize, bpp, s );
283
_glfwReadStream( s, pix, pixsize );
286
// If the image origin is not what we want, re-arrange the pixels
310
if( (swapy && !(flags & GLFW_ORIGIN_UL_BIT)) ||
311
(!swapy && (flags & GLFW_ORIGIN_UL_BIT)) )
314
dst = &pix[ (h.height-1)*h.width*bpp ];
315
for( n = 0; n < h.height/2; n ++ )
317
for( m = 0; m < h.width ; m ++ )
319
for( k = 0; k < bpp; k ++ )
326
dst -= 2*h.width*bpp;
332
dst = &pix[ (h.width-1)*bpp ];
333
for( n = 0; n < h.height; n ++ )
335
for( m = 0; m < h.width/2 ; m ++ )
337
for( k = 0; k < bpp; k ++ )
345
src += ((h.width+1)/2)*bpp;
346
dst += ((3*h.width+1)/2)*bpp;
350
// Convert BGR/BGRA to RGB/RGBA, and optionally colormap indeces to
354
// Convert colormap pixel format (BGR -> RGB or BGRA -> RGBA)
355
if( bpp2 == 3 || bpp2 == 4 )
357
for( n = 0; n < h.cmaplen; n ++ )
359
tmp = cmap[ n*bpp2 ];
360
cmap[ n*bpp2 ] = cmap[ n*bpp2 + 2 ];
361
cmap[ n*bpp2 + 2 ] = tmp;
365
// Convert pixel data to RGB/RGBA data
366
for( m = h.width * h.height - 1; m >= 0; m -- )
369
for( k = 0; k < bpp2; k ++ )
371
pix[ m*bpp2 + k ] = cmap[ n*bpp2 + k ];
375
// Free memory for colormap (it's not needed anymore)
380
// Convert image pixel format (BGR -> RGB or BGRA -> RGBA)
381
if( bpp2 == 3 || bpp2 == 4 )
385
for( n = 0; n < h.height * h.width; n ++ )
396
// Fill out GLFWimage struct (the Format field will be set by
398
img->Width = h.width;
399
img->Height = h.height;
400
img->BytesPerPixel = bpp2;