图像柔光效果(SoftGlow)的原理及其实现
由于CSDN博客和博客园的编辑方面有不一致的地方,导致文中部分图片错位,为不影响浏览效果,建议点击打开链接。
图像柔光效果在很多商业软件中都有实现,比如美图秀秀,光影魔术手等。其能针对原始图像产生一副新的比较平滑感觉光线比较柔和的效果,给人一种朦胧美,如下面几幅图所示:
目前,关于该算法的可控参数,美图秀秀只提供了一个程度(0-100%)控制量,其算法调节的效果和幅度都较小,光影魔术手有柔化程度和高光柔化两个参数,其中柔化程度控制柔化的朦胧效果,高光柔化调节图像的亮度。 还有一些开源的软件如Imagestone、paint.net、gimp也有softglow算法,他们都提供了3个控制量:半径、亮度、对比度(锐度),其中Imagestone其实是翻译的gimp的算法,而GIMP和paint.net的算法在基本原理上是一样的,细节上有所区别而已。
我们以paint.net的实现过程为例进行说明,在paint.net的源代码中,GlowEffect.cs为实现该效果的文件,我抽取其部分源代码简要说明下这个算法的过程。
[csharp] view plaincopyprint?public GlowEffect() : base(StaticName, StaticImage, null, EffectDirectives.None, true)
{
this.blurEffect = new BlurEffect();
this.bcAdjustment = new BrightnessAndContrastAdjustment();
this.screenBlendOp = new UserBlendOps.ScreenBlendOp();
}
public GlowEffect() : base(StaticName, StaticImage, null, EffectDirectives.None, true)
{
this.blurEffect = new BlurEffect();
this.bcAdjustment = new BrightnessAndContrastAdjustment();
this.screenBlendOp = new UserBlendOps.ScreenBlendOp();
}
以及代码片段:
[csharp] view plaincopyprint?public override unsafe void Render(
EffectConfigToken parameters,
RenderArgs dstArgs,
RenderArgs srcArgs,
System.Drawing.Rectangle[] rois,
int startIndex,
int length)
{
// First we blur the source, and write the result to the destination surface
// Then we apply Brightness/Contrast with the input as the dst, and the output as the dst
// Third, we apply the Screen blend operation so that dst = dst OVER src
ThreeAmountsConfigToken token = (ThreeAmountsConfigToken)parameters;
AmountEffectConfigToken blurToken = new AmountEffectConfigToken(token.Amount1);
this.blurEffect.Render(blurToken, dstArgs, srcArgs, rois, startIndex, length);
BrightnessAndContrastAdjustmentConfigToken bcToken = new BrightnessAndContrastAdjustmentConfigToken(token.Amount2, token.Amount3);
this.bcAdjustment.Render(bcToken, dstArgs, dstArgs, rois, startIndex, length);
for (int i = startIndex; i < startIndex + length; ++i)
{
Rectangle roi = rois[i];
for (int y = roi.Top; y < roi.Bottom; ++y)
{
ColorBgra* dstPtr = dstArgs.Surface.GetPointAddressUnchecked(roi.Left, y);
ColorBgra* srcPtr = srcArgs.Surface.GetPointAddressUnchecked(roi.Left, y);
screenBlendOp.Apply(dstPtr, srcPtr, dstPtr, roi.Width);
}
}
}
public override unsafe void Render(
EffectConfigToken parameters,
RenderArgs dstArgs,
RenderArgs srcArgs,
System.Drawing.Rectangle[] rois,
int startIndex,
int length)
{
// First we blur the source, and write the result to the destination surface
// Then we apply Brightness/Contrast with the input as the dst, and the output as the dst
// Third, we apply the Screen blend operation so that dst = dst OVER src
ThreeAmountsConfigToken token = (ThreeAmountsConfigToken)parameters;
AmountEffectConfigToken blurToken = new AmountEffectConfigToken(token.Amount1);
this.blurEffect.Render(blurToken, dstArgs, srcArgs, rois, startIndex, length);
BrightnessAndContrastAdjustmentConfigToken bcToken = new BrightnessAndContrastAdjustmentConfigToken(token.Amount2, token.Amount3);
this.bcAdjustment.Render(bcToken, dstArgs, dstArgs, rois, startIndex, length);
for (int i = startIndex; i < startIndex + length; ++i)
{
补充:软件开发 , C# ,