From 2acf691603cb0fb7c8b580befbc7be49b9300e53 Mon Sep 17 00:00:00 2001 From: ludwig Date: Thu, 14 Feb 2008 11:13:18 +0000 Subject: move all image decoders into separate files git-svn-id: svn://svn.icculus.org/quake3/trunk@1257 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/renderer/tr_image_tga.c | 317 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 code/renderer/tr_image_tga.c (limited to 'code/renderer/tr_image_tga.c') diff --git a/code/renderer/tr_image_tga.c b/code/renderer/tr_image_tga.c new file mode 100644 index 0000000..b375404 --- /dev/null +++ b/code/renderer/tr_image_tga.c @@ -0,0 +1,317 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake III Arena source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "tr_local.h" + +/* +======================================================================== + +TGA files are used for 24/32 bit images + +======================================================================== +*/ + +typedef struct _TargaHeader { + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; +} TargaHeader; + +void LoadTGA ( const char *name, byte **pic, int *width, int *height) +{ + unsigned columns, rows, numPixels; + byte *pixbuf; + int row, column; + byte *buf_p; + byte *end; + byte *buffer = NULL; + TargaHeader targa_header; + byte *targa_rgba; + int length; + + *pic = NULL; + + if(width) + *width = 0; + if(height) + *height = 0; + + // + // load the file + // + length = ri.FS_ReadFile ( ( char * ) name, (void **)&buffer); + if (!buffer || length < 0) { + return; + } + + if(length < 18) + { + ri.Error( ERR_DROP, "LoadTGA: header too short (%s)\n", name ); + } + + buf_p = buffer; + end = buffer + length; + + targa_header.id_length = buf_p[0]; + targa_header.colormap_type = buf_p[1]; + targa_header.image_type = buf_p[2]; + + memcpy(&targa_header.colormap_index, &buf_p[3], 2); + memcpy(&targa_header.colormap_length, &buf_p[5], 2); + targa_header.colormap_size = buf_p[7]; + memcpy(&targa_header.x_origin, &buf_p[8], 2); + memcpy(&targa_header.y_origin, &buf_p[10], 2); + memcpy(&targa_header.width, &buf_p[12], 2); + memcpy(&targa_header.height, &buf_p[14], 2); + targa_header.pixel_size = buf_p[16]; + targa_header.attributes = buf_p[17]; + + targa_header.colormap_index = LittleShort(targa_header.colormap_index); + targa_header.colormap_length = LittleShort(targa_header.colormap_length); + targa_header.x_origin = LittleShort(targa_header.x_origin); + targa_header.y_origin = LittleShort(targa_header.y_origin); + targa_header.width = LittleShort(targa_header.width); + targa_header.height = LittleShort(targa_header.height); + + buf_p += 18; + + if (targa_header.image_type!=2 + && targa_header.image_type!=10 + && targa_header.image_type != 3 ) + { + ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n"); + } + + if ( targa_header.colormap_type != 0 ) + { + ri.Error( ERR_DROP, "LoadTGA: colormaps not supported\n" ); + } + + if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) + { + ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); + } + + columns = targa_header.width; + rows = targa_header.height; + numPixels = columns * rows * 4; + + if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows) + { + ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size\n", name); + } + + + targa_rgba = ri.Malloc (numPixels); + + if (targa_header.id_length != 0) + { + if (buf_p + targa_header.id_length > end) + ri.Error( ERR_DROP, "LoadTGA: header too short (%s)\n", name ); + + buf_p += targa_header.id_length; // skip TARGA image comment + } + + if ( targa_header.image_type==2 || targa_header.image_type == 3 ) + { + if(buf_p + columns*rows*targa_header.pixel_size/8 > end) + { + ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name); + } + + // Uncompressed RGB or gray scale image + for(row=rows-1; row>=0; row--) + { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column end) + ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name); + packetHeader= *buf_p++; + packetSize = 1 + (packetHeader & 0x7f); + if (packetHeader & 0x80) { // run-length packet + if(buf_p + targa_header.pixel_size/8 > end) + ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name); + switch (targa_header.pixel_size) { + case 24: + blue = *buf_p++; + green = *buf_p++; + red = *buf_p++; + alphabyte = 255; + break; + case 32: + blue = *buf_p++; + green = *buf_p++; + red = *buf_p++; + alphabyte = *buf_p++; + break; + default: + ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); + break; + } + + for(j=0;j0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + else { // non run-length packet + + if(buf_p + targa_header.pixel_size/8*packetSize > end) + ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name); + for(j=0;j0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + } + breakOut:; + } + } + +#if 0 + // TTimo: this is the chunk of code to ensure a behavior that meets TGA specs + // bit 5 set => top-down + if (targa_header.attributes & 0x20) { + unsigned char *flip = (unsigned char*)malloc (columns*4); + unsigned char *src, *dst; + + for (row = 0; row < rows/2; row++) { + src = targa_rgba + row * 4 * columns; + dst = targa_rgba + (rows - row - 1) * 4 * columns; + + memcpy (flip, src, columns*4); + memcpy (src, dst, columns*4); + memcpy (dst, flip, columns*4); + } + free (flip); + } +#endif + // instead we just print a warning + if (targa_header.attributes & 0x20) { + ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name); + } + + if (width) + *width = columns; + if (height) + *height = rows; + + *pic = targa_rgba; + + ri.FS_FreeFile (buffer); +} -- cgit v1.2.3