|
|
@ -110,20 +110,21 @@ void Image_Reset( void ) |
|
|
|
image.size = 0; |
|
|
|
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
|
|
|
|
// clear any force flags
|
|
|
|
image.force_flags = 0; |
|
|
|
image.force_flags = 0; |
|
|
|
|
|
|
|
|
|
|
|
if( image.cubemap && image.num_sides != 6 ) |
|
|
|
if( image.cubemap && image.num_sides != 6 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// this never be happens, just in case
|
|
|
|
// this never can happen, just in case
|
|
|
|
FS_FreeImage( pack ); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pack = Mem_Calloc( host.imagepool, sizeof( *pack )); |
|
|
|
|
|
|
|
|
|
|
|
if( image.cubemap ) |
|
|
|
if( image.cubemap ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
image.flags |= 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; |
|
|
|
byte *out, *flipped; |
|
|
|
qboolean resampled = false; |
|
|
|
qboolean resampled = false; |
|
|
@ -203,6 +204,88 @@ qboolean FS_AddSideToPack( const char *name, int adjust_flags ) |
|
|
|
return true; |
|
|
|
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 |
|
|
|
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 ) |
|
|
|
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
const char *ext = COM_FileExtension( filename ); |
|
|
|
const char *ext = COM_FileExtension( filename ); |
|
|
|
string path, loadname, sidename; |
|
|
|
string loadname; |
|
|
|
qboolean anyformat = true; |
|
|
|
|
|
|
|
int i; |
|
|
|
int i; |
|
|
|
fs_offset_t filesize = 0; |
|
|
|
const loadpixformat_t *extfmt; |
|
|
|
const loadpixformat_t *format; |
|
|
|
|
|
|
|
const cubepack_t *cmap; |
|
|
|
const cubepack_t *cmap; |
|
|
|
byte *f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Q_strncpy( loadname, filename, sizeof( loadname )); |
|
|
|
Q_strncpy( loadname, filename, sizeof( loadname )); |
|
|
|
Image_Reset(); // clear old image
|
|
|
|
Image_Reset(); // clear old image
|
|
|
|
|
|
|
|
|
|
|
|
if( COM_CheckStringEmpty( ext )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// we needs to compare file extension with list of supported formats
|
|
|
|
// we needs to compare file extension with list of supported formats
|
|
|
|
// and be sure what is real extension, not a filename with dot
|
|
|
|
// and be sure what is real extension, not a filename with dot
|
|
|
|
for( format = image.loadformats; format && format->formatstring; format++ ) |
|
|
|
if(( extfmt = Image_GetLoadFormatForExtension( ext ))) |
|
|
|
{ |
|
|
|
|
|
|
|
if( !Q_stricmp( format->ext, ext )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
COM_StripExtension( loadname ); |
|
|
|
COM_StripExtension( loadname ); |
|
|
|
anyformat = false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// special mode: skip any checks, load file from buffer
|
|
|
|
// special mode: skip any checks, load file from buffer
|
|
|
|
if( filename[0] == '#' && buffer && size ) |
|
|
|
if( filename[0] == '#' && buffer && size ) |
|
|
|
goto load_internal; |
|
|
|
goto load_internal; |
|
|
|
|
|
|
|
|
|
|
|
// now try all the formats in the selected list
|
|
|
|
if( Image_ProbeLoad( extfmt, loadname, "", -1 )) |
|
|
|
for( format = image.loadformats; format && format->formatstring; format++) |
|
|
|
return ImagePack(); |
|
|
|
{ |
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check all cubemap sides with package suffix
|
|
|
|
// check all cubemap sides with package suffix
|
|
|
|
for( cmap = load_cubemap; cmap && cmap->type; cmap++ ) |
|
|
|
for( cmap = load_cubemap; cmap && cmap->type; cmap++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for( i = 0; i < 6; i++ ) |
|
|
|
for( i = 0; i < 6; i++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// for support mixed cubemaps e.g. sky_ft.bmp, sky_rt.tga
|
|
|
|
if( Image_ProbeLoad( extfmt, loadname, cmap->type[i].suf, cmap->type[i].hint ) && |
|
|
|
// NOTE: all loaders must keep sides in one format for all
|
|
|
|
FS_AddSideToPack( cmap->type[i].flags )) // process flags to flip some sides
|
|
|
|
for( format = image.loadformats; format && format->formatstring; format++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if( anyformat || !Q_stricmp( ext, format->ext )) |
|
|
|
break; |
|
|
|
{ |
|
|
|
|
|
|
|
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 ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( image.num_sides != i + 1 ) // check side
|
|
|
|
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
|
|
|
|
return ImagePack(); // all done
|
|
|
|
|
|
|
|
|
|
|
|
load_internal: |
|
|
|
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( Image_ProbeLoadBuffer( extfmt, loadname, buffer, size, -1 )) |
|
|
|
if( buffer && size > 0 ) |
|
|
|
return ImagePack(); |
|
|
|
{ |
|
|
|
|
|
|
|
if( format->loadfunc( loadname, buffer, size )) |
|
|
|
|
|
|
|
return ImagePack(); // loaded
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( filename[0] != '#' ) |
|
|
|
if( loadname[0] != '#' ) |
|
|
|
Con_Reportf( S_WARN "FS_LoadImage: couldn't load \"%s\"\n", loadname ); |
|
|
|
Con_Reportf( S_WARN "FS_LoadImage: couldn't load \"%s\"\n", loadname ); |
|
|
|
|
|
|
|
|
|
|
|
// clear any force flags
|
|
|
|
// clear any force flags
|
|
|
@ -345,6 +369,8 @@ load_internal: |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
================ |
|
|
|
================ |
|
|
|
Image_Save |
|
|
|
Image_Save |
|
|
|