Skip to content

Commit

Permalink
Changed: Implemented GL_ScaleBufferNearest; a nearest neighbor image …
Browse files Browse the repository at this point in the history
…scaling algorithm for use with tiny graphics (w*h < 16) rather than hq2x. The hq2x algorithm can do nothing to help graphics this small and better results can be obtained with the simple nearest neighbor algorithm.
  • Loading branch information
danij-deng committed May 21, 2010
1 parent 691bc6f commit 63b078a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 3 deletions.
3 changes: 3 additions & 0 deletions doomsday/engine/portable/include/gl_tex.h
Expand Up @@ -73,4 +73,7 @@ int DrawRealPatch(byte* buffer, int texwidth, int texheight,
boolean checkForAlpha);
boolean ImageHasAlpha(image_t *image);
void GL_TranslatePatch(lumppatch_t* patch, byte* transTable);

int GL_PickSmartScaleMethod(int width, int height);
void GL_SmartFilter(int method, byte* in, byte* out, int width, int height);
#endif
44 changes: 44 additions & 0 deletions doomsday/engine/portable/src/gl_tex.c
Expand Up @@ -1155,3 +1155,47 @@ byte *GL_ApplyColorKeying(byte *buf, uint pixelSize, uint width,

return NULL;
}

void GL_ScaleBufferNearest(const byte* in, int width, int height,
byte* out, int outWidth, int outHeight, int comps)
{
int ratioX = (int)(width << 16 ) / outWidth + 1;
int ratioY = (int)(height << 16) / outHeight + 1;
int i, j;

int shearY = 0;
for(i = 0; i < outHeight; ++i, shearY += ratioY)
{
int shearX = 0;
int shearY2 = (shearY >> 16) * width;
for(j = 0; j < outWidth; ++j, out += comps, shearX += ratioX)
{
int c, n = (shearY2 + (shearX >> 16)) * comps;
for(c = 0; c < comps; ++c, n++)
out[c] = in[n];
}
}
}

int GL_PickSmartScaleMethod(int width, int height)
{
if(width >= MINTEXWIDTH && height >= MINTEXHEIGHT)
return 2; // hq2x
return 1; // nearest neighbor.
}

void GL_SmartFilter(int method, byte* in, byte* out, int width, int height)
{
switch(method)
{
default: // linear interpolation.
GL_ScaleBuffer32(in, width, height, out, width*2, height*2, 4);
break;
case 1: // nearest neighbor.
GL_ScaleBufferNearest(in, width, height, out, width*2, height*2, 4);
break;
case 2: // hq2x
GL_SmartFilter2x(in, out, width, height, width * 8);
break;
};
}
7 changes: 4 additions & 3 deletions doomsday/engine/portable/src/gl_texmanager.c
Expand Up @@ -574,7 +574,7 @@ DGLuint GL_UploadTexture2(texturecontent_t* content)
alphaChannel = true;
}

GL_SmartFilter2x(rgbaOriginal, filtered, width, height, width * 8);
GL_SmartFilter(GL_PickSmartScaleMethod(width, height), rgbaOriginal, filtered, width, height);
width *= 2;
height *= 2;
noStretch = GL_OptimalSize(width, height, &levelWidth, &levelHeight, noStretch, generateMipmaps);
Expand Down Expand Up @@ -2618,6 +2618,7 @@ gltexture_inst_t* GLTexture_Prepare(gltexture_t* tex, void* context, byte* resul

if(scaleSharp)
{
int scaleMethod = GL_PickSmartScaleMethod(image.width, image.height);
int numpels = image.width * image.height;
byte* rgbaPixels = M_Malloc(numpels * 4 * 2);
byte* upscaledPixels = M_Malloc(numpels * 4 * 4);
Expand All @@ -2627,7 +2628,7 @@ gltexture_inst_t* GLTexture_Prepare(gltexture_t* tex, void* context, byte* resul
if(monochrome && (tex->type == GLT_DOOMPATCH || tex->type == GLT_SPRITE))
Desaturate(rgbaPixels, image.width, image.height, 4);

GL_SmartFilter2x(rgbaPixels, upscaledPixels, image.width, image.height, image.width * 8);
GL_SmartFilter(scaleMethod, rgbaPixels, upscaledPixels, image.width, image.height);
image.width *= 2;
image.height *= 2;

Expand Down Expand Up @@ -2770,7 +2771,7 @@ gltexture_inst_t* GLTexture_Prepare(gltexture_t* tex, void* context, byte* resul
image.pixelSize == 4 ? DGL_RGBA : DGL_LUMINANCE );
}

if(tex->type == GLT_FLAT || tex->type == GLT_DOOMTEXTURE || tex->type == GLT_DOOMPATCH || tex->type == GLT_MASK)
if(tex->type == GLT_FLAT || tex->type == GLT_DOOMTEXTURE || tex->type == GLT_MASK)
magFilter = glmode[texMagMode];
else if(tex->type == GLT_SPRITE)
magFilter = filterSprites ? GL_LINEAR : GL_NEAREST;
Expand Down

0 comments on commit 63b078a

Please sign in to comment.