http://blog.csdn.net/jia20003/article/details/7201069
在该前辈的博客处找了段java的均值模糊(box blur)的代码,我把它换成hge的了,效率还可以,不过应该比不上前一篇的方法。但box blur是比较正统的模糊算法,不像前一篇的那般“邪道”,他直接处理像素,其思想方法类似高斯算法,实现上又比高斯算法要简单,虽然效果上比高斯差,但也值得了。
这里我简单讲一下均值模糊的步骤,当然各位也可以看那位前辈的博客:)
1.输入一个半径r,定义模糊的方向,r越大,则越模糊(虽然说是半径r,但是模糊的方向只取一条线,或两条线,例如横,竖,横与竖)。
2.根据1建立一个索引,其实就是空间换时间,提前算好了r范围内所有可能出现的颜色数值之和的均值,这是个固定的值,所以可以一开始就建)。
3.计算第一个r区域的各个像素值之和(r,g,b,a分别算)
4.开始遍历想要输出的纹理像素(注意原纹理矩阵依然保留),每行第一个像素,直接给他赋予2中的均值,往后每遍历一个像素,3计算的像素值之和都加上x+r +1和 x - r 之间的差(或者是y+r+1和y-r-1的差),然后再次赋予新的均值。
代码(使用横方向模糊,每摁一下L键开始模糊,半径为10):
/*
**
** motion blur demo
** based off of tutorial4..
*/
#include "..\..\include\hge.h"
#include "..\..\include\hgesprite.h"
HGE *hge=0;
hgeSprite* spt1;
float x=0.0f, y=0.0f;
HTEXTURE boxblur( HTEXTURE in, int radius ) ;
bool FrameFunc()
{
if(hge->Input_KeyDown(HGEK_L))
{
HTEXTURE dumptex = spt1->GetTexture();
HTEXTURE tex2 = boxblur(dumptex,10);
spt1->SetTexture(tex2);
hge->Texture_Free(dumptex);
}
hge->Gfx_BeginScene();
hge->Gfx_Clear(0);
spt1->Render(x, y);
hge->Gfx_EndScene();
return false;
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
hge = hgeCreate(HGE_VERSION);
hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
hge->System_SetState(HGE_TITLE, "HGE RealTime Blur Demo");
hge->System_SetState(HGE_FPS, 100);
hge->System_SetState(HGE_WINDOWED, true);
hge->System_SetState(HGE_SCREENWIDTH, 1024);
hge->System_SetState(HGE_SCREENHEIGHT, 768);
hge->System_SetState(HGE_SCREENBPP, 32);
if(hge->System_Initiate()) {
HTEXTURE tex=hge->Texture_Load("alley_normal.jpg");
if(!tex)
{
MessageBox(NULL, "Can't load the picture file", "Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
hge->System_Shutdown();
hge->Release();
return 0;
}
spt1=new hgeSprite(tex, 0, 0, 1024, 768);//这是最后会显示的精灵
hge->System_Start();
hge->Texture_Free(spt1->GetTexture());
delete spt1;
}
// Clean up and shutdown
hge->System_Shutdown();
hge->Release();
return 0;
}
HTEXTURE boxblur( HTEXTURE in, int radius )
{
int width, height;
width = hge->Texture_GetWidth(in);
height = hge->Texture_GetHeight(in);
HTEXTURE out = hge->Texture_Create(width, height);
int widthMinus1 = width-1;
int tableSize = 2*radius+1;
unsigned int* divide = new unsigned int[256*tableSize];
// the value scope will be 0 to 255, and number of 0 is table size
// will get means from index not calculate result again since
// color value must be between 0 and 255.
for ( int i = 0; i < 256*tableSize; i++ )
divide[i] = i/tableSize;
int inIndex = 0;
unsigned int* in_ = (unsigned int*)hge->Texture_Lock(in);
unsigned int* out_ = (unsigned int*)hge->Texture_Lock(out, false);
//
for ( int y = 0; y < height; y++ ) {
int outIndex = y;
unsigned int ta = 0, tr = 0, tg = 0, tb = 0; // ARGB -> prepare for the alpha, red, green, blue color value.
for ( int i = -radius; i <= radius; i++ )
{
int clamp = (i < 0) ? 0 : (i > (width-1)) ? (width-1) : i;
unsigned int rgb = in_[inIndex + clamp]; // read input pixel data here. table size data.
ta += (rgb >> 24) & 0xff;
tr += (rgb >> 16) & 0xff;
tg += (rgb >> 8) & 0xff;
tb += rgb & 0xff;
}
for ( int x = 0; x < width; x++ )
{ // get output pixel data.
out_[ outIndex*width + x ] = (divide[ta] << 24) | (divide[tr] << 16) | (divide[tg] << 8) | divide[tb]; // calculate the output data.
int i1 = x+radius+1;
if ( i1 > widthMinus1 )
i1 = widthMinus1;
int i2 = x-radius;
if ( i2 < 0 )
i2 = 0;
int rgb1 = in_[inIndex+i1];
int rgb2 = in_[inIndex+i2];
ta += ((rgb1 >> 24) & 0xff)-((rgb2 >> 24) & 0xff);
tr += ((rgb1 & 0xff0000)-(rgb2 & 0xff0000)) >> 16;
tg += ((rgb1 & 0xff00)-(rgb2 & 0xff00)) >> 8;
tb += (rgb1 & 0xff)-(rgb2 & 0xff);
}
inIndex += width; // next (i+ column number * n, n=1.n-1)
}
hge->Texture_Unlock(in);
hge->Texture_Unlock(out);
delete [] divide;
return out;
}