【图像算法】高斯模糊+径向缩放模糊

来源:互联网 发布:flash制作软件 编辑:程序博客网 时间:2024/05/29 18:06

【原文:http://blog.csdn.net/meegomeego/article/details/8790309】

初学图形编程,开始记录

工作内容:通过学习某知名商业引擎,构建新游戏引擎,对新引擎进行简单测试。

札记:

1、移植代码大部分时间都是很枯燥的,不用想只需要重复的做,重复的做。。。。, 最多要改的地方就是编码规范,然后是在许多模块没有建立的基础上对把移植好的模块编译连接,最重要的技巧就是注释,许多设计没有建立的模块太多,只能留下空实现的函数,以后用到的时候再实现吧。

2、这次做完了Texture模块,虽然还没有做任何渲染相关的代码,但是测试还是需要的,不然以后累加起来可能就忘记了。

2.1。测试流程:载入一个图片到缓存,操作缓存(即像素),做出特定的模糊效果,再另保存为文件,进行查看。(注:文件操作和DDS图像文件读取已经做完)

2.2。制作高斯模糊(累加像素求平均值):

      输入:像素数据指针,高斯模糊半径(X和Y分量上各一个)

      算法流程:1、遍历每一个像素点

                     2、以这个像素点为中心,根据高斯模糊半径创建一个区域,此区域内的像素用来计算中心点像素的高斯模糊值。

                     3、遍历这个区域的每一个像素,累加RGBA的各个分量值(我测试的图片是32位的DDS文件)。

                     4、用各个分量除以累加的数量组合成一个像素(即高斯模糊后的像素点)。

      注:

          1、使用unsigned char储存一个像素的分量,但累加的时候要使用更大存储空间的类型比如unsigned int,否则会溢出。

          2、这次操作的图像是读DDS文件,保存格式为BMP,发现两种格式文件的RGBA的通道存储顺序是不一致的,所以操作的时候要改为正确的才能进行存储。

          3、BMP格式解析文件是从下到上进行倒置存储的。

          4、进行多次遍历像素点的时候要保持遍历的顺序,否则容易出现贴图倒置或翻转的效果。

      事例代码:

//---------------------------------------------------------------------------
void FillPerPixelGaussBlur(yqg_IPixelData * pDest, DWORD originX, DWORD originY, BYTE * pSrc, DWORD radiusX, DWORD radiusY)
{
    // 记录共受多少个像素的影响
    DWORD t_Num = 0;
    // 获得高斯模糊半径内的像素区域
    DWORD t_pixelLeft  = originX > radiusX ? originX-radiusX : 0;
    DWORD t_pixelTop   = originY > radiusY ? originY-radiusY : 0;
    DWORD t_pixelRight = (originX+radiusX) < pDest->GetWidth()  ? originX+radiusX : pDest->GetWidth();
    DWORD t_pixelBottom= (originY+radiusY) < pDest->GetHeight() ? originY+radiusY : pDest->GetHeight();
    DWORD t_pPixels[4];
    for(int t_d = 0; t_d < 4; ++t_d)
    {
        t_pPixels[t_d] = 0;
    }
    // 遍历区域内的每个元素
    for(DWORD t_dX = t_pixelLeft; t_dX < t_pixelRight; ++t_dX)
    {
        for(DWORD t_dY = t_pixelTop; t_dY < t_pixelBottom; ++t_dY)
        {
            // 计数
            ++t_Num;
            // 将影响像素分值添加到高斯模糊像素上
            BYTE * t_pOrigin = (BYTE*)&(((DWORD*)pSrc)[t_dX + t_dY * pDest->GetWidth()]);
            t_pPixels[0] = t_pPixels[0] + *(t_pOrigin+0);            //Red
            t_pPixels[1] = t_pPixels[1] + *(t_pOrigin+1);            //Green
            t_pPixels[2] = t_pPixels[2] + *(t_pOrigin+2);            //Blue
            t_pPixels[3] = t_pPixels[3] + *(t_pOrigin+3);            //Alpha
        }
    }
    // 取累加后的像素平均值,即高斯模糊
    if(t_Num != 0)
    {
        BYTE * t_pDestPixel = pDest->operator()(originX, originY);
        *(t_pDestPixel+0) = (BYTE)(t_pPixels[0] / t_Num);//Blue    
        *(t_pDestPixel+1) = (BYTE)(t_pPixels[1] / t_Num);//Green
        *(t_pDestPixel+2) = (BYTE)(t_pPixels[2] / t_Num);//Red
        *(t_pDestPixel+3) = (BYTE)(t_pPixels[3] / t_Num);
    }
}
//---------------------------------------------------------------------------

