* unlimit MAX_IMAGES

This commit is contained in:
Garux 2021-10-06 10:51:32 +03:00
parent 2602c48a18
commit 9660fbb6f1
7 changed files with 90 additions and 148 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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