summaryrefslogtreecommitdiff
path: root/source/r_images.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/r_images.c')
-rw-r--r--source/r_images.c2290
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" );
}