diff options
Diffstat (limited to 'src/engine/external/glfw/lib/tga.c')
| -rw-r--r-- | src/engine/external/glfw/lib/tga.c | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/src/engine/external/glfw/lib/tga.c b/src/engine/external/glfw/lib/tga.c new file mode 100644 index 00000000..51e73844 --- /dev/null +++ b/src/engine/external/glfw/lib/tga.c @@ -0,0 +1,405 @@ +//======================================================================== +// GLFW - An OpenGL framework +// File: tga.c +// Platform: Any +// API version: 2.6 +// WWW: http://glfw.sourceforge.net +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +//======================================================================== +// Description: +// +// TGA format image file loader. This module supports version 1 Targa +// images, with these restrictions: +// - Pixel format may only be 8, 24 or 32 bits +// - Colormaps must be no longer than 256 entries +// +//======================================================================== + + +#include "internal.h" + + +//************************************************************************ +//**** GLFW internal functions & declarations **** +//************************************************************************ + +//======================================================================== +// TGA file header information +//======================================================================== + +typedef struct { + int idlen; // 1 byte + int cmaptype; // 1 byte + int imagetype; // 1 byte + int cmapfirstidx; // 2 bytes + int cmaplen; // 2 bytes + int cmapentrysize; // 1 byte + int xorigin; // 2 bytes + int yorigin; // 2 bytes + int width; // 2 bytes + int height; // 2 bytes + int bitsperpixel; // 1 byte + int imageinfo; // 1 byte + int _alphabits; // (derived from imageinfo) + int _origin; // (derived from imageinfo) +} _tga_header_t; + +#define _TGA_CMAPTYPE_NONE 0 +#define _TGA_CMAPTYPE_PRESENT 1 + +#define _TGA_IMAGETYPE_NONE 0 +#define _TGA_IMAGETYPE_CMAP 1 +#define _TGA_IMAGETYPE_TC 2 +#define _TGA_IMAGETYPE_GRAY 3 +#define _TGA_IMAGETYPE_CMAP_RLE 9 +#define _TGA_IMAGETYPE_TC_RLE 10 +#define _TGA_IMAGETYPE_GRAY_RLE 11 + +#define _TGA_IMAGEINFO_ALPHA_MASK 0x0f +#define _TGA_IMAGEINFO_ALPHA_SHIFT 0 +#define _TGA_IMAGEINFO_ORIGIN_MASK 0x30 +#define _TGA_IMAGEINFO_ORIGIN_SHIFT 4 + +#define _TGA_ORIGIN_BL 0 +#define _TGA_ORIGIN_BR 1 +#define _TGA_ORIGIN_UL 2 +#define _TGA_ORIGIN_UR 3 + + +//======================================================================== +// _glfwReadTGAHeader() - Read TGA file header (and check that it is +// valid) +//======================================================================== + +static int _glfwReadTGAHeader( _GLFWstream *s, _tga_header_t *h ) +{ + unsigned char buf[ 18 ]; + int pos; + + // Read TGA file header from file + pos = _glfwTellStream( s ); + _glfwReadStream( s, buf, 18 ); + + // Interpret header (endian independent parsing) + h->idlen = (int) buf[0]; + h->cmaptype = (int) buf[1]; + h->imagetype = (int) buf[2]; + h->cmapfirstidx = (int) buf[3] | (((int) buf[4]) << 8); + h->cmaplen = (int) buf[5] | (((int) buf[6]) << 8); + h->cmapentrysize = (int) buf[7]; + h->xorigin = (int) buf[8] | (((int) buf[9]) << 8); + h->yorigin = (int) buf[10] | (((int) buf[11]) << 8); + h->width = (int) buf[12] | (((int) buf[13]) << 8); + h->height = (int) buf[14] | (((int) buf[15]) << 8); + h->bitsperpixel = (int) buf[16]; + h->imageinfo = (int) buf[17]; + + // Extract alphabits and origin information + h->_alphabits = (int) (h->imageinfo & _TGA_IMAGEINFO_ALPHA_MASK) >> + _TGA_IMAGEINFO_ALPHA_SHIFT; + h->_origin = (int) (h->imageinfo & _TGA_IMAGEINFO_ORIGIN_MASK) >> + _TGA_IMAGEINFO_ORIGIN_SHIFT; + + // Validate TGA header (is this a TGA file?) + if( (h->cmaptype == 0 || h->cmaptype == 1) && + ((h->imagetype >= 1 && h->imagetype <= 3) || + (h->imagetype >= 9 && h->imagetype <= 11)) && + (h->bitsperpixel == 8 || h->bitsperpixel == 24 || + h->bitsperpixel == 32) ) + { + // Skip the ID field + _glfwSeekStream( s, h->idlen, SEEK_CUR ); + + // Indicate that the TGA header was valid + return GL_TRUE; + } + else + { + // Restore file position + _glfwSeekStream( s, pos, SEEK_SET ); + + // Indicate that the TGA header was invalid + return GL_FALSE; + } +} + +//======================================================================== +// _glfwReadTGA_RLE() - Read Run-Length Encoded data +//======================================================================== + +static void _glfwReadTGA_RLE( unsigned char *buf, int size, int bpp, + _GLFWstream *s ) +{ + int repcount, bytes, k, n; + unsigned char pixel[ 4 ]; + char c; + + // Dummy check + if( bpp > 4 ) + { + return; + } + + while( size > 0 ) + { + // Get repetition count + _glfwReadStream( s, &c, 1 ); + repcount = (unsigned int) c; + bytes = ((repcount & 127) + 1) * bpp; + if( size < bytes ) + { + bytes = size; + } + + // Run-Length packet? + if( repcount & 128 ) + { + _glfwReadStream( s, pixel, bpp ); + for( n = 0; n < (repcount & 127) + 1; n ++ ) + { + for( k = 0; k < bpp; k ++ ) + { + *buf ++ = pixel[ k ]; + } + } + } + else + { + // It's a Raw packet + _glfwReadStream( s, buf, bytes ); + buf += bytes; + } + + size -= bytes; + } +} + + +//======================================================================== +// _glfwReadTGA() - Read a TGA image from a file +//======================================================================== + +int _glfwReadTGA( _GLFWstream *s, GLFWimage *img, int flags ) +{ + _tga_header_t h; + unsigned char *cmap, *pix, tmp, *src, *dst; + int cmapsize, pixsize, pixsize2; + int bpp, bpp2, k, m, n, swapx, swapy; + + // Read TGA header + if( !_glfwReadTGAHeader( s, &h ) ) + { + return 0; + } + + // Is there a colormap? + cmapsize = (h.cmaptype == _TGA_CMAPTYPE_PRESENT ? 1 : 0) * h.cmaplen * + ((h.cmapentrysize+7) / 8); + if( cmapsize > 0 ) + { + // Is it a colormap that we can handle? + if( (h.cmapentrysize != 24 && h.cmapentrysize != 32) || + h.cmaplen == 0 || h.cmaplen > 256 ) + { + return 0; + } + + // Allocate memory for colormap + cmap = (unsigned char *) malloc( cmapsize ); + if( cmap == NULL ) + { + return 0; + } + + // Read colormap from file + _glfwReadStream( s, cmap, cmapsize ); + } + else + { + cmap = NULL; + } + + // Size of pixel data + pixsize = h.width * h.height * ((h.bitsperpixel + 7) / 8); + + // Bytes per pixel (pixel data - unexpanded) + bpp = (h.bitsperpixel + 7) / 8; + + // Bytes per pixel (expanded pixels - not colormap indeces) + if( cmap ) + { + bpp2 = (h.cmapentrysize + 7) / 8; + } + else + { + bpp2 = bpp; + } + + // For colormaped images, the RGB/RGBA image data may use more memory + // than the stored pixel data + pixsize2 = h.width * h.height * bpp2; + + // Allocate memory for pixel data + pix = (unsigned char *) malloc( pixsize2 ); + if( pix == NULL ) + { + if( cmap ) + { + free( cmap ); + } + return 0; + } + + // Read pixel data from file + if( h.imagetype >= _TGA_IMAGETYPE_CMAP_RLE ) + { + _glfwReadTGA_RLE( pix, pixsize, bpp, s ); + } + else + { + _glfwReadStream( s, pix, pixsize ); + } + + // If the image origin is not what we want, re-arrange the pixels + switch( h._origin ) + { + default: + case _TGA_ORIGIN_UL: + swapx = 0; + swapy = 1; + break; + + case _TGA_ORIGIN_BL: + swapx = 0; + swapy = 0; + break; + + case _TGA_ORIGIN_UR: + swapx = 1; + swapy = 1; + break; + + case _TGA_ORIGIN_BR: + swapx = 1; + swapy = 0; + break; + } + if( (swapy && !(flags & GLFW_ORIGIN_UL_BIT)) || + (!swapy && (flags & GLFW_ORIGIN_UL_BIT)) ) + { + src = pix; + dst = &pix[ (h.height-1)*h.width*bpp ]; + for( n = 0; n < h.height/2; n ++ ) + { + for( m = 0; m < h.width ; m ++ ) + { + for( k = 0; k < bpp; k ++ ) + { + tmp = *src; + *src ++ = *dst; + *dst ++ = tmp; + } + } + dst -= 2*h.width*bpp; + } + } + if( swapx ) + { + src = pix; + dst = &pix[ (h.width-1)*bpp ]; + for( n = 0; n < h.height; n ++ ) + { + for( m = 0; m < h.width/2 ; m ++ ) + { + for( k = 0; k < bpp; k ++ ) + { + tmp = *src; + *src ++ = *dst; + *dst ++ = tmp; + } + dst -= 2*bpp; + } + src += ((h.width+1)/2)*bpp; + dst += ((3*h.width+1)/2)*bpp; + } + } + + // Convert BGR/BGRA to RGB/RGBA, and optionally colormap indeces to + // RGB/RGBA values + if( cmap ) + { + // Convert colormap pixel format (BGR -> RGB or BGRA -> RGBA) + if( bpp2 == 3 || bpp2 == 4 ) + { + for( n = 0; n < h.cmaplen; n ++ ) + { + tmp = cmap[ n*bpp2 ]; + cmap[ n*bpp2 ] = cmap[ n*bpp2 + 2 ]; + cmap[ n*bpp2 + 2 ] = tmp; + } + } + + // Convert pixel data to RGB/RGBA data + for( m = h.width * h.height - 1; m >= 0; m -- ) + { + n = pix[ m ]; + for( k = 0; k < bpp2; k ++ ) + { + pix[ m*bpp2 + k ] = cmap[ n*bpp2 + k ]; + } + } + + // Free memory for colormap (it's not needed anymore) + free( cmap ); + } + else + { + // Convert image pixel format (BGR -> RGB or BGRA -> RGBA) + if( bpp2 == 3 || bpp2 == 4 ) + { + src = pix; + dst = &pix[ 2 ]; + for( n = 0; n < h.height * h.width; n ++ ) + { + tmp = *src; + *src = *dst; + *dst = tmp; + src += bpp2; + dst += bpp2; + } + } + } + + // Fill out GLFWimage struct (the Format field will be set by + // glfwReadImage) + img->Width = h.width; + img->Height = h.height; + img->BytesPerPixel = bpp2; + img->Data = pix; + + return 1; +} + |