X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=tools%2Fquake3%2Fq3map2%2Fimage.c;h=5ab1d48b1c1a4799b295564851401d751a93a6e0;hp=929b15d96cf5ec6c5e256955c16d0b40f0d9fdda;hb=7fc621fc78d0e040dc2c12f38dc53dd9048215dc;hpb=806e3fe1c8297febd69d0d59a2b91d929ba521fe diff --git a/tools/quake3/q3map2/image.c b/tools/quake3/q3map2/image.c index 929b15d9..5ab1d48b 100644 --- a/tools/quake3/q3map2/image.c +++ b/tools/quake3/q3map2/image.c @@ -1,30 +1,30 @@ /* ------------------------------------------------------------------------------- -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. + Copyright (C) 1999-2007 id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ----------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------- -This code has been altered significantly from its original form, to support -several games based on the Quake III Arena engine, in the form of "Q3Map2." + This code has been altered significantly from its original form, to support + several games based on the Quake III Arena engine, in the form of "Q3Map2." -------------------------------------------------------------------------------- */ + ------------------------------------------------------------------------------- */ @@ -40,50 +40,48 @@ several games based on the Quake III Arena engine, in the form of "Q3Map2." /* ------------------------------------------------------------------------------- -this file contains image pool management with reference counting. note: it isn't -reentrant, so only call it from init/shutdown code or wrap calls in a mutex + this file contains image pool management with reference counting. note: it isn't + reentrant, so only call it from init/shutdown code or wrap calls in a mutex -------------------------------------------------------------------------------- */ + ------------------------------------------------------------------------------- */ /* -LoadDDSBuffer() -loads a dxtc (1, 3, 5) dds buffer into a valid rgba image -*/ + LoadDDSBuffer() + loads a dxtc (1, 3, 5) dds buffer into a valid rgba image + */ + +static void LoadDDSBuffer( byte *buffer, int size, byte **pixels, int *width, int *height ){ + int w, h; + ddsPF_t pf; + -static void LoadDDSBuffer( byte *buffer, int size, byte **pixels, int *width, int *height ) -{ - int w, h; - ddsPF_t pf; - - /* dummy check */ - if( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL ) + if ( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL ) { return; - + } + /* null out */ *pixels = 0; *width = 0; *height = 0; - + /* get dds info */ - if( DDSGetInfo( (ddsBuffer_t*) buffer, &w, &h, &pf ) ) - { + if ( DDSGetInfo( (ddsBuffer_t*) buffer, &w, &h, &pf ) ) { Sys_Printf( "WARNING: Invalid DDS texture\n" ); return; } - + /* only certain types of dds textures are supported */ - if( pf != DDS_PF_ARGB8888 && pf != DDS_PF_DXT1 && pf != DDS_PF_DXT3 && pf != DDS_PF_DXT5 ) - { + if ( pf != DDS_PF_ARGB8888 && pf != DDS_PF_DXT1 && pf != DDS_PF_DXT3 && pf != DDS_PF_DXT5 ) { Sys_Printf( "WARNING: Only DDS texture formats ARGB8888, DXT1, DXT3, and DXT5 are supported (%d)\n", pf ); return; } - + /* create image pixel buffer */ *width = w; *height = h; *pixels = safe_malloc( w * h * 4 ); - + /* decompress the dds texture */ DDSDecompress( (ddsBuffer_t*) buffer, *pixels ); } @@ -91,25 +89,24 @@ static void LoadDDSBuffer( byte *buffer, int size, byte **pixels, int *width, in /* -PNGReadData() -callback function for libpng to read from a memory buffer -note: this function is a total hack, as it reads/writes the png struct directly! -*/ + PNGReadData() + callback function for libpng to read from a memory buffer + note: this function is a total hack, as it reads/writes the png struct directly! + */ typedef struct pngBuffer_s { - byte *buffer; - png_size_t size, offset; -} -pngBuffer_t; + byte *buffer; + png_size_t size, offset; +} pngBuffer_t; -void PNGReadData( png_struct *png, png_byte *buffer, png_size_t size ) -{ - pngBuffer_t *pb = (pngBuffer_t*) png_get_io_ptr( png ); - - - if( (pb->offset + size) > pb->size ) - size = (pb->size - pb->offset); +void PNGReadData( png_struct *png, png_byte *buffer, png_size_t size ){ + pngBuffer_t *pb = (pngBuffer_t*) png_get_io_ptr( png ); + + + if ( ( pb->offset + size ) > pb->size ) { + size = ( pb->size - pb->offset ); + } memcpy( buffer, &pb->buffer[ pb->offset ], size ); pb->offset += size; //% Sys_Printf( "Copying %d bytes from 0x%08X to 0x%08X (offset: %d of %d)\n", size, &pb->buffer[ pb->offset ], buffer, pb->offset, pb->size ); @@ -118,139 +115,132 @@ void PNGReadData( png_struct *png, png_byte *buffer, png_size_t size ) /* -LoadPNGBuffer() -loads a png file buffer into a valid rgba image -*/ + LoadPNGBuffer() + loads a png file buffer into a valid rgba image + */ + +static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, int *height ){ + png_struct *png; + png_info *info, *end; + pngBuffer_t pb; + //pngBuffer_t *pb = (pngBuffer_t*) png_get_io_ptr( png ); + int bitDepth, colorType; + png_uint_32 w, h, i; + byte **rowPointers; -static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, int *height ) -{ - png_struct *png; - png_info *info, *end; - pngBuffer_t pb; - int bitDepth, colorType, channels; - png_uint_32 w, h, i; - byte **rowPointers; - - /* dummy check */ - if( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL ) + if ( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL ) { return; - + } + /* null out */ *pixels = 0; *width = 0; *height = 0; - + /* determine if this is a png file */ - if( png_sig_cmp( buffer, 0, 8 ) != 0 ) - { + if ( png_sig_cmp( buffer, 0, 8 ) != 0 ) { Sys_Printf( "WARNING: Invalid PNG file\n" ); return; } - + /* create png structs */ png = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); - if( png == NULL ) - { + if ( png == NULL ) { Sys_Printf( "WARNING: Unable to create PNG read struct\n" ); return; } - + info = png_create_info_struct( png ); - if( info == NULL ) - { + if ( info == NULL ) { Sys_Printf( "WARNING: Unable to create PNG info struct\n" ); png_destroy_read_struct( &png, NULL, NULL ); return; } - + end = png_create_info_struct( png ); - if( end == NULL ) - { + if ( end == NULL ) { Sys_Printf( "WARNING: Unable to create PNG end info struct\n" ); png_destroy_read_struct( &png, &info, NULL ); return; } - + /* set read callback */ pb.buffer = buffer; pb.size = size; pb.offset = 0; png_set_read_fn( png, &pb, PNGReadData ); - png->io_ptr = &pb; /* hack! */ - + //png->io_ptr = &pb; /* hack! */ + /* set error longjmp */ - if( setjmp( png->jmpbuf ) ) - { + if ( setjmp( png_jmpbuf(png) ) ) { Sys_Printf( "WARNING: An error occurred reading PNG image\n" ); png_destroy_read_struct( &png, &info, &end ); return; } - + /* fixme: add proper i/o stuff here */ /* read png info */ png_read_info( png, info ); - + /* read image header chunk */ png_get_IHDR( png, info, - &w, &h, &bitDepth, &colorType, NULL, NULL, NULL ); - - /* read number of channels */ - channels = png_get_channels( png, info ); - + &w, &h, &bitDepth, &colorType, NULL, NULL, NULL ); + /* the following will probably bork on certain types of png images, but hey... */ /* force indexed/gray/trans chunk to rgb */ - if( (colorType == PNG_COLOR_TYPE_PALETTE && bitDepth <= 8) || - (colorType == PNG_COLOR_TYPE_GRAY && bitDepth <= 8) || - png_get_valid( png, info, PNG_INFO_tRNS ) ) + if ( ( colorType == PNG_COLOR_TYPE_PALETTE && bitDepth <= 8 ) || + ( colorType == PNG_COLOR_TYPE_GRAY && bitDepth <= 8 ) || + png_get_valid( png, info, PNG_INFO_tRNS ) ) { png_set_expand( png ); - + } + /* strip 16bpc -> 8bpc */ - if( bitDepth == 16 ) + if ( bitDepth == 16 ) { png_set_strip_16( png ); - + } + /* pad rgb to rgba */ - if( bitDepth == 8 && colorType == PNG_COLOR_TYPE_RGB) + if ( bitDepth == 8 && colorType == PNG_COLOR_TYPE_RGB ) { png_set_filler( png, 255, PNG_FILLER_AFTER ); - + } + /* create image pixel buffer */ *width = w; *height = h; *pixels = safe_malloc( w * h * 4 ); - + /* create row pointers */ rowPointers = safe_malloc( h * sizeof( byte* ) ); - for( i = 0; i < h; i++ ) - rowPointers[ i ] = *pixels + (i * w * 4); - + for ( i = 0; i < h; i++ ) + rowPointers[ i ] = *pixels + ( i * w * 4 ); + /* read the png */ png_read_image( png, rowPointers ); - + /* clean up */ free( rowPointers ); png_destroy_read_struct( &png, &info, &end ); - + } /* -ImageInit() -implicitly called by every function to set up image list -*/ + ImageInit() + implicitly called by every function to set up image list + */ -static void ImageInit( void ) -{ - int i; - - - if( numImages <= 0 ) - { +static void ImageInit( void ){ + int i; + + + if ( numImages <= 0 ) { /* clear images (fixme: this could theoretically leak) */ memset( images, 0, sizeof( images ) ); - + /* generate *bogus image */ images[ 0 ].name = safe_malloc( strlen( DEFAULT_IMAGE ) + 1 ); strcpy( images[ 0 ].name, DEFAULT_IMAGE ); @@ -260,7 +250,7 @@ static void ImageInit( void ) images[ 0 ].height = 64; images[ 0 ].refCount = 1; images[ 0 ].pixels = safe_malloc( 64 * 64 * 4 ); - for( i = 0; i < (64 * 64 * 4); i++ ) + for ( i = 0; i < ( 64 * 64 * 4 ); i++ ) images[ 0 ].pixels[ i ] = 255; } } @@ -268,27 +258,28 @@ static void ImageInit( void ) /* -ImageFree() -frees an rgba image -*/ + ImageFree() + frees an rgba image + */ -void ImageFree( image_t *image ) -{ +void ImageFree( image_t *image ){ /* dummy check */ - if( image == NULL ) + if ( image == NULL ) { return; - + } + /* decrement refcount */ image->refCount--; - + /* free? */ - if( image->refCount <= 0 ) - { - if( image->name != NULL ) + if ( image->refCount <= 0 ) { + if ( image->name != NULL ) { free( image->name ); + } image->name = NULL; - if( image->filename != NULL ) + if ( image->filename != NULL ) { free( image->filename ); + } image->filename = NULL; free( image->pixels ); image->width = 0; @@ -300,34 +291,35 @@ void ImageFree( image_t *image ) /* -ImageFind() -finds an existing rgba image and returns a pointer to the image_t struct or NULL if not found -*/ + ImageFind() + finds an existing rgba image and returns a pointer to the image_t struct or NULL if not found + */ + +image_t *ImageFind( const char *filename ){ + int i; + char name[ 1024 ]; + -image_t *ImageFind( const char *filename ) -{ - int i; - char name[ 1024 ]; - - /* init */ ImageInit(); - + /* dummy check */ - if( filename == NULL || filename[ 0 ] == '\0' ) + if ( filename == NULL || filename[ 0 ] == '\0' ) { return NULL; - + } + /* strip file extension off name */ strcpy( name, filename ); StripExtension( name ); - + /* search list */ - for( i = 0; i < MAX_IMAGES; i++ ) + for ( i = 0; i < MAX_IMAGES; i++ ) { - if( images[ i ].name != NULL && !strcmp( name, images[ i ].name ) ) + if ( images[ i ].name != NULL && !strcmp( name, images[ i ].name ) ) { return &images[ i ]; + } } - + /* no matching image found */ return NULL; } @@ -335,82 +327,83 @@ image_t *ImageFind( const char *filename ) /* -ImageLoad() -loads an rgba image and returns a pointer to the image_t struct or NULL if not found -*/ + ImageLoad() + loads an rgba image and returns a pointer to the image_t struct or NULL if not found + */ + +image_t *ImageLoad( const char *filename ){ + int i; + image_t *image; + char name[ 1024 ]; + int size; + byte *buffer = NULL; + qboolean alphaHack = qfalse; + -image_t *ImageLoad( const char *filename ) -{ - int i; - image_t *image; - char name[ 1024 ]; - int size; - byte *buffer = NULL; - qboolean alphaHack = qfalse; - - /* init */ ImageInit(); - + /* dummy check */ - if( filename == NULL || filename[ 0 ] == '\0' ) + if ( filename == NULL || filename[ 0 ] == '\0' ) { return NULL; - + } + /* strip file extension off name */ strcpy( name, filename ); StripExtension( name ); - + /* try to find existing image */ image = ImageFind( name ); - if( image != NULL ) - { + if ( image != NULL ) { image->refCount++; return image; } - + /* none found, so find first non-null image */ image = NULL; - for( i = 0; i < MAX_IMAGES; i++ ) + for ( i = 0; i < MAX_IMAGES; i++ ) { - if( images[ i ].name == NULL ) - { + if ( images[ i ].name == NULL ) { image = &images[ i ]; break; } } - + /* too many images? */ - if( image == NULL ) + if ( image == NULL ) { Error( "MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES ); - + } + /* set it up */ image->name = safe_malloc( strlen( name ) + 1 ); strcpy( image->name, name ); - + /* attempt to load tga */ StripExtension( name ); strcat( name, ".tga" ); size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 ); - if( size > 0 ) + if ( size > 0 ) { LoadTGABuffer( buffer, buffer + size, &image->pixels, &image->width, &image->height ); + } else { /* attempt to load png */ StripExtension( name ); strcat( name, ".png" ); size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 ); - if( size > 0 ) + if ( size > 0 ) { LoadPNGBuffer( buffer, size, &image->pixels, &image->width, &image->height ); + } else { /* attempt to load jpg */ StripExtension( name ); strcat( name, ".jpg" ); size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 ); - if( size > 0 ) - { - if( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL ) + if ( size > 0 ) { + if ( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL ) { Sys_Printf( "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels ); + } alphaHack = qtrue; } else @@ -419,18 +412,16 @@ image_t *ImageLoad( const char *filename ) StripExtension( name ); strcat( name, ".dds" ); size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 ); - if( size > 0 ) - { + if ( size > 0 ) { LoadDDSBuffer( buffer, size, &image->pixels, &image->width, &image->height ); - + /* debug code */ #if 1 { - ddsPF_t pf; + ddsPF_t pf; DDSGetInfo( (ddsBuffer_t*) buffer, NULL, NULL, &pf ); Sys_Printf( "pf = %d\n", pf ); - if( image->width > 0 ) - { + if ( image->width > 0 ) { StripExtension( name ); strcat( name, "_converted.tga" ); WriteTGA( "C:\\games\\quake3\\baseq3\\textures\\rad\\dds_converted.tga", image->pixels, image->width, image->height ); @@ -441,52 +432,47 @@ image_t *ImageLoad( const char *filename ) } } } - + /* free file buffer */ free( buffer ); - + /* make sure everything's kosher */ - if( size <= 0 || image->width <= 0 || image->height <= 0 || image->pixels == NULL ) - { + if ( size <= 0 || image->width <= 0 || image->height <= 0 || image->pixels == NULL ) { //% Sys_Printf( "size = %d width = %d height = %d pixels = 0x%08x (%s)\n", //% size, image->width, image->height, image->pixels, name ); free( image->name ); image->name = NULL; return NULL; } - + /* set filename */ image->filename = safe_malloc( strlen( name ) + 1 ); strcpy( image->filename, name ); - + /* set count */ image->refCount = 1; numImages++; - if(alphaHack) - { + if ( alphaHack ) { StripExtension( name ); strcat( name, "_alpha.jpg" ); size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 ); - if( size > 0 ) - { + if ( size > 0 ) { unsigned char *pixels; int width, height; - if( LoadJPGBuff( buffer, size, &pixels, &width, &height ) == -1 && pixels != NULL ) + if ( LoadJPGBuff( buffer, size, &pixels, &width, &height ) == -1 && pixels != NULL ) { Sys_Printf( "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels ); - if(pixels && width == image->width && height == image->height) - { + } + if ( pixels && width == image->width && height == image->height ) { int i; - for(i = 0; i < width*height; ++i) - image->pixels[4*i+3] = pixels[4*i+2]; // copy alpha from blue channel + for ( i = 0; i < width * height; ++i ) + image->pixels[4 * i + 3] = pixels[4 * i + 2]; // copy alpha from blue channel } - free(pixels); - free(buffer); + free( pixels ); + free( buffer ); } } - + /* return the image */ return image; } - -