图片缩放算法

本算法是以灰度图为例,彩色图像也很简单大家自己修改即可.当然对浮点纹理也有效果.

该算法在地形的高度图处理中已被使用,效率和效果还算满意.

先看效果原始图片

 

最近点采样

 

线性采样

基本原理就是缩放前后的图片相对应的位置的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;
}

源代码下载:

/Files/WengYB/ScalingTexture.rar

posted @ 2010-05-31 14:17  醉翁之家  阅读(3299)  评论(0编辑  收藏  举报