在hge中实现对静态图片的动态模糊 (box blur版)
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 ;
}