* unlimit MAX_IMAGES
This commit is contained in:
parent
2602c48a18
commit
9660fbb6f1
|
|
@ -1127,7 +1127,7 @@ void LoadTGA( const char *name, byte **pixels, int *width, int *height ){
|
|||
WriteTGA
|
||||
================
|
||||
*/
|
||||
void WriteTGA( const char *filename, byte *data, int width, int height ) {
|
||||
void WriteTGA( const char *filename, const byte *data, int width, int height ) {
|
||||
byte *buffer;
|
||||
int i;
|
||||
int c;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ void Save256Image( const char *name, byte *pixels, byte *palette,
|
|||
|
||||
void LoadTGA( const char *filename, byte **pixels, int *width, int *height );
|
||||
void LoadTGABuffer( const byte *buffer, const byte* enddata, byte **pic, int *width, int *height );
|
||||
void WriteTGA( const char *filename, byte *data, int width, int height );
|
||||
void WriteTGA( const char *filename, const byte *data, int width, int height );
|
||||
void WriteTGAGray( const char *filename, byte *data, int width, int height );
|
||||
int LoadJPGBuff( void *src_buffer, int src_size, unsigned char **pic, int *width, int *height );
|
||||
|
||||
|
|
|
|||
|
|
@ -246,8 +246,8 @@ static void ConvertShader( FILE *f, const bspShader_t& shader ){
|
|||
}
|
||||
|
||||
/* set bitmap filename */
|
||||
if ( si->shaderImage->filename[ 0 ] != '*' ) {
|
||||
strcpy( filename, si->shaderImage->filename );
|
||||
if ( si->shaderImage->filename.c_str()[ 0 ] != '*' ) {
|
||||
strcpy( filename, si->shaderImage->filename.c_str() );
|
||||
}
|
||||
else{
|
||||
sprintf( filename, "%s.tga", si->shader.c_str() );
|
||||
|
|
|
|||
|
|
@ -155,8 +155,8 @@ static void ConvertShaderToMTL( FILE *f, const bspShader_t& shader ){
|
|||
}
|
||||
|
||||
/* set bitmap filename */
|
||||
if ( si->shaderImage->filename[ 0 ] != '*' ) {
|
||||
strcpy( filename, si->shaderImage->filename );
|
||||
if ( si->shaderImage->filename.c_str()[ 0 ] != '*' ) {
|
||||
strcpy( filename, si->shaderImage->filename.c_str() );
|
||||
}
|
||||
else{
|
||||
sprintf( filename, "%s.tga", si->shader.c_str() );
|
||||
|
|
|
|||
|
|
@ -223,57 +223,18 @@ static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, in
|
|||
|
||||
|
||||
|
||||
/*
|
||||
ImageInit()
|
||||
implicitly called by every function to set up image list
|
||||
*/
|
||||
static std::forward_list<image_t> images;
|
||||
|
||||
static void ImageInit( void ){
|
||||
if ( numImages <= 0 ) {
|
||||
/* clear images (fixme: this could theoretically leak) */
|
||||
memset( images, 0, sizeof( images ) );
|
||||
|
||||
/* generate *bogus image */
|
||||
images[ 0 ].name = copystring( DEFAULT_IMAGE );
|
||||
images[ 0 ].filename = copystring( DEFAULT_IMAGE );
|
||||
images[ 0 ].width = 64;
|
||||
images[ 0 ].height = 64;
|
||||
images[ 0 ].refCount = 1;
|
||||
images[ 0 ].pixels = safe_malloc( 64 * 64 * 4 );
|
||||
memset( images[ 0 ].pixels, 255, 64 * 64 * 4 );
|
||||
static struct construct_default_image
|
||||
{
|
||||
construct_default_image(){
|
||||
image_t img;
|
||||
img.name = img.filename = DEFAULT_IMAGE;
|
||||
img.width = img.height = 64;
|
||||
img.pixels = void_ptr( memset( safe_malloc( 64 * 64 * 4 ), 255, 64 * 64 * 4 ) );
|
||||
images.emplace_front( std::move( img ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ImageFree()
|
||||
frees an rgba image
|
||||
*/
|
||||
|
||||
void ImageFree( image_t *image ){
|
||||
/* dummy check */
|
||||
if ( image == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* decrement refcount */
|
||||
image->refCount--;
|
||||
|
||||
/* free? */
|
||||
if ( image->refCount <= 0 ) {
|
||||
free( image->name );
|
||||
image->name = NULL;
|
||||
free( image->filename );
|
||||
image->filename = NULL;
|
||||
free( image->pixels );
|
||||
image->width = 0;
|
||||
image->height = 0;
|
||||
numImages--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} s_construct_default_image;
|
||||
|
||||
/*
|
||||
ImageFind()
|
||||
|
|
@ -281,20 +242,17 @@ void ImageFree( image_t *image ){
|
|||
name is name without extension, as in images[ i ].name
|
||||
*/
|
||||
|
||||
image_t *ImageFind( const char *name ){
|
||||
/* init */
|
||||
ImageInit();
|
||||
|
||||
static const image_t *ImageFind( const char *name ){
|
||||
/* dummy check */
|
||||
if ( strEmptyOrNull( name ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* search list */
|
||||
for ( int i = 0; i < MAX_IMAGES; ++i )
|
||||
for ( const auto& img : images )
|
||||
{
|
||||
if ( images[ i ].name != NULL && strEqual( name, images[ i ].name ) ) {
|
||||
return &images[ i ];
|
||||
if ( striEqual( name, img.name.c_str() ) ) {
|
||||
return &img;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -310,89 +268,70 @@ image_t *ImageFind( const char *name ){
|
|||
expects extensionless path as input
|
||||
*/
|
||||
|
||||
image_t *ImageLoad( const char *filename ){
|
||||
image_t *image;
|
||||
char name[ 1024 ];
|
||||
const image_t *ImageLoad( const char *name ){
|
||||
/* dummy check */
|
||||
if ( strEmptyOrNull( name ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* try to find existing image */
|
||||
if ( auto img = ImageFind( name ) ) {
|
||||
return img;
|
||||
}
|
||||
|
||||
/* none found, so let's create a new one */
|
||||
image_t image;
|
||||
char filename[ 1024 ];
|
||||
int size;
|
||||
byte *buffer = NULL;
|
||||
bool alphaHack = false;
|
||||
|
||||
|
||||
/* init */
|
||||
ImageInit();
|
||||
|
||||
/* dummy check */
|
||||
if ( strEmptyOrNull( filename ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy( name, filename );
|
||||
|
||||
/* try to find existing image */
|
||||
image = ImageFind( name );
|
||||
if ( image != NULL ) {
|
||||
image->refCount++;
|
||||
return image;
|
||||
}
|
||||
|
||||
/* none found, so find first empty image slot */
|
||||
for ( int i = 0; i < MAX_IMAGES; ++i )
|
||||
{
|
||||
if ( images[ i ].name == NULL ) {
|
||||
image = &images[ i ];
|
||||
image->name = copystring( name ); /* set it up */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* too many images? */
|
||||
if ( image == NULL ) {
|
||||
Error( "MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES );
|
||||
}
|
||||
image.name = name;
|
||||
|
||||
/* attempt to load tga */
|
||||
strcat( name, ".tga" ); // StripExtension( name ); already
|
||||
size = vfsLoadFile( name, (void**) &buffer, 0 );
|
||||
sprintf( filename, "%s.tga", name ); // StripExtension( name ); already
|
||||
size = vfsLoadFile( filename, (void**) &buffer, 0 );
|
||||
if ( size > 0 ) {
|
||||
LoadTGABuffer( buffer, buffer + size, &image->pixels, &image->width, &image->height );
|
||||
LoadTGABuffer( buffer, buffer + size, &image.pixels, &image.width, &image.height );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* attempt to load png */
|
||||
path_set_extension( name, ".png" );
|
||||
size = vfsLoadFile( name, (void**) &buffer, 0 );
|
||||
path_set_extension( filename, ".png" );
|
||||
size = vfsLoadFile( filename, (void**) &buffer, 0 );
|
||||
if ( size > 0 ) {
|
||||
LoadPNGBuffer( buffer, size, &image->pixels, &image->width, &image->height );
|
||||
LoadPNGBuffer( buffer, size, &image.pixels, &image.width, &image.height );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* attempt to load jpg */
|
||||
path_set_extension( name, ".jpg" );
|
||||
size = vfsLoadFile( name, (void**) &buffer, 0 );
|
||||
path_set_extension( filename, ".jpg" );
|
||||
size = vfsLoadFile( filename, (void**) &buffer, 0 );
|
||||
if ( size > 0 ) {
|
||||
if ( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL ) {
|
||||
// On error, LoadJPGBuff might store a pointer to the error message in image->pixels
|
||||
Sys_Warning( "LoadJPGBuff %s %s\n", name, (unsigned char*) image->pixels );
|
||||
if ( LoadJPGBuff( buffer, size, &image.pixels, &image.width, &image.height ) == -1 && image.pixels != NULL ) {
|
||||
// On error, LoadJPGBuff might store a pointer to the error message in image.pixels
|
||||
Sys_Warning( "LoadJPGBuff %s %s\n", filename, (unsigned char*) image.pixels );
|
||||
image.pixels = NULL;
|
||||
}
|
||||
alphaHack = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* attempt to load dds */
|
||||
path_set_extension( name, ".dds" );
|
||||
size = vfsLoadFile( name, (void**) &buffer, 0 );
|
||||
path_set_extension( filename, ".dds" );
|
||||
size = vfsLoadFile( filename, (void**) &buffer, 0 );
|
||||
if ( size > 0 ) {
|
||||
LoadDDSBuffer( buffer, size, &image->pixels, &image->width, &image->height );
|
||||
LoadDDSBuffer( buffer, size, &image.pixels, &image.width, &image.height );
|
||||
|
||||
/* debug code */
|
||||
#if 1
|
||||
#if 0
|
||||
{
|
||||
ddsPF_t pf;
|
||||
DDSGetInfo( (ddsBuffer_t*) buffer, NULL, NULL, &pf );
|
||||
Sys_Printf( "pf = %d\n", pf );
|
||||
if ( image->width > 0 ) {
|
||||
path_set_extension( name, "_converted.tga" );
|
||||
WriteTGA( "C:\\games\\quake3\\baseq3\\textures\\rad\\dds_converted.tga", image->pixels, image->width, image->height );
|
||||
if ( image.width > 0 ) {
|
||||
path_set_extension( filename, "_converted.tga" );
|
||||
WriteTGA( "C:\\games\\quake3\\baseq3\\textures\\rad\\dds_converted.tga", image.pixels, image.width, image.height );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -400,10 +339,10 @@ image_t *ImageLoad( const char *filename ){
|
|||
else
|
||||
{
|
||||
/* attempt to load ktx */
|
||||
path_set_extension( name, ".ktx" );
|
||||
size = vfsLoadFile( name, (void**) &buffer, 0 );
|
||||
path_set_extension( filename, ".ktx" );
|
||||
size = vfsLoadFile( filename, (void**) &buffer, 0 );
|
||||
if ( size > 0 ) {
|
||||
LoadKTXBufferFirstImage( buffer, size, &image->pixels, &image->width, &image->height );
|
||||
LoadKTXBufferFirstImage( buffer, size, &image.pixels, &image.width, &image.height );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -414,36 +353,31 @@ image_t *ImageLoad( const char *filename ){
|
|||
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;
|
||||
//% size, image.width, image.height, image.pixels, filename );
|
||||
image.pixels = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set filename */
|
||||
image->filename = copystring( name );
|
||||
|
||||
/* set count */
|
||||
image->refCount = 1;
|
||||
numImages++;
|
||||
image.filename = filename;
|
||||
|
||||
if ( alphaHack ) {
|
||||
path_set_extension( name, "_alpha.jpg" );
|
||||
size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
|
||||
path_set_extension( filename, "_alpha.jpg" );
|
||||
size = vfsLoadFile( (const char*) filename, (void**) &buffer, 0 );
|
||||
if ( size > 0 ) {
|
||||
unsigned char *pixels;
|
||||
int width, height;
|
||||
if ( LoadJPGBuff( buffer, size, &pixels, &width, &height ) == -1 ) {
|
||||
if (pixels) {
|
||||
// On error, LoadJPGBuff might store a pointer to the error message in pixels
|
||||
Sys_Warning( "LoadJPGBuff %s %s\n", name, (unsigned char*) pixels );
|
||||
Sys_Warning( "LoadJPGBuff %s %s\n", filename, (unsigned char*) pixels );
|
||||
}
|
||||
} else {
|
||||
if ( width == image->width && height == image->height ) {
|
||||
if ( width == image.width && height == image.height ) {
|
||||
for ( int i = 0; i < width * height; ++i )
|
||||
image->pixels[4 * i + 3] = pixels[4 * i + 2]; // copy alpha from blue channel
|
||||
image.pixels[4 * i + 3] = pixels[4 * i + 2]; // copy alpha from blue channel
|
||||
}
|
||||
free( pixels );
|
||||
}
|
||||
|
|
@ -451,6 +385,6 @@ image_t *ImageLoad( const char *filename ){
|
|||
}
|
||||
}
|
||||
|
||||
/* return the image */
|
||||
return image;
|
||||
/* cache and return the image */
|
||||
return &( *images.insert_after( images.cbegin(), std::move( image ) ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@
|
|||
// now checking it for strlen() < MAX_QPATH (so it's null terminated), though this check may be not enough/too much, depending on the use case
|
||||
#define MAX_QPATH 64
|
||||
|
||||
#define MAX_IMAGES 2048
|
||||
#define DEFAULT_IMAGE "*default"
|
||||
|
||||
#define DEF_BACKSPLASH_FRACTION 0.05f /* 5% backsplash by default */
|
||||
|
|
@ -413,10 +412,25 @@ typedef Vector3 tcMod_t[ 3 ];
|
|||
|
||||
struct image_t
|
||||
{
|
||||
char *name, *filename;
|
||||
int refCount;
|
||||
CopiedString name; // relative path w/o extension
|
||||
CopiedString filename; // relative path with extension
|
||||
int width, height;
|
||||
byte *pixels;
|
||||
byte *pixels = nullptr;
|
||||
|
||||
image_t() = default;
|
||||
image_t( const image_t& ) = delete;
|
||||
image_t( image_t&& other ) noexcept :
|
||||
name( std::move( other.name ) ),
|
||||
filename( std::move( other.filename ) ),
|
||||
width( other.width ),
|
||||
height( other.height ),
|
||||
pixels( std::exchange( other.pixels, nullptr ) )
|
||||
{}
|
||||
image_t& operator=( const image_t& ) = delete;
|
||||
image_t& operator=( image_t&& ) noexcept = delete;
|
||||
~image_t(){
|
||||
free( pixels );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -576,9 +590,9 @@ struct shaderInfo_t
|
|||
EImplicitMap implicitMap; /* ydnar: enemy territory implicit shaders */
|
||||
String64 implicitImagePath;
|
||||
|
||||
image_t *shaderImage;
|
||||
image_t *lightImage;
|
||||
image_t *normalImage;
|
||||
const image_t *shaderImage;
|
||||
const image_t *lightImage;
|
||||
const image_t *normalImage;
|
||||
|
||||
float skyLightValue; /* ydnar */
|
||||
int skyLightIterations; /* ydnar */
|
||||
|
|
@ -1813,9 +1827,7 @@ int ExportEntitiesMain( Args& args );
|
|||
|
||||
|
||||
/* image.c */
|
||||
void ImageFree( image_t *image );
|
||||
image_t *ImageFind( const char *name );
|
||||
image_t *ImageLoad( const char *filename );
|
||||
const image_t *ImageLoad( const char *name );
|
||||
|
||||
|
||||
/* shaders.c */
|
||||
|
|
@ -1876,9 +1888,6 @@ void InjectCommandLine( const char *stage, const std::vec
|
|||
|
||||
|
||||
/* general */
|
||||
Q_EXTERN int numImages Q_ASSIGN( 0 );
|
||||
Q_EXTERN image_t images[ MAX_IMAGES ];
|
||||
|
||||
Q_EXTERN shaderInfo_t *shaderInfo Q_ASSIGN( NULL );
|
||||
Q_EXTERN int numShaderInfo Q_ASSIGN( 0 );
|
||||
|
||||
|
|
|
|||
|
|
@ -747,7 +747,6 @@ static void LoadShaderImages( shaderInfo_t *si ){
|
|||
/* if no light image, reuse shader image */
|
||||
if ( si->lightImage == NULL ) {
|
||||
si->lightImage = si->shaderImage;
|
||||
si->lightImage->refCount++;
|
||||
}
|
||||
|
||||
/* create default and average colors */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user