diff options
Diffstat (limited to 'source/r_images.c')
-rw-r--r-- | source/r_images.c | 2290 |
1 files changed, 1106 insertions, 1184 deletions
diff --git a/source/r_images.c b/source/r_images.c index 5b92392..4c873bf 100644 --- a/source/r_images.c +++ b/source/r_images.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2003-2006 Andrey Nazarov +Copyright (C) 2003-2008 Andrey Nazarov Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -23,13 +23,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // images.c -- image reading and writing functions // -#include "config.h" +#include "com_local.h" #if USE_PNG #include <png.h> #endif -#if USE_JPEG +#if USE_JPG #if !USE_PNG #include <setjmp.h> #endif @@ -37,10 +37,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <jpeglib.h> #endif -#include "q_shared.h" -#include "com_public.h" -#include "q_files.h" #include "q_list.h" +#include "files.h" +#include "sys_public.h" #include "r_shared.h" /* @@ -51,189 +50,185 @@ PCX LOADING ================================================================= */ -// FIXME: get rid of this -#ifdef SOFTWARE_RENDERER -#define PCX_ALLOC( x ) R_Malloc( x ) -#define PCX_FREE( x ) com.Free( x ) -#else -#define PCX_ALLOC( x ) fs.AllocTempMem( w * h ) -#define PCX_FREE( x ) fs.FreeFile( x ) -#endif +#include "d_pcx.h" /* ============== -Image_LoadPCX +IMG_LoadPCX ============== */ -void Image_LoadPCX( const char *filename, byte **pic, byte *palette, int *width, int *height ) { - byte *raw, *end; - pcx_t *pcx; - size_t len, x, y, w, h; - int dataByte, runLength; - byte *out, *pix; - - if( !filename || !pic ) { - Com_Error( ERR_FATAL, "LoadPCX: NULL" ); - } - - *pic = NULL; +qboolean IMG_LoadPCX( const char *filename, byte **pic, byte *palette, int *width, int *height ) { + byte *raw, *end; + dpcx_t *pcx; + size_t len, x, y, w, h; + int dataByte, runLength; + byte *out, *pix; + + if( !filename ) { + Com_Error( ERR_FATAL, "LoadPCX: NULL" ); + } + if( pic ) { + *pic = NULL; + } - // - // load the file - // - len = fs.LoadFile( filename, (void **)&pcx ); - if( !pcx ) { - return; - } + // + // load the file + // + len = FS_LoadFile( filename, (void **)&pcx ); + if( !pcx ) { + return qfalse; + } if( len < sizeof( *pcx ) ) { - Com_WPrintf( "LoadPCX: %s: file too short\n", filename ); + Com_WPrintf( "LoadPCX: %s: file too short\n", filename ); goto fail2; } - // - // parse the PCX file - // - + // + // parse the PCX file + // w = LittleShort( pcx->xmax ) + 1; h = LittleShort( pcx->ymax ) + 1; - - if( pcx->manufacturer != 0x0a - || pcx->version != 5 - || pcx->encoding != 1 - || pcx->bits_per_pixel != 8 - || w > 640 - || h > 480 ) - { - Com_WPrintf( "LoadPCX: %s: unsupported format\n", filename ); + if( pcx->manufacturer != 0x0a || pcx->version != 5 + || pcx->encoding != 1 || pcx->bits_per_pixel != 8 + || w > 640 || h > 480 ) + { + Com_WPrintf( "LoadPCX: %s: unsupported format\n", filename ); goto fail2; - } - - pix = out = PCX_ALLOC( w * h ); + } - if( palette ) { + // + // get palette + // + if( palette ) { if( len < 768 ) { - Com_WPrintf( "LoadPCX: %s: palette too short\n", filename ); - goto fail1; + Com_WPrintf( "LoadPCX: %s: palette too short\n", filename ); + goto fail2; } - memcpy( palette, ( byte * )pcx + len - 768, 768 ); - } + memcpy( palette, ( byte * )pcx + len - 768, 768 ); + } - raw = pcx->data; - end = ( byte * )pcx + len; + // + // get pixels + // + if( pic ) { + pix = out = IMG_AllocPixels( w * h ); - for( y = 0; y < h; y++, pix += w ) { - for( x = 0; x < w; ) { - if( raw >= end ) { - Com_WPrintf( "LoadPCX: %s: read past end of file\n", filename ); - goto fail1; - } - dataByte = *raw++; + raw = pcx->data; + end = ( byte * )pcx + len; - if( ( dataByte & 0xC0 ) == 0xC0 ) { - runLength = dataByte & 0x3F; - if( x + runLength > w ) { - Com_WPrintf( "LoadPCX: %s: run length overrun\n", filename ); - goto fail1; - } + for( y = 0; y < h; y++, pix += w ) { + for( x = 0; x < w; ) { if( raw >= end ) { - Com_WPrintf( "LoadPCX: %s: read past end of file\n", filename ); + Com_WPrintf( "LoadPCX: %s: read past end of file\n", filename ); goto fail1; } - dataByte = *raw++; - while( runLength-- ) { + dataByte = *raw++; + + if( ( dataByte & 0xC0 ) == 0xC0 ) { + runLength = dataByte & 0x3F; + if( x + runLength > w ) { + Com_WPrintf( "LoadPCX: %s: run length overrun\n", filename ); + goto fail1; + } + if( raw >= end ) { + Com_WPrintf( "LoadPCX: %s: read past end of file\n", filename ); + goto fail1; + } + dataByte = *raw++; + while( runLength-- ) { + pix[x++] = dataByte; + } + } else { pix[x++] = dataByte; } - } else { - pix[x++] = dataByte; - } - - } - - } + } + } - if( width ) - *width = w; - if( height ) - *height = h; + *pic = out; + } - *pic = out; + if( width ) + *width = w; + if( height ) + *height = h; - fs.FreeFile( pcx ); - return; + FS_FreeFile( pcx ); + return qtrue; fail1: - PCX_FREE( out ); + IMG_FreePixels( out ); fail2: - fs.FreeFile( pcx ); + FS_FreeFile( pcx ); + return qfalse; } /* ============== -Image_WritePCX +IMG_WritePCX ============== */ -qboolean Image_WritePCX( const char *filename, const byte *data, int width, +qboolean IMG_WritePCX( const char *filename, const byte *data, int width, int height, int rowbytes, byte *palette ) { - int i, j, length; - pcx_t *pcx; - byte *pack; + int i, j, length; + dpcx_t *pcx; + byte *pack; qboolean ret = qfalse; fileHandle_t f; - pcx = fs.AllocTempMem( width * height * 2 + 1000 ); - pcx->manufacturer = 0x0a; // PCX id - pcx->version = 5; // 256 color - pcx->encoding = 1; // uncompressed - pcx->bits_per_pixel = 8; // 256 color - pcx->xmin = 0; - pcx->ymin = 0; - pcx->xmax = LittleShort( width - 1 ); - pcx->ymax = LittleShort( height - 1 ); - pcx->hres = LittleShort( width ); - pcx->vres = LittleShort( height ); - memset( pcx->palette, 0, sizeof( pcx->palette ) ); - pcx->color_planes = 1; // chunky image - pcx->bytes_per_line = LittleShort( width ); - pcx->palette_type = LittleShort( 2 ); // not a grey scale - memset( pcx->filler, 0, sizeof( pcx->filler ) ); + pcx = FS_AllocTempMem( width * height * 2 + 1000 ); + pcx->manufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // uncompressed + pcx->bits_per_pixel = 8; // 256 color + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = LittleShort( width - 1 ); + pcx->ymax = LittleShort( height - 1 ); + pcx->hres = LittleShort( width ); + pcx->vres = LittleShort( height ); + memset( pcx->palette, 0, sizeof( pcx->palette ) ); + pcx->color_planes = 1; // chunky image + pcx->bytes_per_line = LittleShort( width ); + pcx->palette_type = LittleShort( 2 ); // not a grey scale + memset( pcx->filler, 0, sizeof( pcx->filler ) ); // pack the image - pack = pcx->data; - for( i = 0; i < height; i++) { - for( j = 0; j < width; j++) { - if( ( *data & 0xc0 ) == 0xc0 ) { - *pack++ = 0xc1; + pack = pcx->data; + for( i = 0; i < height; i++) { + for( j = 0; j < width; j++) { + if( ( *data & 0xc0 ) == 0xc0 ) { + *pack++ = 0xc1; } - *pack++ = *data++; - } - data += rowbytes - width; - } - + *pack++ = *data++; + } + data += rowbytes - width; + } + // write the palette - *pack++ = 0x0c; // palette ID byte - for( i = 0; i < 768; i++ ) - *pack++ = *palette++; - + *pack++ = 0x0c; // palette ID byte + for( i = 0; i < 768; i++ ) + *pack++ = *palette++; + // write output file - fs.FOpenFile( filename, &f, FS_MODE_WRITE ); - if( !f ) { + FS_FOpenFile( filename, &f, FS_MODE_WRITE ); + if( !f ) { goto fail; - } + } - length = pack - ( byte * )pcx; - if( fs.Write( pcx, length, f ) == length ) { + length = pack - ( byte * )pcx; + if( FS_Write( pcx, length, f ) == length ) { ret = qtrue; } - fs.FCloseFile( f ); + FS_FCloseFile( f ); fail: - fs.FreeFile( pcx ); + FS_FreeFile( pcx ); return ret; } -#ifdef TRUECOLOR_RENDERER +#if USE_TGA /* ========================================================= @@ -243,207 +238,201 @@ TARGA LOADING ========================================================= */ -static qboolean tga_decode_bgr( byte *data, byte *pixels, - int columns, int rows, byte *maxp ) -{ - int col, row; - uint32_t *pixbuf; +#define TGA_DECODE( x ) \ + static qboolean tga_decode_##x( byte *data, byte *pixels, \ + int columns, int rows, byte *maxp ) - for( row = rows - 1; row >= 0; row-- ) { - pixbuf = ( uint32_t * )pixels + row * columns; +typedef qboolean (*tga_decode_t)( byte *, byte *, int, int, byte * ); - for( col = 0; col < columns; col++ ) { - *pixbuf++ = MakeColor( data[2], data[1], data[0], 255 ); - data += 3; - } - } +TGA_DECODE( bgr ) { + int col, row; + uint32_t *pixbuf; - return qtrue; + for( row = rows - 1; row >= 0; row-- ) { + pixbuf = ( uint32_t * )pixels + row * columns; + + for( col = 0; col < columns; col++ ) { + *pixbuf++ = MakeColor( data[2], data[1], data[0], 255 ); + data += 3; + } + } + + return qtrue; } -static qboolean tga_decode_bgra( byte *data, byte *pixels, - int columns, int rows, byte *maxp ) -{ - int col, row; - uint32_t *pixbuf; +TGA_DECODE( bgra ) { + int col, row; + uint32_t *pixbuf; - for( row = rows - 1; row >= 0; row-- ) { - pixbuf = ( uint32_t * )pixels + row * columns; + for( row = rows - 1; row >= 0; row-- ) { + pixbuf = ( uint32_t * )pixels + row * columns; - for( col = 0; col < columns; col++ ) { - *pixbuf++ = MakeColor( data[2], data[1], data[0], data[3] ); - data += 4; - } - } + for( col = 0; col < columns; col++ ) { + *pixbuf++ = MakeColor( data[2], data[1], data[0], data[3] ); + data += 4; + } + } - return qtrue; + return qtrue; } -static qboolean tga_decode_bgr_flip( byte *data, byte *pixels, - int columns, int rows, byte *maxp ) -{ - int count; - uint32_t *pixbuf; +TGA_DECODE( bgr_flip ) { + int count; + uint32_t *pixbuf; - pixbuf = ( uint32_t * )pixels; - count = rows * columns; - do { - *pixbuf++ = MakeColor( data[2], data[1], data[0], 255 ); - data += 3; - } while( --count ); + pixbuf = ( uint32_t * )pixels; + count = rows * columns; + do { + *pixbuf++ = MakeColor( data[2], data[1], data[0], 255 ); + data += 3; + } while( --count ); - return qtrue; + return qtrue; } -static qboolean tga_decode_bgra_flip( byte *data, byte *pixels, - int columns, int rows, byte *maxp ) -{ - int count; - uint32_t *pixbuf; +TGA_DECODE( bgra_flip ) { + int count; + uint32_t *pixbuf; - pixbuf = ( uint32_t * )pixels; - count = rows * columns; - do { - *pixbuf++ = MakeColor( data[2], data[1], data[0], data[3] ); - data += 4; - } while( --count ); + pixbuf = ( uint32_t * )pixels; + count = rows * columns; + do { + *pixbuf++ = MakeColor( data[2], data[1], data[0], data[3] ); + data += 4; + } while( --count ); - return qtrue; + return qtrue; } -static qboolean tga_decode_bgr_rle( byte *data, byte *pixels, - int columns, int rows, byte *maxp ) -{ - int col, row; - uint32_t *pixbuf, color; - byte packetHeader, packetSize; - int j; - - for( row = rows - 1; row >= 0; row-- ) { - pixbuf = ( uint32_t * )pixels + row * columns; - - for( col = 0; col < columns; ) { - packetHeader = *data++; - packetSize = 1 + ( packetHeader & 0x7f ); - - if( packetHeader & 0x80 ) { - /* run-length packet */ - if( data + 3 > maxp ) { - return qfalse; - } - color = MakeColor( data[2], data[1], data[0], 255 ); - data += 3; - for( j = 0; j < packetSize; j++ ) { - *pixbuf++ = color; - - col++; - if( col == columns ) { - /* run spans across rows */ - col = 0; - - if( row > 0 ) - row--; - else - goto breakOut; - - pixbuf = ( uint32_t * )pixels + row * columns; - } - } - } else { - /* non run-length packet */ - if( data + 3 * packetSize > maxp ) { - return qfalse; - } - for( j = 0; j < packetSize; j++ ) { - *pixbuf++ = MakeColor( data[2], data[1], data[0], 255 ); - data += 3; - - col++; - if( col == columns ) { - /* run spans across rows */ - col = 0; - if( row > 0 ) - row--; - else - goto breakOut; - pixbuf = ( uint32_t * )pixels + row * columns; - } - } - } - } +TGA_DECODE( bgr_rle ) { + int col, row; + uint32_t *pixbuf, color; + byte packetHeader, packetSize; + int j; + + for( row = rows - 1; row >= 0; row-- ) { + pixbuf = ( uint32_t * )pixels + row * columns; + + for( col = 0; col < columns; ) { + packetHeader = *data++; + packetSize = 1 + ( packetHeader & 0x7f ); + + if( packetHeader & 0x80 ) { + /* run-length packet */ + if( data + 3 > maxp ) { + return qfalse; + } + color = MakeColor( data[2], data[1], data[0], 255 ); + data += 3; + for( j = 0; j < packetSize; j++ ) { + *pixbuf++ = color; + + col++; + if( col == columns ) { + /* run spans across rows */ + col = 0; + + if( row > 0 ) + row--; + else + goto breakOut; + + pixbuf = ( uint32_t * )pixels + row * columns; + } + } + } else { + /* non run-length packet */ + if( data + 3 * packetSize > maxp ) { + return qfalse; + } + for( j = 0; j < packetSize; j++ ) { + *pixbuf++ = MakeColor( data[2], data[1], data[0], 255 ); + data += 3; + + col++; + if( col == columns ) { + /* run spans across rows */ + col = 0; + if( row > 0 ) + row--; + else + goto breakOut; + pixbuf = ( uint32_t * )pixels + row * columns; + } + } + } + } breakOut: ; - } + } - return qtrue; + return qtrue; } -static qboolean tga_decode_bgra_rle( byte *data, byte *pixels, - int columns, int rows, byte *maxp ) -{ - int col, row; - uint32_t *pixbuf, color; - byte packetHeader, packetSize; - int j; - - for( row = rows - 1; row >= 0; row-- ) { - pixbuf = ( uint32_t * )pixels + row * columns; - - for( col = 0; col < columns; ) { - packetHeader = *data++; - packetSize = 1 + ( packetHeader & 0x7f ); - - if( packetHeader & 0x80 ) { - /* run-length packet */ - if( data + 4 > maxp ) { - return qfalse; - } - color = MakeColor( data[2], data[1], data[0], data[3] ); - data += 4; - for( j = 0; j < packetSize; j++ ) { - *pixbuf++ = color; - - col++; - if( col == columns ) { - /* run spans across rows */ - col = 0; - - if( row > 0 ) - row--; - else - goto breakOut; - - pixbuf = ( uint32_t * )pixels + row * columns; - } - } - } else { - /* non run-length packet */ - if( data + 4 * packetSize > maxp ) { - return qfalse; - } - for( j = 0; j < packetSize; j++ ) { - *pixbuf++ = MakeColor( data[2], data[1], data[0], data[3] ); - data += 4; - - col++; - if( col == columns ) { - /* run spans across rows */ - col = 0; - if( row > 0 ) - row--; - else - goto breakOut; - pixbuf = ( uint32_t * )pixels + row * columns; - } - } - } - } +TGA_DECODE( bgra_rle ) { + int col, row; + uint32_t *pixbuf, color; + byte packetHeader, packetSize; + int j; + + for( row = rows - 1; row >= 0; row-- ) { + pixbuf = ( uint32_t * )pixels + row * columns; + + for( col = 0; col < columns; ) { + packetHeader = *data++; + packetSize = 1 + ( packetHeader & 0x7f ); + + if( packetHeader & 0x80 ) { + /* run-length packet */ + if( data + 4 > maxp ) { + return qfalse; + } + color = MakeColor( data[2], data[1], data[0], data[3] ); + data += 4; + for( j = 0; j < packetSize; j++ ) { + *pixbuf++ = color; + + col++; + if( col == columns ) { + /* run spans across rows */ + col = 0; + + if( row > 0 ) + row--; + else + goto breakOut; + + pixbuf = ( uint32_t * )pixels + row * columns; + } + } + } else { + /* non run-length packet */ + if( data + 4 * packetSize > maxp ) { + return qfalse; + } + for( j = 0; j < packetSize; j++ ) { + *pixbuf++ = MakeColor( data[2], data[1], data[0], data[3] ); + data += 4; + + col++; + if( col == columns ) { + /* run spans across rows */ + col = 0; + if( row > 0 ) + row--; + else + goto breakOut; + pixbuf = ( uint32_t * )pixels + row * columns; + } + } + } + } breakOut: ; - } + } - return qtrue; + return qtrue; } @@ -454,115 +443,110 @@ breakOut: ; LoadTGA ============= */ -void Image_LoadTGA( const char *filename, byte **pic, - int *width, int *height ) -{ - byte *buffer; - size_t length; - byte *pixels; - int offset, w, h; - qboolean (*decode)( byte *, byte *, int, int, byte * ); - int id_length, image_type, pixel_size, attributes, bpp; - - if( !filename || !pic ) { - Com_Error( ERR_FATAL, "LoadTGA: NULL" ); - } +void IMG_LoadTGA( const char *filename, byte **pic, int *width, int *height ) { + byte *buffer; + size_t length; + byte *pixels; + int offset, w, h; + tga_decode_t decode; + int id_length, image_type, pixel_size, attributes, bpp; + + if( !filename || !pic ) { + Com_Error( ERR_FATAL, "LoadTGA: NULL" ); + } - *pic = NULL; + *pic = NULL; - // - // load the file - // - length = fs.LoadFile( filename, ( void ** )&buffer ); - if( !buffer ) { - return; - } + // + // load the file + // + length = FS_LoadFile( filename, ( void ** )&buffer ); + if( !buffer ) { + return; + } - if( length < TARGA_HEADER_SIZE ) { - Com_WPrintf( "LoadTGA: %s: file too small\n", filename ); - goto finish; - } + if( length < TARGA_HEADER_SIZE ) { + Com_WPrintf( "LoadTGA: %s: file too small\n", filename ); + goto finish; + } - id_length = buffer[0]; + id_length = buffer[0]; image_type = buffer[2]; w = MakeShort( buffer[12], buffer[13] ); h = MakeShort( buffer[14], buffer[15] ); - pixel_size = buffer[16]; + pixel_size = buffer[16]; attributes = buffer[17]; - - // skip TARGA image comment - offset = TARGA_HEADER_SIZE + id_length; - if( offset + 4 > length ) { - Com_WPrintf( "LoadTGA: %s: offset out of range\n", filename ); - goto finish; - } + + // skip TARGA image comment + offset = TARGA_HEADER_SIZE + id_length; + if( offset + 4 > length ) { + Com_WPrintf( "LoadTGA: %s: offset out of range\n", filename ); + goto finish; + } - if( pixel_size == 32 ) { - bpp = 4; - } else if( pixel_size == 24 ) { - bpp = 3; - } else { - Com_WPrintf( "LoadTGA: %s: only 32 and 24 bit targa RGB " - "images supported, this one is %d bit\n", + if( pixel_size == 32 ) { + bpp = 4; + } else if( pixel_size == 24 ) { + bpp = 3; + } else { + Com_WPrintf( "LoadTGA: %s: only 32 and 24 bit targa RGB " + "images supported, this one is %d bit\n", filename, pixel_size ); - goto finish; - } - - if( w < 1 || h < 1 || w > MAX_TEXTURE_SIZE || h > MAX_TEXTURE_SIZE ) { - Com_WPrintf( "LoadTGA: %s: bad dimensions: %dx%d\n", - filename, w, h ); - goto finish; - } - - if( image_type == 2 ) { - if( offset + w * h * bpp > length ) { - Com_WPrintf( "LoadTGA: %s: malformed targa image\n", filename ); - goto finish; - } - if( attributes & 32 ) { - if( pixel_size == 32 ) { - decode = tga_decode_bgra_flip; - } else { - decode = tga_decode_bgr_flip; - } - } else { - if( pixel_size == 32 ) { - decode = tga_decode_bgra; - } else { - decode = tga_decode_bgr; - } - } - } else if( image_type == 10 ) { - if( attributes & 32 ) { - Com_WPrintf( "LoadTGA: %s: vertically flipped, RLE encoded " - "images are not supported\n", filename ); - goto finish; - } - if( pixel_size == 32 ) { - decode = tga_decode_bgra_rle; - } else { - decode = tga_decode_bgr_rle; - } - } else { - Com_WPrintf( "LoadTGA: %s: only type 2 and 10 targa RGB " - "images supported, this one is %d\n", - filename, image_type ); - goto finish; - } + goto finish; + } - pixels = fs.AllocTempMem( w * h * 4 ); + if( w < 1 || h < 1 || w > MAX_TEXTURE_SIZE || h > MAX_TEXTURE_SIZE ) { + Com_WPrintf( "LoadTGA: %s: bad dimensions: %dx%d\n", + filename, w, h ); + goto finish; + } - if( (*decode)( buffer + offset, pixels, w, h, buffer + length ) == qfalse ) { - fs.FreeFile( pixels ); - goto finish; - } + if( image_type == 2 ) { + if( offset + w * h * bpp > length ) { + Com_WPrintf( "LoadTGA: %s: malformed targa image\n", filename ); + goto finish; + } + if( attributes & 32 ) { + if( pixel_size == 32 ) { + decode = tga_decode_bgra_flip; + } else { + decode = tga_decode_bgr_flip; + } + } else { + if( pixel_size == 32 ) { + decode = tga_decode_bgra; + } else { + decode = tga_decode_bgr; + } + } + } else if( image_type == 10 ) { + if( attributes & 32 ) { + Com_WPrintf( "LoadTGA: %s: vertically flipped, RLE encoded " + "images are not supported\n", filename ); + goto finish; + } + if( pixel_size == 32 ) { + decode = tga_decode_bgra_rle; + } else { + decode = tga_decode_bgr_rle; + } + } else { + Com_WPrintf( "LoadTGA: %s: only type 2 and 10 targa RGB " + "images supported, this one is %d\n", + filename, image_type ); + goto finish; + } - *pic = pixels; - *width = w; - *height = h; - + pixels = IMG_AllocPixels( w * h * 4 ); + if( decode( buffer + offset, pixels, w, h, buffer + length ) ) { + *pic = pixels; + *width = w; + *height = h; + } else { + IMG_FreePixels( pixels ); + } finish: - fs.FreeFile( buffer ); + FS_FreeFile( buffer ); } /* @@ -575,46 +559,45 @@ TARGA WRITING /* ================= -Image_WriteTGA +IMG_WriteTGA ================= */ -qboolean Image_WriteTGA( const char *filename, const byte *bgr, - int width, int height ) -{ - int length; - fileHandle_t f; - byte header[TARGA_HEADER_SIZE]; +qboolean IMG_WriteTGA( const char *filename, const byte *bgr, int width, int height ) { + int length; + fileHandle_t f; + byte header[TARGA_HEADER_SIZE]; - fs.FOpenFile( filename, &f, FS_MODE_WRITE ); - if( !f ) { - return qfalse; - } + FS_FOpenFile( filename, &f, FS_MODE_WRITE ); + if( !f ) { + return qfalse; + } memset( &header, 0, sizeof( header ) ); - header[ 2] = 2; // uncompressed type - header[12] = width & 255; + header[ 2] = 2; // uncompressed type + header[12] = width & 255; header[13] = width >> 8; - header[14] = height & 255; + header[14] = height & 255; header[15] = height >> 8; - header[16] = 24; // pixel size + header[16] = 24; // pixel size - if( fs.Write( &header, sizeof( header ), f ) != sizeof( header ) ) { + if( FS_Write( &header, sizeof( header ), f ) != sizeof( header ) ) { goto fail; } - length = width * height * 3; - if( fs.Write( bgr, length, f ) != length ) { + length = width * height * 3; + if( FS_Write( bgr, length, f ) != length ) { goto fail; } - fs.FCloseFile( f ); - return qtrue; + FS_FCloseFile( f ); + return qtrue; fail: - fs.FCloseFile( f ); - return qfalse; + FS_FCloseFile( f ); + return qfalse; } +#endif // USE_TGA /* ========================================================= @@ -624,17 +607,17 @@ JPEG LOADING ========================================================= */ -#if USE_JPEG +#if USE_JPG typedef struct my_error_mgr { - struct jpeg_error_mgr pub; - jmp_buf setjmp_buffer; + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; const char *filename; } *my_error_ptr; METHODDEF( void )my_output_message( j_common_ptr cinfo ) { char buffer[JMSG_LENGTH_MAX]; - my_error_ptr myerr = ( my_error_ptr )cinfo->err; + my_error_ptr myerr = ( my_error_ptr )cinfo->err; (*cinfo->err->format_message)( cinfo, buffer ); @@ -642,50 +625,50 @@ METHODDEF( void )my_output_message( j_common_ptr cinfo ) { } METHODDEF( void )my_error_exit( j_common_ptr cinfo ) { - my_error_ptr myerr = ( my_error_ptr )cinfo->err; + my_error_ptr myerr = ( my_error_ptr )cinfo->err; - (*cinfo->err->output_message)( cinfo ); + (*cinfo->err->output_message)( cinfo ); - longjmp( myerr->setjmp_buffer, 1 ); + longjmp( myerr->setjmp_buffer, 1 ); } METHODDEF( void )mem_init_source( j_decompress_ptr cinfo ) { } METHODDEF( boolean )mem_fill_input_buffer( j_decompress_ptr cinfo ) { - my_error_ptr jerr = ( my_error_ptr )cinfo->err; + my_error_ptr jerr = ( my_error_ptr )cinfo->err; - longjmp( jerr->setjmp_buffer, 1 ); - return TRUE; + longjmp( jerr->setjmp_buffer, 1 ); + return TRUE; } METHODDEF( void )mem_skip_input_data( j_decompress_ptr cinfo, long num_bytes ) { - struct jpeg_source_mgr *src = cinfo->src; - my_error_ptr jerr = ( my_error_ptr )cinfo->err; + struct jpeg_source_mgr *src = cinfo->src; + my_error_ptr jerr = ( my_error_ptr )cinfo->err; - if( src->bytes_in_buffer < num_bytes ) { - longjmp( jerr->setjmp_buffer, 1 ); - } - - src->next_input_byte += ( size_t )num_bytes; - src->bytes_in_buffer -= ( size_t )num_bytes; + if( src->bytes_in_buffer < num_bytes ) { + longjmp( jerr->setjmp_buffer, 1 ); + } + + src->next_input_byte += ( size_t )num_bytes; + src->bytes_in_buffer -= ( size_t )num_bytes; } METHODDEF( void )mem_term_source( j_decompress_ptr cinfo ) { } METHODDEF( void )jpeg_mem_src( j_decompress_ptr cinfo, byte *data, size_t size ) { - cinfo->src = ( struct jpeg_source_mgr * )(*cinfo->mem->alloc_small)( + cinfo->src = ( struct jpeg_source_mgr * )(*cinfo->mem->alloc_small)( ( j_common_ptr )cinfo, JPOOL_PERMANENT, sizeof( struct jpeg_source_mgr ) ); - cinfo->src->init_source = mem_init_source; - cinfo->src->fill_input_buffer = mem_fill_input_buffer; - cinfo->src->skip_input_data = mem_skip_input_data; - cinfo->src->resync_to_restart = jpeg_resync_to_restart; - cinfo->src->term_source = mem_term_source; - cinfo->src->bytes_in_buffer = size; - cinfo->src->next_input_byte = data; + cinfo->src->init_source = mem_init_source; + cinfo->src->fill_input_buffer = mem_fill_input_buffer; + cinfo->src->skip_input_data = mem_skip_input_data; + cinfo->src->resync_to_restart = jpeg_resync_to_restart; + cinfo->src->term_source = mem_term_source; + cinfo->src->bytes_in_buffer = size; + cinfo->src->next_input_byte = data; } /* @@ -693,83 +676,82 @@ METHODDEF( void )jpeg_mem_src( j_decompress_ptr cinfo, byte *data, size_t size ) LoadJPG ================= */ -void Image_LoadJPG( const char *filename, byte **pic, int *width, int *height ) { - struct jpeg_decompress_struct cinfo; - struct my_error_mgr jerr; - JSAMPARRAY buffer; - int row_stride; - byte *rawdata; - size_t rawlength; - byte *pixels; - byte *src; +void IMG_LoadJPG( const char *filename, byte **pic, int *width, int *height ) { + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + JSAMPARRAY buffer; + int row_stride; + byte *rawdata; + size_t rawlength; + byte *pixels; + byte *src; uint32_t *dst; - int i; + int i; - if( !filename || !pic ) { - Com_Error( ERR_FATAL, "LoadJPG: NULL" ); - } + if( !filename || !pic ) { + Com_Error( ERR_FATAL, "LoadJPG: NULL" ); + } - *pic = NULL; - pixels = NULL; + *pic = pixels = NULL; - rawlength = fs.LoadFile( filename, ( void ** )&rawdata ); - if( !rawdata ) { - return; - } + rawlength = FS_LoadFile( filename, ( void ** )&rawdata ); + if( !rawdata ) { + return; + } - cinfo.err = jpeg_std_error( &jerr.pub ); - jerr.pub.error_exit = my_error_exit; - jerr.pub.output_message = my_output_message; + cinfo.err = jpeg_std_error( &jerr.pub ); + jerr.pub.error_exit = my_error_exit; + jerr.pub.output_message = my_output_message; jerr.filename = filename; - jpeg_create_decompress( &cinfo ); - - if( setjmp( jerr.setjmp_buffer ) ) { - jpeg_destroy_decompress( &cinfo ); - if( pixels ) { - fs.FreeFile( pixels ); - } - fs.FreeFile( rawdata ); - return; - } + jpeg_create_decompress( &cinfo ); + + if( setjmp( jerr.setjmp_buffer ) ) { + jpeg_destroy_decompress( &cinfo ); + if( pixels ) { + IMG_FreePixels( pixels ); + } + FS_FreeFile( rawdata ); + return; + } - jpeg_mem_src( &cinfo, rawdata, rawlength ); - jpeg_read_header( &cinfo, TRUE ); - jpeg_start_decompress( &cinfo ); - - if( cinfo.output_components != 3 /*&& cinfo.output_components != 4*/ ) { - Com_WPrintf( "LoadJPG: %s: unsupported number of color components: %i\n", - filename, cinfo.output_components ); - jpeg_destroy_decompress( &cinfo ); - fs.FreeFile( rawdata ); - return; - } + jpeg_mem_src( &cinfo, rawdata, rawlength ); + jpeg_read_header( &cinfo, TRUE ); + jpeg_start_decompress( &cinfo ); + + if( cinfo.output_components != 3 /*&& cinfo.output_components != 4*/ ) { + Com_WPrintf( "LoadJPG: %s: unsupported number of color components: %i\n", + filename, cinfo.output_components ); + jpeg_destroy_decompress( &cinfo ); + FS_FreeFile( rawdata ); + return; + } - *width = cinfo.output_width; - *height = cinfo.output_height; + *width = cinfo.output_width; + *height = cinfo.output_height; - pixels = fs.AllocTempMem( cinfo.output_width * cinfo.output_height * 4 ); + pixels = IMG_AllocPixels( cinfo.output_width * cinfo.output_height * 4 ); - row_stride = cinfo.output_width * cinfo.output_components; + row_stride = cinfo.output_width * cinfo.output_components; - buffer = (*cinfo.mem->alloc_sarray)( ( j_common_ptr )&cinfo, JPOOL_IMAGE, row_stride, 1 ); + buffer = (*cinfo.mem->alloc_sarray)( ( j_common_ptr )&cinfo, JPOOL_IMAGE, row_stride, 1 ); - dst = ( uint32_t * )pixels; - while( cinfo.output_scanline < cinfo.output_height ) { - jpeg_read_scanlines( &cinfo, buffer, 1 ); + dst = ( uint32_t * )pixels; + while( cinfo.output_scanline < cinfo.output_height ) { + jpeg_read_scanlines( &cinfo, buffer, 1 ); - src = ( byte * )buffer[0]; - for( i = 0; i < cinfo.output_width; i++, src += 3 ) { - *dst++ = MakeColor( src[0], src[1], src[2], 255 ); - } - } + src = ( byte * )buffer[0]; + for( i = 0; i < cinfo.output_width; i++, src += 3 ) { + *dst++ = MakeColor( src[0], src[1], src[2], 255 ); + } + } - jpeg_finish_decompress( &cinfo ); - jpeg_destroy_decompress( &cinfo ); + jpeg_finish_decompress( &cinfo ); + jpeg_destroy_decompress( &cinfo ); - fs.FreeFile( rawdata ); + FS_FreeFile( rawdata ); - *pic = pixels; + *pic = pixels; } @@ -781,129 +763,129 @@ JPEG WRITING ========================================================= */ -#define OUTPUT_BUF_SIZE 4096 +#define OUTPUT_BUF_SIZE 4096 typedef struct my_destination_mgr { - struct jpeg_destination_mgr pub; /* public fields */ + struct jpeg_destination_mgr pub; /* public fields */ - fileHandle_t hFile; /* target stream */ - JOCTET *buffer; /* start of buffer */ + fileHandle_t hFile; /* target stream */ + JOCTET *buffer; /* start of buffer */ } *my_dest_ptr; METHODDEF( void ) vfs_init_destination( j_compress_ptr cinfo ) { - my_dest_ptr dest = ( my_dest_ptr )cinfo->dest; + my_dest_ptr dest = ( my_dest_ptr )cinfo->dest; - /* Allocate the output buffer --- it will be released when done with image */ - dest->buffer = ( JOCTET * )(*cinfo->mem->alloc_small)( ( j_common_ptr )cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof( JOCTET ) ); + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = ( JOCTET * )(*cinfo->mem->alloc_small)( ( j_common_ptr )cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof( JOCTET ) ); - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } METHODDEF( boolean ) vfs_empty_output_buffer( j_compress_ptr cinfo ) { - my_dest_ptr dest = ( my_dest_ptr )cinfo->dest; - my_error_ptr jerr = ( my_error_ptr )cinfo->err; + my_dest_ptr dest = ( my_dest_ptr )cinfo->dest; + my_error_ptr jerr = ( my_error_ptr )cinfo->err; - if( fs.Write( dest->buffer, OUTPUT_BUF_SIZE, dest->hFile ) != OUTPUT_BUF_SIZE ) { - longjmp( jerr->setjmp_buffer, 1 ); - } + if( FS_Write( dest->buffer, OUTPUT_BUF_SIZE, dest->hFile ) != OUTPUT_BUF_SIZE ) { + longjmp( jerr->setjmp_buffer, 1 ); + } - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - return TRUE; + return TRUE; } METHODDEF( void ) vfs_term_destination( j_compress_ptr cinfo ) { - my_dest_ptr dest = ( my_dest_ptr )cinfo->dest; - my_error_ptr jerr = ( my_error_ptr )cinfo->err; - int remaining = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; - - /* Write any data remaining in the buffer */ - if( remaining > 0 ) { - if( fs.Write( dest->buffer, remaining, dest->hFile ) != remaining ) { - longjmp( jerr->setjmp_buffer, 1 ); - } - } + my_dest_ptr dest = ( my_dest_ptr )cinfo->dest; + my_error_ptr jerr = ( my_error_ptr )cinfo->err; + int remaining = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if( remaining > 0 ) { + if( FS_Write( dest->buffer, remaining, dest->hFile ) != remaining ) { + longjmp( jerr->setjmp_buffer, 1 ); + } + } } METHODDEF( void ) jpeg_vfs_dst( j_compress_ptr cinfo, fileHandle_t hFile ) { - my_dest_ptr dest; + my_dest_ptr dest; - dest = ( my_dest_ptr )(*cinfo->mem->alloc_small)( ( j_common_ptr )cinfo, JPOOL_PERMANENT, sizeof( struct my_destination_mgr ) ); - cinfo->dest = &dest->pub; + dest = ( my_dest_ptr )(*cinfo->mem->alloc_small)( ( j_common_ptr )cinfo, JPOOL_PERMANENT, sizeof( struct my_destination_mgr ) ); + cinfo->dest = &dest->pub; - dest->pub.init_destination = vfs_init_destination; - dest->pub.empty_output_buffer = vfs_empty_output_buffer; - dest->pub.term_destination = vfs_term_destination; - dest->hFile = hFile; + dest->pub.init_destination = vfs_init_destination; + dest->pub.empty_output_buffer = vfs_empty_output_buffer; + dest->pub.term_destination = vfs_term_destination; + dest->hFile = hFile; } /* ================= -Image_WriteJPG +IMG_WriteJPG ================= */ -qboolean Image_WriteJPG( const char *filename, const byte *rgb, int width, int height, int quality ) { - struct jpeg_compress_struct cinfo; - struct my_error_mgr jerr; - fileHandle_t hFile; - JSAMPROW row_pointer[1]; - int row_stride; - - fs.FOpenFile( filename, &hFile, FS_MODE_WRITE ); - if( !hFile ) { - Com_DPrintf( "WriteJPG: %s: couldn't create file\n", filename ); - return qfalse; - } +qboolean IMG_WriteJPG( const char *filename, const byte *rgb, int width, int height, int quality ) { + struct jpeg_compress_struct cinfo; + struct my_error_mgr jerr; + fileHandle_t hFile; + JSAMPROW row_pointer[1]; + int row_stride; - cinfo.err = jpeg_std_error( &jerr.pub ); - jerr.pub.error_exit = my_error_exit; + FS_FOpenFile( filename, &hFile, FS_MODE_WRITE ); + if( !hFile ) { + Com_DPrintf( "WriteJPG: %s: couldn't create file\n", filename ); + return qfalse; + } - if( setjmp( jerr.setjmp_buffer ) ) { - Com_DPrintf( "WriteJPG: %s: JPEGLIB signaled an error\n", filename ); - jpeg_destroy_compress( &cinfo ); - fs.FCloseFile( hFile ); - return qfalse; - } + cinfo.err = jpeg_std_error( &jerr.pub ); + jerr.pub.error_exit = my_error_exit; - jpeg_create_compress( &cinfo ); + if( setjmp( jerr.setjmp_buffer ) ) { + Com_DPrintf( "WriteJPG: %s: JPEGLIB signaled an error\n", filename ); + jpeg_destroy_compress( &cinfo ); + FS_FCloseFile( hFile ); + return qfalse; + } - jpeg_vfs_dst( &cinfo, hFile ); + jpeg_create_compress( &cinfo ); - cinfo.image_width = width; // image width and height, in pixels - cinfo.image_height = height; - cinfo.input_components = 3; // # of color components per pixel - cinfo.in_color_space = JCS_RGB; // colorspace of input image + jpeg_vfs_dst( &cinfo, hFile ); - clamp( quality, 0, 100 ); + cinfo.image_width = width; // image width and height, in pixels + cinfo.image_height = height; + cinfo.input_components = 3; // # of color components per pixel + cinfo.in_color_space = JCS_RGB; // colorspace of input image - jpeg_set_defaults( &cinfo ); - jpeg_set_quality( &cinfo, quality, TRUE ); + clamp( quality, 0, 100 ); - jpeg_start_compress( &cinfo, TRUE ); + jpeg_set_defaults( &cinfo ); + jpeg_set_quality( &cinfo, quality, TRUE ); - row_stride = width * 3; // JSAMPLEs per row in image_buffer + jpeg_start_compress( &cinfo, TRUE ); - while( cinfo.next_scanline < cinfo.image_height ) { - row_pointer[0] = ( byte * )( &rgb[( cinfo.image_height - cinfo.next_scanline - 1 ) * row_stride] ); - jpeg_write_scanlines( &cinfo, row_pointer, 1 ); - } + row_stride = width * 3; // JSAMPLEs per row in image_buffer - jpeg_finish_compress( &cinfo ); - fs.FCloseFile( hFile ); + while( cinfo.next_scanline < cinfo.image_height ) { + row_pointer[0] = ( byte * )( &rgb[( cinfo.image_height - cinfo.next_scanline - 1 ) * row_stride] ); + jpeg_write_scanlines( &cinfo, row_pointer, 1 ); + } - jpeg_destroy_compress( &cinfo ); + jpeg_finish_compress( &cinfo ); + FS_FCloseFile( hFile ); - return qtrue; + jpeg_destroy_compress( &cinfo ); + + return qtrue; } -#endif /* USE_JPEG */ +#endif /* USE_JPG */ #if USE_PNG @@ -917,32 +899,32 @@ PNG LOADING */ struct pngReadStruct { - byte *data; - byte *maxp; + byte *data; + byte *maxp; }; static void QDECL png_vfs_read_fn( png_structp png_ptr, png_bytep buf, png_size_t size ) { - struct pngReadStruct *r = png_get_io_ptr( png_ptr ); + struct pngReadStruct *r = png_get_io_ptr( png_ptr ); - if( r->data + size > r->maxp ) { + if( r->data + size > r->maxp ) { png_error( png_ptr, "read error" ); - } else { - memcpy( buf, r->data, size ); - r->data += size; + } else { + memcpy( buf, r->data, size ); + r->data += size; } } static void QDECL png_console_error_fn( png_structp png_ptr, png_const_charp error_msg ) { - char *f = png_get_error_ptr( png_ptr ); + char *f = png_get_error_ptr( png_ptr ); - Com_EPrintf( "LoadPNG: %s: %s\n", f, error_msg ); - longjmp( png_jmpbuf( png_ptr ), -1 ); + Com_EPrintf( "LoadPNG: %s: %s\n", f, error_msg ); + longjmp( png_jmpbuf( png_ptr ), -1 ); } static void QDECL png_console_warning_fn( png_structp png_ptr, png_const_charp warning_msg ) { - char *f = png_get_error_ptr( png_ptr ); + char *f = png_get_error_ptr( png_ptr ); - Com_WPrintf( "LoadPNG: %s: %s\n", f, warning_msg ); + Com_WPrintf( "LoadPNG: %s: %s\n", f, warning_msg ); } /* @@ -950,161 +932,160 @@ static void QDECL png_console_warning_fn( png_structp png_ptr, png_const_charp w LoadPNG ================= */ -void Image_LoadPNG( const char *filename, byte **pic, int *width, int *height ) { - byte *rawdata; - size_t rawlength; - byte *pixels; - png_bytep row_pointers[MAX_TEXTURE_SIZE]; - png_uint_32 w, h, rowbytes, row; +void IMG_LoadPNG( const char *filename, byte **pic, int *width, int *height ) { + byte *rawdata; + size_t rawlength; + byte *pixels; + png_bytep row_pointers[MAX_TEXTURE_SIZE]; + png_uint_32 w, h, rowbytes, row; int bitdepth, colortype; - png_structp png_ptr; - png_infop info_ptr; - struct pngReadStruct r; + png_structp png_ptr; + png_infop info_ptr; + struct pngReadStruct r; - if( !filename || !pic ) { - Com_Error( ERR_FATAL, "LoadPNG: NULL" ); - } + if( !filename || !pic ) { + Com_Error( ERR_FATAL, "LoadPNG: NULL" ); + } - *pic = NULL; - pixels = NULL; + *pic = pixels = NULL; - rawlength = fs.LoadFile( filename, ( void ** )&rawdata ); - if( !rawdata ) { - return; - } + rawlength = FS_LoadFile( filename, ( void ** )&rawdata ); + if( !rawdata ) { + return; + } - png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, - ( png_voidp )filename, png_console_error_fn, png_console_warning_fn ); - if( !png_ptr ) { - goto fail; - } + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, + ( png_voidp )filename, png_console_error_fn, png_console_warning_fn ); + if( !png_ptr ) { + goto fail; + } - info_ptr = png_create_info_struct( png_ptr ); - if( !info_ptr ) { - png_destroy_read_struct( &png_ptr, NULL, NULL ); - goto fail; - } + info_ptr = png_create_info_struct( png_ptr ); + if( !info_ptr ) { + png_destroy_read_struct( &png_ptr, NULL, NULL ); + goto fail; + } - if( setjmp( png_jmpbuf( png_ptr ) ) ) { - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + if( setjmp( png_jmpbuf( png_ptr ) ) ) { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); if( pixels ) { - fs.FreeFile( pixels ); + IMG_FreePixels( pixels ); } - goto fail; - } + goto fail; + } - r.data = rawdata; - r.maxp = rawdata + rawlength; - png_set_read_fn( png_ptr, ( png_voidp )&r, png_vfs_read_fn ); + r.data = rawdata; + r.maxp = rawdata + rawlength; + png_set_read_fn( png_ptr, ( png_voidp )&r, png_vfs_read_fn ); - png_read_info( png_ptr, info_ptr ); + png_read_info( png_ptr, info_ptr ); - if( !png_get_IHDR( png_ptr, info_ptr, &w, &h, &bitdepth, &colortype, - NULL, NULL, NULL ) ) - { - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); - goto fail; - } + if( !png_get_IHDR( png_ptr, info_ptr, &w, &h, &bitdepth, &colortype, + NULL, NULL, NULL ) ) + { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + goto fail; + } - if( w > MAX_TEXTURE_SIZE || h > MAX_TEXTURE_SIZE ) { - Com_EPrintf( "LoadPNG: %s: oversize image dimensions: %lux%lu\n", - filename, w, h ); - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); - goto fail; - } + if( w > MAX_TEXTURE_SIZE || h > MAX_TEXTURE_SIZE ) { + Com_EPrintf( "LoadPNG: %s: oversize image dimensions: %lux%lu\n", + filename, w, h ); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + goto fail; + } - switch( colortype ) { - case PNG_COLOR_TYPE_PALETTE: - png_set_palette_to_rgb( png_ptr ); - break; - case PNG_COLOR_TYPE_GRAY: - if( bitdepth < 8 ) { - png_set_gray_1_2_4_to_8( png_ptr ); - } - // fall through - case PNG_COLOR_TYPE_GRAY_ALPHA: - png_set_gray_to_rgb( png_ptr ); - break; - } + switch( colortype ) { + case PNG_COLOR_TYPE_PALETTE: + png_set_palette_to_rgb( png_ptr ); + break; + case PNG_COLOR_TYPE_GRAY: + if( bitdepth < 8 ) { + png_set_gray_1_2_4_to_8( png_ptr ); + } + // fall through + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_set_gray_to_rgb( png_ptr ); + break; + } - if( bitdepth < 8 ) { - png_set_packing( png_ptr ); - } else if( bitdepth == 16 ) { - png_set_strip_16( png_ptr ); - } + if( bitdepth < 8 ) { + png_set_packing( png_ptr ); + } else if( bitdepth == 16 ) { + png_set_strip_16( png_ptr ); + } - if( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) { - png_set_tRNS_to_alpha( png_ptr ); - } + if( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) { + png_set_tRNS_to_alpha( png_ptr ); + } - png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); + png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); - png_read_update_info( png_ptr, info_ptr ); + png_read_update_info( png_ptr, info_ptr ); - rowbytes = png_get_rowbytes( png_ptr, info_ptr ); - pixels = fs.AllocTempMem( h * rowbytes ); + rowbytes = png_get_rowbytes( png_ptr, info_ptr ); + pixels = IMG_AllocPixels( h * rowbytes ); - for( row = 0; row < h; row++ ) { - row_pointers[row] = pixels + row * rowbytes; - } + for( row = 0; row < h; row++ ) { + row_pointers[row] = pixels + row * rowbytes; + } - png_read_image( png_ptr, row_pointers ); + png_read_image( png_ptr, row_pointers ); - png_read_end( png_ptr, info_ptr ); + png_read_end( png_ptr, info_ptr ); - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); - *pic = pixels; - *width = w; - *height = h; + *pic = pixels; + *width = w; + *height = h; fail: - fs.FreeFile( rawdata ); + FS_FreeFile( rawdata ); } static void QDECL png_vfs_write_fn( png_structp png_ptr, png_bytep buf, png_size_t size ) { - fileHandle_t *f = png_get_io_ptr( png_ptr ); - fs.Write( buf, size, *f ); + fileHandle_t *f = png_get_io_ptr( png_ptr ); + FS_Write( buf, size, *f ); } static void QDECL png_vfs_flush_fn( png_structp png_ptr ) { - //fileHandle_t *f = png_get_io_ptr( png_ptr ); - //fs.Flush( *f ); + //fileHandle_t *f = png_get_io_ptr( png_ptr ); + //FS_Flush( *f ); } -qboolean Image_WritePNG( const char *filename, const byte *rgb, int width, int height, int compression ) { - png_structp png_ptr; - png_infop info_ptr; +qboolean IMG_WritePNG( const char *filename, const byte *rgb, int width, int height, int compression ) { + png_structp png_ptr; + png_infop info_ptr; fileHandle_t f; qboolean ret = qfalse; png_bytepp row_pointers = NULL; int row_stride; int i; - fs.FOpenFile( filename, &f, FS_MODE_WRITE ); - if( !f ) { - Com_DPrintf( "WritePNG: %s: couldn't create file\n", filename ); - return qfalse; - } + FS_FOpenFile( filename, &f, FS_MODE_WRITE ); + if( !f ) { + Com_DPrintf( "WritePNG: %s: couldn't create file\n", filename ); + return qfalse; + } - png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, - ( png_voidp )filename, png_console_error_fn, png_console_warning_fn ); - if( !png_ptr ) { + png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, + ( png_voidp )filename, png_console_error_fn, png_console_warning_fn ); + if( !png_ptr ) { goto fail; - } + } - info_ptr = png_create_info_struct( png_ptr ); - if( !info_ptr ) { - png_destroy_write_struct( &png_ptr, NULL ); - goto fail; - } + info_ptr = png_create_info_struct( png_ptr ); + if( !info_ptr ) { + png_destroy_write_struct( &png_ptr, NULL ); + goto fail; + } - if( setjmp( png_jmpbuf( png_ptr ) ) ) { - png_destroy_write_struct( &png_ptr, &info_ptr ); - goto fail; - } + if( setjmp( png_jmpbuf( png_ptr ) ) ) { + png_destroy_write_struct( &png_ptr, &info_ptr ); + goto fail; + } - png_set_write_fn( png_ptr, ( png_voidp )&f, + png_set_write_fn( png_ptr, ( png_voidp )&f, png_vfs_write_fn, png_vfs_flush_fn ); png_set_IHDR( png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, @@ -1114,7 +1095,7 @@ qboolean Image_WritePNG( const char *filename, const byte *rgb, int width, int h clamp( compression, Z_NO_COMPRESSION, Z_BEST_COMPRESSION ); png_set_compression_level( png_ptr, compression ); - row_pointers = fs.AllocTempMem( sizeof( png_bytep ) * height ); + row_pointers = FS_AllocTempMem( sizeof( png_bytep ) * height ); row_stride = width * 3; for( i = 0; i < height; i++ ) { row_pointers[i] = ( png_bytep )rgb + ( height - i - 1 ) * row_stride; @@ -1124,22 +1105,20 @@ qboolean Image_WritePNG( const char *filename, const byte *rgb, int width, int h png_write_png( png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL ); - png_destroy_write_struct( &png_ptr, &info_ptr ); + png_destroy_write_struct( &png_ptr, &info_ptr ); ret = qtrue; fail: if( row_pointers ) { - fs.FreeFile( row_pointers ); + FS_FreeFile( row_pointers ); } - fs.FCloseFile( f ); + FS_FCloseFile( f ); return ret; } #endif /* USE_PNG */ -#endif /* TRUECOLOR_RENDERER */ - /* ========================================================= @@ -1148,292 +1127,219 @@ IMAGE MANAGER ========================================================= */ -image_t r_images[MAX_RIMAGES]; -list_t r_imageHash[RIMAGES_HASH]; -int r_numImages; +#define RIMAGES_HASH 256 -uint32_t d_8to24table[256]; +image_t r_images[MAX_RIMAGES]; +list_t r_imageHash[RIMAGES_HASH]; +int r_numImages; -#ifdef TRUECOLOR_RENDERER +uint32_t d_8to24table[256]; -static cvar_t *r_override_textures; -static cvar_t *r_texture_formats; +#if USE_PNG || USE_JPG || USE_TGA +static cvar_t *r_override_textures; +static cvar_t *r_texture_formats; +#endif /* -================ -R_ResampleTexture -================ +=============== +IMG_List_f +=============== */ -void R_ResampleTexture( const byte *in, int inwidth, int inheight, byte *out, int outwidth, int outheight ) { - int i, j; - const byte *inrow1, *inrow2; - unsigned frac, fracstep; - unsigned p1[MAX_TEXTURE_SIZE], p2[MAX_TEXTURE_SIZE]; - const byte *pix1, *pix2, *pix3, *pix4; - float heightScale; - - if( outwidth > MAX_TEXTURE_SIZE ) { - Com_Error( ERR_FATAL, "%s: outwidth > %d", __func__, MAX_TEXTURE_SIZE ); - } - - fracstep = inwidth * 0x10000 / outwidth; - - frac = fracstep >> 2; - for( i = 0; i < outwidth; i++ ) { - p1[i] = 4 * ( frac >> 16 ); - frac += fracstep; - } - frac = 3 * ( fracstep >> 2 ); - for( i = 0; i < outwidth; i++ ) { - p2[i] = 4 * ( frac >> 16 ); - frac += fracstep; - } +static void IMG_List_f( void ) { + int i; + image_t *image; + int texels, count; + + Com_Printf( "------------------\n"); + texels = count = 0; + + for( i = 0, image = r_images; i < r_numImages; i++, image++ ) { + if( !image->registration_sequence ) + continue; + texels += image->upload_width * image->upload_height; + switch( image->type ) { + case it_skin: + Com_Printf( "M" ); + break; + case it_sprite: + Com_Printf( "S" ); + break; + case it_wall: + Com_Printf( "W" ); + break; + case it_pic: + Com_Printf( "P" ); + break; + case it_sky: + Com_Printf( "Y" ); + break; + case it_charset: + Com_Printf( "C" ); + break; + default: + Com_Printf( " " ); + break; + } - heightScale = ( float )inheight / outheight; - inwidth <<= 2; - for( i = 0; i < outheight; i++ ) { - inrow1 = in + inwidth * ( int )( ( i + 0.25f ) * heightScale ); - inrow2 = in + inwidth * ( int )( ( i + 0.75f ) * heightScale ); - for( j = 0; j < outwidth; j++ ) { - pix1 = inrow1 + p1[j]; - pix2 = inrow1 + p2[j]; - pix3 = inrow2 + p1[j]; - pix4 = inrow2 + p2[j]; - out[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2; - out[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2; - out[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2; - out[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2; - out += 4; - } - } + Com_Printf( " %4i %4i %s: %s\n", + image->upload_width, + image->upload_height, + ( image->flags & if_paletted ) ? "PAL" : "RGB", + image->name ); + count++; + } + Com_Printf( "Total images: %d (out of %d slots)\n", count, r_numImages ); + Com_Printf( "Total texels: %d (not counting mipmaps)\n", texels ); } -#endif /* TRUECOLOR_RENDERER */ +image_t *IMG_Alloc( const char *name ) { + int i; + image_t *image; -/* -=============== -R_ImageList_f -=============== -*/ -static void R_ImageList_f( void ) { - int i; - image_t *image; - int texels; - - Com_Printf( "------------------\n"); - texels = 0; - - for( i = 0, image = r_images; i < r_numImages; i++, image++ ) { - if( !image->registration_sequence ) - continue; - texels += image->upload_width * image->upload_height; - switch( image->type ) { - case it_skin: - Com_Printf( "M" ); - break; - case it_sprite: - Com_Printf( "S" ); - break; - case it_wall: - Com_Printf( "W" ); - break; - case it_pic: - Com_Printf( "P" ); - break; - case it_sky: - Com_Printf( "Y" ); - break; - case it_charset: - Com_Printf( "C" ); - break; - default: - Com_Printf( " " ); - break; - } - - Com_Printf( " %4i %4i %s: %s\n", image->upload_width, - image->upload_height, ( image->flags & if_paletted ) ? "PAL" : "RGB", - image->name ); - } - Com_Printf( "Total texel count (not counting mipmaps): %i\n", texels ); -} + // find a free image_t slot + for( i = 0, image = r_images; i < r_numImages; i++, image++ ) { + if( !image->registration_sequence ) + break; + } -static image_t *R_AllocImageInternal( const char *name, unsigned hash ) { - int i; - image_t *image; - - // find a free image_t slot - for( i = 0, image = r_images; i < r_numImages; i++, image++ ) { - if( !image->registration_sequence ) - break; - } - - if( i == r_numImages ) { - if( r_numImages == MAX_RIMAGES ) - Com_Error( ERR_FATAL, "R_AllocImage: MAX_IMAGES" ); - r_numImages++; - } + if( i == r_numImages ) { + if( r_numImages == MAX_RIMAGES ) + Com_Error( ERR_FATAL, "%s: MAX_IMAGES exceeded", __func__ ); + r_numImages++; + } - strcpy( image->name, name ); - List_Append( &r_imageHash[hash], &image->entry ); + strcpy( image->name, name ); - image->registration_sequence = registration_sequence; + image->registration_sequence = registration_sequence; - return image; + return image; } /* =============== -R_LookupImage +IMG_Lookup Finds the given image of the given type. Case and extension insensitive. =============== */ -static image_t *R_LookupImage( const char *name, imagetype_t type, - unsigned hash, size_t baselength ) +static image_t *IMG_Lookup( const char *name, imagetype_t type, + unsigned hash, size_t baselength ) { - image_t *image; + image_t *image; - // look for it + // look for it LIST_FOR_EACH( image_t, image, &r_imageHash[hash], entry ) { - if( image->type != type ) { - continue; - } - if( !Q_stricmpn( image->name, name, baselength ) ) { - return image; - } - } - - return NULL; -} - -image_t *R_AllocImage( const char *name ) { - char buffer[MAX_QPATH]; - char *ext; - unsigned hash; - image_t *image; - size_t length; - - if( !name || !name[0] ) { - Com_Error( ERR_FATAL, "R_AllocImage: NULL" ); - } - - length = strlen( name ); - if( length >= MAX_QPATH ) { - Com_Error( ERR_FATAL, "R_AllocImage: oversize name" ); - } - - memcpy( buffer, name, length + 1 ); - - ext = COM_FileExtension( buffer ); - if( *ext == '.' ) { - *ext = 0; - } else { - ext = NULL; - } - hash = Com_HashPath( buffer, RIMAGES_HASH ); - if( ext ) { - *ext = '.'; - } - - image = R_AllocImageInternal( buffer, hash ); + if( image->type != type ) { + continue; + } + // FIXME + if( !FS_pathcmpn( image->name, name, baselength ) ) { + return image; + } + } - return image; + return NULL; } +/* +=============== +IMG_Create -image_t *R_CreateImage( const char *name, byte *pic, int width, int height, - imagetype_t type, imageflags_t flags ) +Allocates and loads image from supplied data. +=============== +*/ +image_t *IMG_Create( const char *name, byte *pic, int width, int height, + imagetype_t type, imageflags_t flags ) { - image_t *image; - - image = R_AllocImage( name ); - R_LoadImage( image, pic, width, height, type, flags ); + image_t *image; - return image; + image = IMG_Alloc( name ); + IMG_Load( image, pic, width, height, type, flags ); + return image; } - -#ifdef TRUECOLOR_RENDERER - /* =============== -R_FindImage +IMG_Find -Finds or loads the given image (8 or 32 bit) +Finds or loads the given image, adding it to the hash table. =============== */ -image_t *R_FindImage( const char *name, imagetype_t type ) { - image_t *image; - byte *pic; - int width, height; - char buffer[MAX_QPATH]; - char *ext, *s; - size_t length; - unsigned hash, extHash; - imageflags_t flags; - - if( !name || !name[0] ) { - Com_Error( ERR_FATAL, "R_FindImage: NULL" ); - } +image_t *IMG_Find( const char *name, imagetype_t type ) { + image_t *image; + byte *pic; + int width, height; + char buffer[MAX_QPATH]; + char *ext; + size_t length; + unsigned hash, extHash; + imageflags_t flags; +#if USE_PNG || USE_JPG || USE_TGA + char *s; +#endif - length = strlen( name ); - if( length >= MAX_QPATH ) { - Com_Error( ERR_FATAL, "R_FindImage: oversize name" ); - } + if( !name ) { + Com_Error( ERR_FATAL, "%s: NULL", __func__ ); + } - if( length <= 4 ) { - return NULL; // must have at least 1 char of base name - } + length = strlen( name ); + if( length >= MAX_QPATH ) { + Com_Error( ERR_FATAL, "%s: oversize name", __func__ ); + } - length -= 4; - if( name[length] != '.' ) { - return NULL; - } - - strcpy( buffer, name ); - buffer[length] = 0; + if( length <= 4 ) { + return NULL; // must have at least 1 char of base name + } - hash = Com_HashPath( buffer, RIMAGES_HASH ); + length -= 4; + if( name[length] != '.' ) { + return NULL; + } + + strcpy( buffer, name ); + buffer[length] = 0; - if( ( image = R_LookupImage( buffer, type, hash, length ) ) != NULL ) { - image->registration_sequence = registration_sequence; - return image; - } + hash = Com_HashPath( buffer, RIMAGES_HASH ); - ext = buffer + length; - Q_strlwr( ext + 1 ); - extHash = MakeLong( '.', ext[1], ext[2], ext[3] ); + if( ( image = IMG_Lookup( buffer, type, hash, length ) ) != NULL ) { + image->registration_sequence = registration_sequence; + return image; + } - // - // load the pic from disk - // - pic = NULL; - image = NULL; - flags = 0; + ext = buffer + length; + Q_strlwr( ext + 1 ); + extHash = MakeLong( '.', ext[1], ext[2], ext[3] ); - if( r_override_textures->integer ) { + // + // create the pic from disk + // + pic = NULL; + flags = 0; + +#if USE_PNG || USE_JPG || USE_TGA + if( r_override_textures->integer ) { for( s = r_texture_formats->string; *s; s++ ) { switch( *s ) { #if USE_PNG case 'p': // try *.png strcpy( ext, ".png" ); - Image_LoadPNG( buffer, &pic, &width, &height ); + IMG_LoadPNG( buffer, &pic, &width, &height ); break; #endif -#if USE_JPEG +#if USE_JPG case 'j': // try *.jpg strcpy( ext, ".jpg" ); - Image_LoadJPG( buffer, &pic, &width, &height ); + IMG_LoadJPG( buffer, &pic, &width, &height ); break; #endif +#if USE_TGA case 't': // try *.tga strcpy( ext, ".tga" ); - Image_LoadTGA( buffer, &pic, &width, &height ); + IMG_LoadTGA( buffer, &pic, &width, &height ); break; } - +#endif if( pic ) { // replacing 8 bit texture with 32 bit texture if( extHash == EXTENSION_WAL ) { @@ -1441,7 +1347,7 @@ image_t *R_FindImage( const char *name, imagetype_t type ) { } else if( extHash == EXTENSION_PCX ) { flags |= if_replace_pcx; } - goto load; + goto create; } } @@ -1450,415 +1356,431 @@ image_t *R_FindImage( const char *name, imagetype_t type ) { case EXTENSION_TGA: case EXTENSION_JPG: case EXTENSION_PCX: - strcpy( ext, ".pcx" ); - Image_LoadPCX( buffer, &pic, NULL, &width, &height ); - if( pic ) { - flags |= if_paletted; - goto load; - } - return NULL; - case EXTENSION_WAL: - strcpy( ext, ".wal" ); - image = R_LoadWal( buffer ); - return image; - } - - return NULL; - } + strcpy( ext, ".pcx" ); + IMG_LoadPCX( buffer, &pic, NULL, &width, &height ); + if( pic ) { + flags |= if_paletted; + goto create; + } + return NULL; + case EXTENSION_WAL: + strcpy( ext, ".wal" ); + if( ( image = IMG_LoadWAL( buffer ) ) != NULL ) { + goto append; + } + } + + return NULL; + } +#endif - switch( extHash ) { - case EXTENSION_PNG: + switch( extHash ) { + case EXTENSION_PNG: #if USE_PNG - // try *.png - strcpy( ext, ".png" ); - Image_LoadPNG( buffer, &pic, &width, &height ); - if( pic ) { - goto load; - } + // try *.png + strcpy( ext, ".png" ); + IMG_LoadPNG( buffer, &pic, &width, &height ); + if( pic ) { + goto create; + } #endif +#if USE_JPG || USE_TGA for( s = r_texture_formats->string; *s; s++ ) { switch( *s ) { -#if USE_JPEG +#if USE_JPG case 'j': // try *.jpg strcpy( ext, ".jpg" ); - Image_LoadJPG( buffer, &pic, &width, &height ); + IMG_LoadJPG( buffer, &pic, &width, &height ); break; #endif +#if USE_TGA case 't': // try *.tga strcpy( ext, ".tga" ); - Image_LoadTGA( buffer, &pic, &width, &height ); + IMG_LoadTGA( buffer, &pic, &width, &height ); break; } +#endif if( pic ) { - goto load; + goto create; } } +#endif + // try *.pcx + strcpy( ext, ".pcx" ); + IMG_LoadPCX( buffer, &pic, NULL, &width, &height ); + if( pic ) { + flags |= if_paletted; + goto create; + } + return NULL; + + case EXTENSION_TGA: +#if USE_TGA + strcpy( ext, ".tga" ); + IMG_LoadTGA( buffer, &pic, &width, &height ); + if( pic ) { + goto create; + } +#endif - // try *.pcx - strcpy( ext, ".pcx" ); - Image_LoadPCX( buffer, &pic, NULL, &width, &height ); - if( pic ) { - flags |= if_paletted; - goto load; - } - return NULL; - - case EXTENSION_TGA: - strcpy( ext, ".tga" ); - Image_LoadTGA( buffer, &pic, &width, &height ); - if( pic ) { - goto load; - } - +#if USE_PNG || USE_JPG for( s = r_texture_formats->string; *s; s++ ) { switch( *s ) { #if USE_PNG case 'p': // try *.png strcpy( ext, ".png" ); - Image_LoadPNG( buffer, &pic, &width, &height ); + IMG_LoadPNG( buffer, &pic, &width, &height ); break; #endif -#if USE_JPEG +#if USE_JPG case 'j': // try *.jpg strcpy( ext, ".jpg" ); - Image_LoadJPG( buffer, &pic, &width, &height ); + IMG_LoadJPG( buffer, &pic, &width, &height ); break; #endif } if( pic ) { - goto load; + goto create; } } - - // try *.pcx - strcpy( ext, ".pcx" ); - Image_LoadPCX( buffer, &pic, NULL, &width, &height ); - if( pic ) { - flags |= if_paletted; - goto load; - } - return NULL; - - case EXTENSION_JPG: -#if USE_JPEG - strcpy( ext, ".jpg" ); - Image_LoadJPG( buffer, &pic, &width, &height ); - if( pic ) { - goto load; - } +#endif + // try *.pcx + strcpy( ext, ".pcx" ); + IMG_LoadPCX( buffer, &pic, NULL, &width, &height ); + if( pic ) { + flags |= if_paletted; + goto create; + } + return NULL; + + case EXTENSION_JPG: +#if USE_JPG + strcpy( ext, ".jpg" ); + IMG_LoadJPG( buffer, &pic, &width, &height ); + if( pic ) { + goto create; + } #endif +#if USE_PNG || USE_TGA for( s = r_texture_formats->string; *s; s++ ) { switch( *s ) { #if USE_PNG case 'p': // try *.png strcpy( ext, ".png" ); - Image_LoadPNG( buffer, &pic, &width, &height ); + IMG_LoadPNG( buffer, &pic, &width, &height ); break; #endif +#if USE_TGA case 't': // try *.tga strcpy( ext, ".tga" ); - Image_LoadTGA( buffer, &pic, &width, &height ); + IMG_LoadTGA( buffer, &pic, &width, &height ); break; } +#endif if( pic ) { - goto load; + goto create; } } +#endif - - // try *.pcx - strcpy( ext, ".pcx" ); - Image_LoadPCX( buffer, &pic, NULL, &width, &height ); - if( pic ) { - flags |= if_paletted; - goto load; - } - return NULL; + // try *.pcx + strcpy( ext, ".pcx" ); + IMG_LoadPCX( buffer, &pic, NULL, &width, &height ); + if( pic ) { + flags |= if_paletted; + goto create; + } + return NULL; - case EXTENSION_PCX: - strcpy( ext, ".pcx" ); - Image_LoadPCX( buffer, &pic, NULL, &width, &height ); - if( pic ) { - flags |= if_paletted; - goto load; - } + case EXTENSION_PCX: + strcpy( ext, ".pcx" ); + IMG_LoadPCX( buffer, &pic, NULL, &width, &height ); + if( pic ) { + flags |= if_paletted; + goto create; + } +#if USE_PNG || USE_JPG || USE_TGA for( s = r_texture_formats->string; *s; s++ ) { switch( *s ) { #if USE_PNG case 'p': // try *.png strcpy( ext, ".png" ); - Image_LoadPNG( buffer, &pic, &width, &height ); + IMG_LoadPNG( buffer, &pic, &width, &height ); break; #endif -#if USE_JPEG +#if USE_JPG case 'j': // try *.jpg strcpy( ext, ".jpg" ); - Image_LoadJPG( buffer, &pic, &width, &height ); + IMG_LoadJPG( buffer, &pic, &width, &height ); break; #endif +#if USE_TGA case 't': // try *.tga strcpy( ext, ".tga" ); - Image_LoadTGA( buffer, &pic, &width, &height ); + IMG_LoadTGA( buffer, &pic, &width, &height ); break; } - +#endif if( pic ) { - goto load; + goto create; } } +#endif + return NULL; - return NULL; - - case EXTENSION_WAL: - strcpy( ext, ".wal" ); - image = R_LoadWal( buffer ); - if( image ) { - return image; - } + case EXTENSION_WAL: + strcpy( ext, ".wal" ); + if( ( image = IMG_LoadWAL( buffer ) ) != NULL ) { + goto append; + } - // FIXME: no way to figure correct texture dimensions here +#if USE_PNG || USE_JPG || USE_TGA + // FIXME: no way to figure correct texture dimensions here for( s = r_texture_formats->string; *s; s++ ) { switch( *s ) { #if USE_PNG case 'p': // try *.png strcpy( ext, ".png" ); - Image_LoadPNG( buffer, &pic, &width, &height ); + IMG_LoadPNG( buffer, &pic, &width, &height ); break; #endif -#if USE_JPEG +#if USE_JPG case 'j': // try *.jpg strcpy( ext, ".jpg" ); - Image_LoadJPG( buffer, &pic, &width, &height ); + IMG_LoadJPG( buffer, &pic, &width, &height ); break; #endif +#if USE_TGA case 't': // try *.tga strcpy( ext, ".tga" ); - Image_LoadTGA( buffer, &pic, &width, &height ); + IMG_LoadTGA( buffer, &pic, &width, &height ); break; } - +#endif if( pic ) { - goto load; + goto create; } } +#endif + return NULL; - return NULL; + default: + return NULL; + } - default: - return NULL; - +create: + image = IMG_Create( buffer, pic, width, height, type, flags ); +append: + List_Append( &r_imageHash[hash], &image->entry ); + return image; +} + +/* +=============== +IMG_ForHandle +=============== +*/ +image_t *IMG_ForHandle( qhandle_t h ) { + if( h < 0 || h >= r_numImages ) { + Com_Error( ERR_FATAL, "%s: %d out of range", __func__, h ); } -load: - image = R_AllocImageInternal( buffer, hash ); - R_LoadImage( image, pic, width, height, type, flags ); - return image; + return &r_images[h]; } -#else /* TRUECOLOR_RENDERER */ - /* =============== -R_FindImage - -Finds or loads the given image (8 bit) +R_RegisterSkin =============== */ -image_t *R_FindImage( const char *name, imagetype_t type ) { +qhandle_t R_RegisterSkin( const char *name ) { image_t *image; - byte *pic; - int width, height; - char buffer[MAX_QPATH]; - char *ext; - int length; - unsigned hash, extHash; - - if( !name || !name[0] ) { - Com_Error( ERR_FATAL, "R_FindImage: NULL" ); - } - length = strlen( name ); - if( length >= MAX_QPATH ) { - Com_Error( ERR_FATAL, "R_FindImage: oversize name: %d chars", length ); + image = IMG_Find( name, it_skin ); + if( !image ) { + return 0; } - if( length <= 4 ) { - /* must have at least 1 char of basename - * and 4 chars of extension part */ - return NULL; - } + return ( image - r_images ); +} - length -= 4; - if( name[length] != '.' ) { - return NULL; - } - - strcpy( buffer, name ); - Q_strlwr( buffer ); - buffer[length] = 0; +/* +================ +R_RegisterPic +================ +*/ +qhandle_t R_RegisterPic( const char *name ) { + image_t *image; + char fullname[MAX_QPATH]; - hash = Com_HashPath( buffer, RIMAGES_HASH ); + if( name[0] == '*' ) { + image = IMG_Find( name + 1, it_tmp ); + } else if( name[0] == '/' || name[0] == '\\' ) { + image = IMG_Find( name + 1, it_pic ); + } else { + Q_concat( fullname, sizeof( fullname ), "pics/", name, NULL ); + COM_DefaultExtension( fullname, ".pcx", sizeof( fullname ) ); + image = IMG_Find( fullname, it_pic ); + } - if( ( image = R_LookupImage( buffer, type, hash, length ) ) != NULL ) { - image->registration_sequence = registration_sequence; - return image; + if( !image ) { + return 0; } - ext = buffer + length; - extHash = MakeLong( '.', ext[1], ext[2], ext[3] ); + return ( image - r_images ); +} - *ext = '.'; +/* +================ +R_RegisterFont +================ +*/ +qhandle_t R_RegisterFont( const char *name ) { + image_t *image; + char fullname[MAX_QPATH]; - // - // load the pic from disk - // - if( extHash == EXTENSION_JPG || extHash == EXTENSION_TGA || extHash == EXTENSION_PNG ) { - strcpy( ext, ".pcx" ); - extHash = EXTENSION_PCX; - } - if( extHash == EXTENSION_PCX ) { - Image_LoadPCX( buffer, &pic, NULL, &width, &height ); - if( !pic ) { - return NULL; - } - image = R_AllocImageInternal( buffer, hash ); - R_LoadImage( image, pic, width, height, type, if_paletted ); - return image; + if( name[0] == '/' || name[0] == '\\' ) { + image = IMG_Find( name + 1, it_charset ); + } else { + Q_concat( fullname, sizeof( fullname ), "pics/", name, NULL ); + COM_DefaultExtension( fullname, ".pcx", sizeof( fullname ) ); + image = IMG_Find( fullname, it_charset ); } - if( extHash == EXTENSION_WAL ) { - image = R_LoadWal( buffer ); - return image; + if( !image ) { + return 0; } - return NULL; + return ( image - r_images ); } -#endif /* !TRUECOLOR_RENDERER */ - /* ================ -R_FreeUnusedImages +IMG_FreeUnused Any image that was not touched on this registration sequence will be freed. ================ */ -void R_FreeUnusedImages( void ) { - image_t *image, *last; +void IMG_FreeUnused( void ) { + image_t *image, *last; int count = 0; - last = r_images + r_numImages; - for( image = r_images; image != last; image++ ) { - if( image->registration_sequence == registration_sequence ) { -#ifdef SOFTWARE_RENDERER - Com_PageInMemory( image->pixels[0], image->width * image->height * VID_BYTES ); + last = r_images + r_numImages; + for( image = r_images; image < last; image++ ) { + if( image->registration_sequence == registration_sequence ) { +#if SOFTWARE_RENDERER + Com_PageInMemory( image->pixels[0], image->width * image->height * VID_BYTES ); #endif - continue; // used this sequence - } - if( !image->registration_sequence ) - continue; // free image_t slot - if( image->type == it_pic || image->type == it_charset ) - continue; // don't free pics - if( image->flags & if_auto ) { - continue; // don't free auto textures - } - - // delete it from hash table - List_Remove( &image->entry ); - - // free it - R_FreeImage( image ); + continue; // used this sequence + } + if( !image->registration_sequence ) + continue; // free image_t slot + if( image->type == it_pic || image->type == it_charset ) + continue; // don't free pics + if( image->flags & if_auto ) { + continue; // don't free auto textures + } + + // delete it from hash table + List_Remove( &image->entry ); + + // free it + IMG_Unload( image ); memset( image, 0, sizeof( *image ) ); count++; - } + } - Com_DPrintf( "%s: %i images freed\n", __func__, count ); + if( count ) { + Com_DPrintf( "%s: %i images freed\n", __func__, count ); + } } -void R_FreeAllImages( void ) { - image_t *image, *last; +void IMG_FreeAll( void ) { + image_t *image, *last; int i, count = 0; - - last = r_images + r_numImages; - for( image = r_images; image != last; image++ ) { - if( !image->registration_sequence ) - continue; // free image_t slot - // free it - R_FreeImage( image ); - + + last = r_images + r_numImages; + for( image = r_images; image < last; image++ ) { + if( !image->registration_sequence ) + continue; // free image_t slot + // free it + IMG_Unload( image ); + memset( image, 0, sizeof( *image ) ); count++; - } + } - Com_DPrintf( "%s: %i images freed\n", __func__, count ); - - r_numImages = 0; + if( count ) { + Com_DPrintf( "%s: %i images freed\n", __func__, count ); + } + + r_numImages = 0; for( i = 0; i < RIMAGES_HASH; i++ ) { - List_Init( &r_imageHash[i] ); + List_Init( &r_imageHash[i] ); } } /* =============== R_GetPalette + +Reads the palette and (optionally) loads +the colormap for software renderer. =============== */ -void R_GetPalette( byte **dest ) { - int i; - byte *pic, *src; - byte palette[768]; - int width, height; - - /* get the palette */ - Image_LoadPCX( "pics/colormap.pcx", &pic, palette, &width, &height ); - if( !pic ) { - Com_Error( ERR_FATAL, "Couldn't load pics/colormap.pcx" ); - } - - src = palette; - for( i = 0; i < 255; i++ ) { - d_8to24table[i] = MakeColor( src[0], src[1], src[2], 255 ); - src += 3; - } +void IMG_GetPalette( byte **pic ) { + int i; + byte pal[768], *src; + int w, h; - /* 255 is transparent*/ - d_8to24table[i] = MakeColor( src[0], src[1], src[2], 0 ); + // get the palette + if( !IMG_LoadPCX( "pics/colormap.pcx", pic, pal, &w, &h ) ) { + Com_Error( ERR_FATAL, "Couldn't load pics/colormap.pcx" ); + } - if( dest ) { - *dest = R_Malloc( width * height ); - memcpy( *dest, pic, width * height ); - } + for( i = 0, src = pal; i < 255; i++, src += 3 ) { + d_8to24table[i] = MakeColor( src[0], src[1], src[2], 255 ); + } - fs.FreeFile( pic ); + // 255 is transparent + d_8to24table[i] = MakeColor( src[0], src[1], src[2], 0 ); } -void R_InitImageManager( void ) { +void IMG_Init( void ) { int i; -#ifdef TRUECOLOR_RENDERER - r_override_textures = cvar.Get( "r_override_textures", "1", CVAR_ARCHIVE|CVAR_FILES ); - r_texture_formats = cvar.Get( "r_texture_formats", + if( r_numImages ) { + Com_Error( ERR_FATAL, "%s: %d images not freed", __func__, r_numImages ); + } + + +#if USE_PNG || USE_JPG || USE_TGA + r_override_textures = Cvar_Get( "r_override_textures", "1", CVAR_ARCHIVE|CVAR_FILES ); + r_texture_formats = Cvar_Get( "r_texture_formats", #if USE_PNG "p" #endif -#if USE_JPEG +#if USE_JPG "j" #endif - "t", 0 ); +#if USE_TGA + "t", +#endif + 0 ); #endif - cmd.AddCommand( "imagelist", R_ImageList_f ); + Cmd_AddCommand( "imagelist", IMG_List_f ); for( i = 0; i < RIMAGES_HASH; i++ ) { - List_Init( &r_imageHash[i] ); + List_Init( &r_imageHash[i] ); } } -void R_ShutdownImageManager( void ) { - cmd.RemoveCommand( "imagelist" ); +void IMG_Shutdown( void ) { + Cmd_RemoveCommand( "imagelist" ); } |