2010-01-14 13 views

Respuesta

10

creo que esto va a hacer lo que quiere:

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; 
    } 
} 

lo que está pasando aquí? Primero escribí un código que llenaría un rectángulo con un pincel de gradiente elíptico que iba del blanco al negro. Luego modifiqué el código para que el área llena también incluyera las esquinas. Hice esto aumentando el tamaño del rectángulo por la diferencia entre las dimensiones del rectángulo y sqrt (2)/2 * las dimensiones del rectángulo.

¿Por qué sqrt (2)/2? Porque el punto (sqrt (2)/2, sqrt (2)/2) es el punto del ángulo de 45 grados en un círculo unitario. Escalar por el ancho y la altura proporciona la distancia necesaria para inflar el recto y asegurarse de que esté completamente cubierto.

Luego ajusté la mezcla del degradado para que fuera mucho más blanca en el centro.

Luego cambié el color de blanco a negro puro transparente y de negro a negro opaco puro. Esto tiene el efecto de pintar las esquinas lejanas en negro y sombrear menos en el camino hacia el centro.

Por último, me escribió un método de utilidad que se ejecuta en un mapa de bits (no he probado esta parte - He probado el código en un gráfico de un panel, pero creo que va a funcionar aquí también

+0

Muchas gracias, intentaré que –

+0

Alguien más note que la viñeta se compensa con la derecha del centro? He comprobado tres veces las matemáticas y todo parece correcto. En una imagen de 1200 píxeles de ancho, la viñeta parece estar a unos 50-60 píxeles a la derecha. –

2

Si su imagen está en un archivo, y si eso es lo suficientemente rápido para sus requisitos, puede usar la herramienta de línea de comandos convert de ImageMagick, tiene una opción -vignette. Para invocar esto desde un programa C#, puede ejecutarlo a través de System.Diagnostics.Process.Start, o puede usar this .NET wrapper para ImageMagick.

+0

Gracias,. esa es una buena solución para mi problema. Sin embargo, me gustaría ver el algoritmo detrás de este efecto para poder implementarlo yo mismo. –

Cuestiones relacionadas