2010-01-14 60 views

回答

10

我相信这会做你想要什么:

public void PaintVignette(Graphics g, Rectangle bounds) 
{ 
    Rectangle ellipsebounds = bounds; 
    ellipsebounds.Offset(-ellipsebounds.X, -ellipsebounds.Y); 
    int x = ellipsebounds.Width - (int)Math.Round(.70712 * ellipsebounds.Width); 
    int y = ellipsebounds.Height - (int)Math.Round(.70712 * ellipsebounds.Height); 
    ellipsebounds.Inflate(x, y); 

    using (GraphicsPath path = new GraphicsPath()) 
    { 
     path.AddEllipse(ellipsebounds); 
     using (PathGradientBrush brush = new PathGradientBrush(path)) 
     { 
      brush.WrapMode = WrapMode.Tile; 
      brush.CenterColor = Color.FromArgb(0, 0, 0, 0); 
      brush.SurroundColors = new Color[] { Color.FromArgb(255, 0, 0, 0) }; 
      Blend blend = new Blend(); 
      blend.Positions = new float[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F }; 
      blend.Factors = new float[] { 0.0f, 0.5f, 1f, 1f, 1.0f, 1.0f }; 
      brush.Blend = blend; 
      Region oldClip = g.Clip; 
      g.Clip = new Region(bounds); 
      g.FillRectangle(brush, ellipsebounds); 
      g.Clip = oldClip; 
     } 
    } 
} 

public Bitmap Vignette(Bitmap b) 
{ 
    Bitmap final = new Bitmap(b); 
    using (Graphics g = Graphics.FromImage(final)) { 
     PaintVignette(g, new Rectangle(0, 0, final.Width, final.Height)); 
     return final; 
    } 
} 

这是怎么回事?首先,我编写了一个代码,用椭圆渐变画笔填充矩形,从白色变为黑色。然后我修改了代码,以便填充区域也包含角落。我是通过矩形尺寸和sqrt(2)/ 2 *矩形尺寸之间的差异来增加矩形尺寸来实现的。

为什么sqrt(2)/ 2?因为点(sqrt(2)/ 2,sqrt(2)/ 2)是单位圆上的45度角点。通过宽度和高度缩放给出了膨胀矩形所需的距离,以确保其完全覆盖。

然后我调整了渐变的混合在中心更白。

然后我将颜色从白色改为纯透明黑色,从黑色改为纯不透明黑色。这样做的效果是将远角涂成黑色,并且在进入中心的过程中遮蔽较少。

最后,我写了一个位图运行(我没有测试过这部分的实用工具方法 - 我测试的代码上的图形从面板,但我认为它会在这里工作过

+0

非常感谢,我会尝试 – 2010-01-14 17:00:25

+0

任何人都会注意到小插曲被抵消中心的权利?我对数学进行了三重检查,看起来一切正常。在1200像素宽的图像上,小插图似乎在右边50-60px。 – 2015-06-01 16:52:49

2

如果您的照片在一个文件中,并且对于您的要求足够快,您可以使用ImageMagick的命令行工具convert,它有一个选项-vignette。要在C#程序中调用此函数,可以通过System.Diagnostics.Process.Start运行它,或者对ImageMagick使用this .NET wrapper

+0

谢谢。这对我的问题是一个很好的解决方案 但是,我希望看到这个效果背后的算法,以便能够自己实现它 – 2010-01-14 15:49:28