2.3。制作径向缩放模糊(针对任意一点,循环数量,根据数量值求出单位缩放,确定当前数量下的像素点,进行累加,然后求平均值):

      输入:像素数据指针,径向缩放中心点(指定的像素位置),数量

      算法流程:1、遍历每一个像素点

                     2、循环数量,根据每个数量下的单位缩放值和中心点累加像素值。

                     3、求平均值,即该像素点的径向缩放模糊值。

      注:做缩放值和像素点的计算时要确定类型,如unsigned int相减是不会的得到负数的,细节很重要。

      事例代码:

//---------------------------------------------------------------------------
void FillPerPixelRadialBlur(yqg_IPixelData * pDest, BYTE * pSrc, DWORD dCenterX, DWORD dCenterY, DWORD dNum, DWORD dCurrentPosX, DWORD dCurrentPosY)
{
    // 缩放值
    float t_fScale;
    // 根据缩放值和中心点计算后用来累加像素点的位置
    DWORD t_caluPixelPosX;
    DWORD t_caluPixelPosY;
    // 临时存储累加的计算结果,并初始化
    DWORD t_pPixels[4];
    for(int t_d = 0; t_d < 4; ++t_d)
    {
        t_pPixels[t_d] = 0;
    }
    // 遍历数量
    for(DWORD t_dIndex = 0; t_dIndex < dNum; ++t_dIndex)
    {
        // 计算缩放值
        t_fScale = 1.0f + (-(dNum*1.0f/pDest->GetWidth()) * t_dIndex) / (dNum - 1);
        // 计算累加像素点的位置
        t_caluPixelPosX = (DWORD)(((int)dCurrentPosX - (int)dCenterX) * t_fScale + dCenterX);
        t_caluPixelPosY = (DWORD)(((int)dCurrentPosY - (int)dCenterY) * t_fScale + dCenterY);
        t_caluPixelPosX = (t_caluPixelPosX > (pDest->GetWidth() - 1)) ? (pDest->GetWidth() - 1) : t_caluPixelPosX;
        t_caluPixelPosY = (t_caluPixelPosY > (pDest->GetHeight() - 1)) ? (pDest->GetHeight() - 1) : t_caluPixelPosY;
        // 将影响像素分值添加到径向缩放模糊像素上
        BYTE * t_pOrigin = (BYTE*)&(((DWORD*)pSrc)[t_caluPixelPosX + t_caluPixelPosY * pDest->GetWidth()]);
        t_pPixels[0] = t_pPixels[0] + *(t_pOrigin+0);            //Red
        t_pPixels[1] = t_pPixels[1] + *(t_pOrigin+1);            //Green
        t_pPixels[2] = t_pPixels[2] + *(t_pOrigin+2);            //Blue
        t_pPixels[3] = t_pPixels[3] + *(t_pOrigin+3);            //Alpha
    }
    // 取累加后的像素平均值,即高斯模糊
    BYTE * t_pDestPixel = pDest->operator()(dCurrentPosX, dCurrentPosY);
    *(t_pDestPixel+0) = (BYTE)(t_pPixels[0] / dNum);//Blue
    *(t_pDestPixel+1) = (BYTE)(t_pPixels[1] / dNum);//Green
    *(t_pDestPixel+2) = (BYTE)(t_pPixels[2] / dNum);//Red
    *(t_pDestPixel+3) = (BYTE)(t_pPixels[3] / dNum);

}
//---------------------------------------------------------------------------

以下是原图和效果图

 

0 0
原创粉丝点击