2012-06-12 10 views
5

cuando dibujo algo así (sólo dibujos al azar aquí):DrawingContext.DrawLine: ¿La pluma no tiene opacidad completa?

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     DrawingVisual visual = new DrawingVisual(); 
     DrawingContext context = visual.RenderOpen(); 

     Pen pen = new Pen(Brushes.Black, 1); 

     context.DrawEllipse(Brushes.YellowGreen, pen, new Point(0,0), 40, 40); 

     for (int i = 0; i <= 100 - 1; i++) 
      context.DrawLine(new Pen(Brushes.Black, 1), new Point(0, i), new Point(i, i)); 

     context.Close(); 

     RenderTargetBitmap bmp = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32); 

     bmp.Render(visual); 
     image1.Source = bmp; 
    } 
} 

los colores de DrawLine y mezcla drawEllipse. (Me di cuenta de que es solo con DrawLine que usa un bolígrafo, y no con otras formas como Rectángulo y Elipse, que usan un Pincel). Extrañamente, incluso con colores del LinearGradientBrush de un fondo de Grids subyacente (argh). Me gustaría que se ordenen z con opacidad completa cada una.

Aquí el código XAML:

<Window x:Class="WpfApplication2.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Image Name="image1" Stretch="None" /> 
</Window> 

Gracias por cualquier ayuda.

+0

Hice una solución mediante el uso de DrawRectangle con un pincel de relleno inscrito DrawLine con un rotulador. Todavía me pregunto por qué las plumas no tienen opacidad completa. – Julian

+0

'Pen' tiene opacidad completa, pero en su caso, las líneas son tan delgadas que se volvieron borrosas y parecen ser semitransparentes. Lea mi respuesta para más información y soluciones sugeridas :). Los rectángulos de dibujo te permiten simular solo líneas horizontales y verticales. Dibujar líneas, pero con mayor ancho debería hacer el truco;). –

Respuesta

2

El código que ha publicado dibuja múltiples líneas delgadas una al lado de la otra. Cada uno de ellos es antialiased y tiene sus lados borrosos. Supongo que el efecto de mezcla de opacidad que describes se debe a esto.

Si dibujó una línea gruesa (es decir, con un ancho de 10), el efecto no aparecería.

Por lo tanto, la solución depende de qué es exactamente lo que está tratando de lograr:

  • se puede tratar de desactivar el antialiasing, si esto es satisfactoria, para obtener más información sobre esto, echa un vistazo aquí: Disabling antialiasing on a WPF image
  • líneas dibujar con una pluma que tiene mayor anchura, es decir new Pen(Brushes.Black, 2)
  • en este caso particular de dibujar líneas cerca uno del otro, se puede incrementar el contador por 0.5f en lugar de 1, por lo reemplazará con for (int i = 0; i <= 100 - 1; i++)for (float i = 0.0f; i <= 100 - 1; i+=0.5f).
  • si no te importa escribir más código, puedes crear tu propia clase de mapa de bits personalizado que no haga borrosas las imágenes. Algunos solución está disponible aquí http://www.nbdtech.com/Blog/archive/2008/11/20/blurred-images-in-wpf.aspx y en el sitio de referencia no
+0

No logré dibujar una línea de ancho de 1px, pero la línea de 2px se dibuja completamente opaca. Aquí hay un buen ejemplo: http://daniel-albuschat.blogspot.com/2011/04/avoiding-anti-aliasing-when-drawing.html – Monsignor

4

Hay dos cuestiones de antialiasing, o sub-pixeling, con RenderTargetBitmap:

1.

Desactivación de sub-pixeling para el mapa de bits sí mismo (por ejemplo, cuando se representa dentro de un UIElement). esto se resuelve aplicando:

RenderOptions.SetBitmapScalingMode(image1, BitmapScalingMode.NearestNeighbor); 

(donde image1 es el objeto de imagen WPF).

Solo es compatible con .NET 4 y superiores. En su caso específico, no importa ya que las líneas se representan píxel tras píxel.

2.

Desactivación de sub-pixeling cuando la prestación EN la RenderTargetBitmap. Se puede lograr con el método RenderOptions.SetEdgeMode con el valor de parámetro de EdgeMode.Aliased.

Sin embargo, este método funcionará sólo si:

  • El método se llama para un objeto DrawingGroup.

  • La geometría antialiased se anida solo a través del compuesto de dibujo normal (por ejemplo, si el DrawingGroup contiene un rectángulo con un VisualBrush encapsula un DrawingVisual, el contenido de ese DrawingVisual se antialias incluso si usó ese método).

lo tanto puede volver a escribir el código de la siguiente manera:

DrawingVisual visual = new DrawingVisual(); 
    DrawingGroup group = new DrawingGroup(); 

    Pen pen = new Pen(Brushes.Black, 1); 

    group.Children.Add(new GeometryDrawing(Brushes.YellowGreen, pen, new EllipseGeometry(new Point(0,0), 40, 40))); 

    for (int i = 0; i <= 100 - 1; i++) 
     group.Children.Add(new GeometryDrawing(null, new Pen(Brushes.Black, 1), new LineGeometry(new Point(0, i), new Point(i, i)))); 

    RenderOptions.SetEdgeMode(group, EdgeMode.Aliased); 

    DrawingContext context = visual.RenderOpen(); 
    context.DrawDrawing(group); 
    context.Close(); 

    RenderTargetBitmap bmp = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32); 

    bmp.Render(visual); 
    image1.Source = bmp; 
+0

Es un ejemplo de trabajo. ¡Gracias! –

1

Otra forma (más fácil) aquí:

https://stackoverflow.com/a/10257614/2463642

Para su ejemplo, sólo hay que crear una clase como:

public class AliasedDrawingVisual : DrawingVisual 
    { 
     public AliasedDrawingVisual() 
     { 
      this.VisualEdgeMode = EdgeMode.Aliased; 
     } 
    } 

y reemplazar la instancia DrawingVisual con AliasedDrawingVisual:

DrawingVisual visual = new AliasedDrawingVisual(); // Here is the only change 
    DrawingContext context = visual.RenderOpen(); 

    Pen pen = new Pen(Brushes.Black, 1); 

    context.DrawEllipse(Brushes.YellowGreen, pen, new Point(0,0), 40, 40); 

    for (int i = 0; i <= 100 - 1; i++) 
     context.DrawLine(new Pen(Brushes.Black, 1), new Point(0, i), new Point(i, i)); 

    context.Close(); 

    RenderTargetBitmap bmp = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32); 

    bmp.Render(visual); 
    image1.Source = bmp; 
Cuestiones relacionadas