diff --git a/engine/common/imagelib/imagelib.h b/engine/common/imagelib/imagelib.h index 376ac04d..d0da19c1 100644 --- a/engine/common/imagelib/imagelib.h +++ b/engine/common/imagelib/imagelib.h @@ -91,7 +91,7 @@ typedef struct imglib_s // global parms rgba_t fogParams; // some water textures has info about underwater fog - image_hint_t hint; // hint for some loaders + int hint; // hint for some loaders byte *tempbuffer; // for convert operations int cmd_flags; // global imglib flags int force_flags; // override cmd_flags @@ -171,7 +171,6 @@ rgbdata_t *Image_Quantize( rgbdata_t *pic ); // img_utils.c // void Image_Reset( void ); -rgbdata_t *ImagePack( void ); byte *Image_Copy( size_t size ); void Image_CopyParms( rgbdata_t *src ); qboolean Image_ValidSize( const char *name ); diff --git a/engine/common/imagelib/img_main.c b/engine/common/imagelib/img_main.c index 51c4b0ac..230d5520 100644 --- a/engine/common/imagelib/img_main.c +++ b/engine/common/imagelib/img_main.c @@ -110,20 +110,21 @@ void Image_Reset( void ) image.size = 0; } -rgbdata_t *ImagePack( void ) +static rgbdata_t *ImagePack( void ) { - rgbdata_t *pack = Mem_Calloc( host.imagepool, sizeof( rgbdata_t )); + rgbdata_t *pack; // clear any force flags image.force_flags = 0; if( image.cubemap && image.num_sides != 6 ) { - // this never be happens, just in case - FS_FreeImage( pack ); + // this never can happen, just in case return NULL; } + pack = Mem_Calloc( host.imagepool, sizeof( *pack )); + if( image.cubemap ) { image.flags |= IMAGE_CUBEMAP; @@ -163,7 +164,7 @@ FS_AddSideToPack ================ */ -qboolean FS_AddSideToPack( const char *name, int adjust_flags ) +static qboolean FS_AddSideToPack( int adjust_flags ) { byte *out, *flipped; qboolean resampled = false; @@ -203,6 +204,88 @@ qboolean FS_AddSideToPack( const char *name, int adjust_flags ) return true; } +static const loadpixformat_t *Image_GetLoadFormatForExtension( const char *ext ) +{ + const loadpixformat_t *format; + + if( !COM_CheckStringEmpty( ext )) + return NULL; + + for( format = image.loadformats; format->formatstring; format++ ) + { + if( !Q_stricmp( ext, format->ext )) + return format; + } + + return NULL; +} + +static qboolean Image_ProbeLoadBuffer_( const loadpixformat_t *fmt, const char *name, const byte *buf, size_t size, int override_hint ) +{ + if( override_hint > 0 ) + image.hint = override_hint; + else image.hint = fmt->hint; + + return fmt->loadfunc( name, buf, size ); +} + +static qboolean Image_ProbeLoadBuffer( const loadpixformat_t *fmt, const char *name, const byte *buf, size_t size, int override_hint ) +{ + if( size <= 0 ) + return false; + + // bruteforce all loaders + if( !fmt ) + { + for( fmt = image.loadformats; fmt->formatstring; fmt++ ) + { + if( Image_ProbeLoadBuffer_( fmt, name, buf, size, override_hint )) + return true; + } + + return false; + } + + return Image_ProbeLoadBuffer_( fmt, name, buf, size, override_hint ); +} + +static qboolean Image_ProbeLoad_( const loadpixformat_t *fmt, const char *name, const char *suffix, int override_hint ) +{ + qboolean success = false; + fs_offset_t filesize; + string path; + byte *f; + + Q_snprintf( path, sizeof( path ), fmt->formatstring, name, suffix, fmt->ext ); + f = FS_LoadFile( path, &filesize, false ); + + if( f ) + { + success = Image_ProbeLoadBuffer( fmt, path, f, filesize, override_hint ); + + Mem_Free( f ); + } + + return success; +} + +static qboolean Image_ProbeLoad( const loadpixformat_t *fmt, const char *name, const char *suffix, int override_hint ) +{ + if( !fmt ) + { + // bruteforce all formats to allow implicit extension + for( fmt = image.loadformats; fmt->formatstring; fmt++ ) + { + if( Image_ProbeLoad_( fmt, name, suffix, override_hint )) + return true; + } + + return false; + } + + return Image_ProbeLoad_( fmt, name, suffix, override_hint ); +} + /* ================ FS_LoadImage @@ -213,87 +296,35 @@ loading and unpack to rgba any known image rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) { const char *ext = COM_FileExtension( filename ); - string path, loadname, sidename; - qboolean anyformat = true; + string loadname; int i; - fs_offset_t filesize = 0; - const loadpixformat_t *format; + const loadpixformat_t *extfmt; const cubepack_t *cmap; - byte *f; Q_strncpy( loadname, filename, sizeof( loadname )); Image_Reset(); // clear old image - if( COM_CheckStringEmpty( ext )) - { - // we needs to compare file extension with list of supported formats - // and be sure what is real extension, not a filename with dot - for( format = image.loadformats; format && format->formatstring; format++ ) - { - if( !Q_stricmp( format->ext, ext )) - { - COM_StripExtension( loadname ); - anyformat = false; - break; - } - } - } + // we needs to compare file extension with list of supported formats + // and be sure what is real extension, not a filename with dot + if(( extfmt = Image_GetLoadFormatForExtension( ext ))) + COM_StripExtension( loadname ); // special mode: skip any checks, load file from buffer if( filename[0] == '#' && buffer && size ) goto load_internal; - // now try all the formats in the selected list - for( format = image.loadformats; format && format->formatstring; format++) - { - if( anyformat || !Q_stricmp( ext, format->ext )) - { - Q_sprintf( path, format->formatstring, loadname, "", format->ext ); - image.hint = format->hint; - f = FS_LoadFile( path, &filesize, false ); - - if( f && filesize > 0 ) - { - if( format->loadfunc( path, f, filesize )) - { - Mem_Free( f ); // release buffer - return ImagePack(); // loaded - } - else Mem_Free( f ); // release buffer - } - } - } + if( Image_ProbeLoad( extfmt, loadname, "", -1 )) + return ImagePack(); // check all cubemap sides with package suffix for( cmap = load_cubemap; cmap && cmap->type; cmap++ ) { for( i = 0; i < 6; i++ ) { - // for support mixed cubemaps e.g. sky_ft.bmp, sky_rt.tga - // NOTE: all loaders must keep sides in one format for all - for( format = image.loadformats; format && format->formatstring; format++ ) + if( Image_ProbeLoad( extfmt, loadname, cmap->type[i].suf, cmap->type[i].hint ) && + FS_AddSideToPack( cmap->type[i].flags )) // process flags to flip some sides { - if( anyformat || !Q_stricmp( ext, format->ext )) - { - Q_sprintf( path, format->formatstring, loadname, cmap->type[i].suf, format->ext ); - image.hint = (image_hint_t)cmap->type[i].hint; // side hint - - f = FS_LoadFile( path, &filesize, false ); - if( f && filesize > 0 ) - { - // this name will be used only for tell user about problems - if( format->loadfunc( path, f, filesize )) - { - Q_snprintf( sidename, sizeof( sidename ), "%s%s.%s", loadname, cmap->type[i].suf, format->ext ); - if( FS_AddSideToPack( sidename, cmap->type[i].flags )) // process flags to flip some sides - { - Mem_Free( f ); - break; // loaded - } - } - Mem_Free( f ); - } - } + break; } if( image.num_sides != i + 1 ) // check side @@ -323,20 +354,13 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) return ImagePack(); // all done load_internal: - for( format = image.loadformats; format && format->formatstring; format++ ) + if( buffer && size ) { - if( anyformat || !Q_stricmp( ext, format->ext )) - { - image.hint = format->hint; - if( buffer && size > 0 ) - { - if( format->loadfunc( loadname, buffer, size )) - return ImagePack(); // loaded - } - } + if( Image_ProbeLoadBuffer( extfmt, loadname, buffer, size, -1 )) + return ImagePack(); } - if( filename[0] != '#' ) + if( loadname[0] != '#' ) Con_Reportf( S_WARN "FS_LoadImage: couldn't load \"%s\"\n", loadname ); // clear any force flags @@ -345,6 +369,8 @@ load_internal: return NULL; } + + /* ================ Image_Save