本文对滤镜中常见的晕影,晕角效果的实现做了研究,具体如下:1 晕影调整算法所谓晕影就是给图像四个角添加暗影效果,这暗影向图像中心逐渐淡化。我们使用如下公式来实现: 假设图像宽度高度分别为w,h: double d = Math.Sqrt((i - w / 2) * (i - w / 2) + (j - h / 2) * (j - h / 2)); double dmax = 1.0 / Math.Sqrt(w * w / 4 + h * h / 4); double lum = 0.75 / (1.0 + Math.Exp((d * dmax - cRadius) * cGradient)) + cLight; //eg:double lum = 0.75 / (1.0 + Math.Exp((d * dmax - 0.85) * 5)) + 0.35; r = (int)((double)r * lum); g = (int)((double)g * lum); b = (int)((double)b * lum); 注释: cRadius (cRadius=0.73)这个参数控制晕影的半径,值越大,半径越大; cLight (cLight=0.25)控制中心圆形区域内的像素亮度,值越大,图像越亮; cGradient (cGradient=20)这个参数控制中心区域与晕影过渡部分的梯度,值越小,过渡越自然,越不明显; 上述算法实现的是圆形晕影。 有了晕影图像之后,我们采用K比例混合算法来实现晕影强度的可调性,假设晕影图像为S(n,m),原图为X(n,m),效果图为Y(n,m),晕影强度因子为K,K属于[0,1],混合公式如下: Y(n,m)=K*X(n,m)+(1-K)*S(n,m) 这样就实现了晕影效果从无到有的调节过程。 2 晕影调节快速算法晕影调节的快速算法主要是改进晕影图像的生成过程。我们可以按照自己的需求使用PS制作出一张晕影效果图,来代替算法生成晕影图像的过程,这样就可以节省算法生成的时间了,之后的调节过程不变。 当然,这个算法的缺点就是晕影的半径,过渡程度和亮度无法调整。 目前,这里给出Instagram里使用的晕角模板: 在Instagram中,是使用这个模板与目标图像执行“柔光”混合图层算法,得到晕角效果的,然后使用1中的K比例混合算法,来快速调节。 最后给出android 中C代码,可以直接使用。 附录 Android C Code with RGB565void THaloEffect(int* srcData, int width, int height) { int gray = 0, green = 0, blue = 0, red = 0, i = 0, j = 0, alpha = 0xFF << 24; for(j = 0; j < height; j++) { for(i = 0; i < width; i++) { gray = srcData[i + j * width]; red = ((gray >> 16) & 0xFF); green = ((gray >> 8) & 0xFF); blue = (gray & 0xFF); double d = sqrt((i - width / 2) * (i - width / 2) + (j - height / 2) * (j - height / 2)); double dmax = 1.0 / sqrt(width * width / 4 + height * height / 4); //double lum = 0.75 / (1.0 + Math.Exp((d * dmax - 0.73) * 20)) + 0.25; double lum = 0.75 / (1.0 + exp((d * dmax - 0.73) * 20)) + 0.25; red = (int)((double)red * lum); red = CheckRange(red); green = (int)((double)green * lum); green = CheckRange(green); blue = (int)((double)blue * lum); blue = CheckRange(blue); srcData[i + j * width] = alpha | (red << 16) | (green << 8) | blue; } } }; void THaloEffect_F(int* srcData, int* mask, int width, int height, int ratio) { int gray = 0,green = 0,blue = 0,red = 0,i = 0, mRed = 0, mGreen = 0, mBlue = 0, alpha = 0xFF << 24; int length = width * height; for (i = 0; i < length; i++) { gray = srcData[i]; red = ((gray >> 16) & 0xFF); green = ((gray >> 8) & 0xFF); blue = (gray & 0xFF); gray = mask[i]; mRed = ((gray >> 16) & 0xFF); mGreen = ((gray >> 8) & 0xFF); mBlue = (gray & 0xFF); mRed = ModeSmoothLight(red, mRed); mGreen = ModeSmoothLight(green, mGreen); mBlue = ModeSmoothLight(blue, mBlue); red = (mRed * ratio + (100 - ratio) * red) / 100; green = (mGreen * ratio + (100 - ratio) * green) / 100; blue = (mBlue * ratio + (100 - ratio) * blue) / 100; srcData[i] = alpha | (red << 16) | (green << 8) | blue; } }; |