Fix loading ridiculously large non-POT-textures

After loading a texture, Doom3 calculates an MD4-sum of it.. this is
mostly pointless and only used for the "reportImageDuplication" console
command, but whatever.
The problem here was that the image was 32000x2000 pixels (due to some
error when creating it) which dhewm3 wanted to convert to the next
bigger power-of-two values with R_ResampleTexture(), but that function
clamps to 4096x4096, so the actually used pixeldata was for 2048x4096.
However, R_ResampleTexture() didn't communicate this to its caller,
and thus a too big size was used for calculating the MD4-sum and it
crashed.

That's fixed now and also a warning is printed about this.
This commit is contained in:
Daniel Gibson 2025-03-03 05:49:16 +01:00
parent dda5e3f499
commit b78becde4c
3 changed files with 17 additions and 9 deletions

View file

@ -468,7 +468,7 @@ FIXME: make an "imageBlock" type to hold byte*,width,height?
byte *R_Dropsample( const byte *in, int inwidth, int inheight,
int outwidth, int outheight );
byte *R_ResampleTexture( const byte *in, int inwidth, int inheight,
int outwidth, int outheight );
int& outwidth, int& outheight );
byte *R_MipMapWithAlphaSpecularity( const byte *in, int width, int height );
byte *R_MipMap( const byte *in, int width, int height, bool preserveBorder );
byte *R_MipMap3D( const byte *in, int width, int height, int depth, bool preserveBorder );

View file

@ -902,12 +902,18 @@ void R_LoadImage( const char *cname, byte **pic, int *width, int *height, ID_TIM
if ( globalImages->image_roundDown.GetBool() && scaled_height > h ) {
scaled_height >>= 1;
}
int outWidth = scaled_width;
int outHeight = scaled_height;
resampledBuffer = R_ResampleTexture( *pic, w, h, outWidth, outHeight );
if ( outWidth != scaled_width || outHeight != scaled_height ) {
common->Warning( "Texture '%s' didn't have power-of-two size *and* was too big, scaled from %dx%d to %dx%d",
name.c_str(), w, h, outWidth, outHeight );
}
resampledBuffer = R_ResampleTexture( *pic, w, h, scaled_width, scaled_height );
R_StaticFree( *pic );
*pic = resampledBuffer;
*width = scaled_width;
*height = scaled_height;
*width = outWidth;
*height = outHeight;
}
}
}

View file

@ -46,7 +46,7 @@ after resampling to the next lower power of two.
*/
#define MAX_DIMENSION 4096
byte *R_ResampleTexture( const byte *in, int inwidth, int inheight,
int outwidth, int outheight ) {
int& _outwidth, int& _outheight ) {
int i, j;
const byte *inrow, *inrow2;
unsigned int frac, fracstep;
@ -54,12 +54,14 @@ byte *R_ResampleTexture( const byte *in, int inwidth, int inheight,
const byte *pix1, *pix2, *pix3, *pix4;
byte *out, *out_p;
if ( outwidth > MAX_DIMENSION ) {
outwidth = MAX_DIMENSION;
if ( _outwidth > MAX_DIMENSION ) {
_outwidth = MAX_DIMENSION;
}
if ( outheight > MAX_DIMENSION ) {
outheight = MAX_DIMENSION;
if ( _outheight > MAX_DIMENSION ) {
_outheight = MAX_DIMENSION;
}
int outwidth = _outwidth;
int outheight = _outheight;
out = (byte *)R_StaticAlloc( outwidth * outheight * 4 );
out_p = out;