/* ref_image.c - shared image code Copyright (C) 2010 Uncle Mike This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "ref_common.h" #include "xash3d_mathlib.h" /* ================ GL_ResampleTexture Assume input buffer is RGBA ================= */ byte *GL_ResampleTexture( const byte *source, int inWidth, int inHeight, int outWidth, int outHeight, qboolean isNormalMap ) { uint frac, fracStep; uint *in = (uint *)source; uint p1[0x1000], p2[0x1000]; byte *pix1, *pix2, *pix3, *pix4; uint *out, *inRow1, *inRow2; static byte *scaledImage = NULL; // pointer to a scaled image vec3_t normal; int i, x, y; if( !source ) return NULL; scaledImage = Mem_Realloc( r_temppool, scaledImage, outWidth * outHeight * 4 ); fracStep = inWidth * 0x10000 / outWidth; out = (uint *)scaledImage; frac = fracStep >> 2; for( i = 0; i < outWidth; i++ ) { p1[i] = 4 * (frac >> 16); frac += fracStep; } frac = (fracStep >> 2) * 3; for( i = 0; i < outWidth; i++ ) { p2[i] = 4 * (frac >> 16); frac += fracStep; } if( isNormalMap ) { for( y = 0; y < outHeight; y++, out += outWidth ) { inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight); inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight); for( x = 0; x < outWidth; x++ ) { pix1 = (byte *)inRow1 + p1[x]; pix2 = (byte *)inRow1 + p2[x]; pix3 = (byte *)inRow2 + p1[x]; pix4 = (byte *)inRow2 + p2[x]; normal[0] = MAKE_SIGNED( pix1[0] ) + MAKE_SIGNED( pix2[0] ) + MAKE_SIGNED( pix3[0] ) + MAKE_SIGNED( pix4[0] ); normal[1] = MAKE_SIGNED( pix1[1] ) + MAKE_SIGNED( pix2[1] ) + MAKE_SIGNED( pix3[1] ) + MAKE_SIGNED( pix4[1] ); normal[2] = MAKE_SIGNED( pix1[2] ) + MAKE_SIGNED( pix2[2] ) + MAKE_SIGNED( pix3[2] ) + MAKE_SIGNED( pix4[2] ); if( !VectorNormalizeLength( normal )) VectorSet( normal, 0.5f, 0.5f, 1.0f ); ((byte *)(out+x))[0] = 128 + (byte)(127.0f * normal[0]); ((byte *)(out+x))[1] = 128 + (byte)(127.0f * normal[1]); ((byte *)(out+x))[2] = 128 + (byte)(127.0f * normal[2]); ((byte *)(out+x))[3] = 255; } } } else { for( y = 0; y < outHeight; y++, out += outWidth ) { inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight); inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight); for( x = 0; x < outWidth; x++ ) { pix1 = (byte *)inRow1 + p1[x]; pix2 = (byte *)inRow1 + p2[x]; pix3 = (byte *)inRow2 + p1[x]; pix4 = (byte *)inRow2 + p2[x]; ((byte *)(out+x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2; ((byte *)(out+x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2; ((byte *)(out+x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2; ((byte *)(out+x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2; } } } return scaledImage; }