当前位置:编程学习 > C#/ASP.NET >>

图像柔光效果(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# ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,