engine: imagelib: refactor image loading function

This commit is contained in:
Alibek Omarov 2022-12-05 03:18:27 +03:00
parent eabbd0061f
commit ccf7619ae5
2 changed files with 106 additions and 81 deletions

View File

@ -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 );

View File

@ -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