图片缩放算法
本算法是以灰度图为例,彩色图像也很简单大家自己修改即可.当然对浮点纹理也有效果.
该算法在地形的高度图处理中已被使用,效率和效果还算满意.
先看效果原始图片
最近点采样
线性采样
基本原理就是缩放前后的图片相对应的位置的UV坐标相同
即: srcX/srcWidth = dstX/dstWidth
srcY/srcHeight = dstY/dstHeight
推出
srcX = dstX * srcWidth / dstWidth;
srcY = dstY * srcHeight / dstHeight;
当然在具体处理过程中有不同的采样算法,比如最近点采样,线性采样等.
下面是具体的C++代码(资源文件为RAW文件):
#include <stdio.h>
typedef unsigned char BYTE;
typedef unsigned int UINT;
// 读单色Raw文件
bool ReadRawFile( BYTE *pData, char *pFileName, UINT width, UINT height )
{
if( pData == NULL || pFileName == NULL || width == 0 || height == 0 )
return false;
FILE *pf = fopen( pFileName, "rb" );
if( pf == NULL )
return false;
fread( pData, 1, width * height, pf );
fclose( pf );
return true;
}
// 写单色Raw文件
bool WriteRawFile( BYTE *pData, char *pFileName, UINT width, UINT height )
{
if( pData == NULL || pFileName == NULL || width == 0 || height == 0 )
return false;
FILE *pf = fopen( pFileName, "wb" );
if( pf == NULL )
return false;
fwrite( pData, 1, width * height, pf );
fclose( pf );
return true;
}
// 缩放纹理
void ScalingTexturePoint( BYTE *pDstTexData, UINT dstWidth, UINT dstHeight, BYTE *pSrcTexData, UINT srcWidth, UINT srcHeight )
{
if( pDstTexData == NULL || pSrcTexData == NULL )
return;
if( dstWidth == 0 || dstHeight == 0 || srcWidth == 0 || srcHeight == 0 )
return;
int x, y;
double sx, sy;
double w = (double)srcWidth/(double)dstWidth;
double h = (double)srcHeight/(double)dstHeight;
int i=0;
for( UINT row=0; row<dstHeight; row++ )
{
sy = (double)row * h;
y = (int)sy;
for( UINT col=0; col<dstWidth; col++ )
{
sx = (double)col * w;
x = (int)sx;
pDstTexData[i] = pSrcTexData[y*srcWidth+x];
i++;
}
}
}
// 缩放纹理
void ScalingTextureLinear( BYTE *pDstTexData, UINT dstWidth, UINT dstHeight, BYTE *pSrcTexData, UINT srcWidth, UINT srcHeight )
{
if( pDstTexData == NULL || pSrcTexData == NULL )
return;
if( dstWidth == 0 || dstHeight == 0 || srcWidth == 0 || srcHeight == 0 )
return;
int x, y;
double sx, sy;
double u, v;
double pm[4];
BYTE color[4];
double w = (double)srcWidth/(double)dstWidth;
double h = (double)srcHeight/(double)dstHeight;
int i=0;
for( UINT row=0; row<dstHeight; row++ )
{
sy = (double)(row+0.5) * h - 0.5;
y = (int)sy;
if( y > sy )
y--;
v = sy - y;
for( UINT col=0; col<dstWidth; col++ )
{
sx = (double)(col+0.5) * w - 0.5;
x = (int)sx;
if( x > sx )
x--;
u = sx - x;
pm[0] = ( 1.0 - u ) * ( 1.0 - v );
pm[1] = v * ( 1.0 - u );
pm[2] = u * ( 1.0 - v );
pm[3] = u * v;
for( int n=0; n<4; n++ )
{
int xx = ( n==0 || n==1 ) ? x : x+1;
if( xx < 0 )
xx = 0;
else if( xx > srcWidth-1 )
xx = srcWidth-1;
int yy = ( n==0 || n==2 ) ? y : y+1;
if( yy < 0 )
yy = 0;
else if( yy > srcHeight-1 )
yy = srcHeight-1;
color[n] = pSrcTexData[yy*srcWidth+xx];
}
pDstTexData[i] = (BYTE)( pm[0]*color[0] + pm[1]*color[1] + pm[2]*color[2] + pm[3]*color[3] );
i++;
}
}
}
void main()
{
UINT srcWidth = 256, srcHeight = 128;
UINT dstWidthA = 128, dstHeightA = 64;
UINT dstWidthB = 1024, dstHeightB = 512;
BYTE *pSrcData = new BYTE[srcWidth*srcHeight];
BYTE *pDstDataA = new BYTE[dstWidthA*dstHeightA];
BYTE *pDstDataB = new BYTE[dstWidthB*dstHeightB];
// 读取原始图片文件
if( ReadRawFile( pSrcData, "SrcPic.raw", srcWidth, srcHeight ) )
{
ScalingTexturePoint( pDstDataA, dstWidthA, dstHeightA, pSrcData, srcWidth, srcHeight );
WriteRawFile( pDstDataA, "DstPicPointA.raw", dstWidthA, dstHeightA );
ScalingTexturePoint( pDstDataB, dstWidthB, dstHeightB, pSrcData, srcWidth, srcHeight );
WriteRawFile( pDstDataB, "DstPicPointB.raw", dstWidthB, dstHeightB );
ScalingTextureLinear( pDstDataA, dstWidthA, dstHeightA, pSrcData, srcWidth, srcHeight );
WriteRawFile( pDstDataA, "DstPicLinearA.raw", dstWidthA, dstHeightA );
ScalingTextureLinear( pDstDataB, dstWidthB, dstHeightB, pSrcData, srcWidth, srcHeight );
WriteRawFile( pDstDataB, "DstPicLinearB.raw", dstWidthB, dstHeightB );
}
delete [] pSrcData;
delete [] pDstDataA;
delete [] pDstDataB;
}
源代码下载: