首先看这两张效果图:
毛玻璃看上去是一些离散的点分布,而这些点是周围像素点的反映。所以需要用到随机值。
算法原理:
1. 统计像素周围区域内的R、G、B的直方图,直方图横坐标是每个像素的灰度值,统计以及每个灰度值的强度
2. 从直方图中随机选取一个灰度强度下的R、G、B的均值就是目标像素结果
该算法存在一个参数:
1. 半径:越大则毛刺更严重,随机范围越大
算法代码:没有经过任何优化
void FrostedGlassRGB(unsigned char* pInput,unsigned char* pOutput,int width,int height,int nStride,int radius)
{
int intensity;
int red[256],green[256],blue[256],intensities[256];
unsigned char* src = pInput;
unsigned char* dst = pOutput;
unsigned char* p;
int i,j,x,y,t;
int offset = nStride-width*3;
if(pInput == NULL || pOutput == NULL)
return;
if(width <= 0 || height <= 0)
return;
if(radius<1)
radius = 1;
srand ((unsigned int)time(0));
// for each line
for ( y = 0; y < height; y++ )
{
// for each pixel
for ( x = 0; x < width; x++, src += 3, dst += 3 )
{
memset(red,0,sizeof(int)*256);
memset(green,0,sizeof(int)*256);
memset(blue,0,sizeof(int)*256);
memset(intensities,0,sizeof(int)*256);
// for each kernel row
for ( i = -radius; i <= radius; i++ )
{
t = y + i;
// skip row
if ( t < 0 )
continue;
// break
if ( t >= height )
break;
// for each kernel column
for ( j = -radius; j <= radius; j++ )
{
t = x + j;
// skip column
if ( t < 0 )
continue;
if ( t < width )
{
p = &src[i * nStride + j * 3];
intensity = (int)( 0.2125 * (*p) + 0.7154 * (*(p+1))) + 0.0721 * (*(p+2));
intensities[intensity] ++;
// red
red[intensity] += *p;
// green
green[intensity] += *(p+1);
// blue
blue[intensity] += *(p+2);
}
}
}
do
{
intensity = (rand()+1)%255;
}
while (intensities[intensity] == 0);
// set destination pixel
*dst = (unsigned char)( red[intensity] / intensities[intensity] );
*(dst+1) = (unsigned char)( green[intensity] / intensities[intensity] );
*(dst+2) = (unsigned char)( blue[intensity] / intensities[intensity] );
}
src += offset;
dst += offset;
}
}