2010-01-14 75 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