2012-06-12 17 views
5

wenn ich zeichne etwas wie die (nur zufälligen Zeichnungen hier):DrawingContext.DrawLine: Stift hat keine vollständige Deckkraft?

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

die Farben DrawLine und DrawEllipse Mix. (Ich habe herausgefunden, dass nur mit DrawLine ein Stift verwendet wird und nicht mit anderen Formen wie Rectangle und Ellipse, die einen Pinsel verwenden). Seltsamerweise sogar mit Farben aus dem LinearGradientBrush eines zugrunde liegenden Grids 'Background (argh). Ich möchte, dass sie jeweils mit voller Opazität z-Ordered sind.

Hier ist der XAML-Code:

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

Vielen Dank für jede Hilfe.

+0

Ich habe eine Umgehung mit DrawLine mit einem Füller Pinsel in DrawLine mit einem Stift verwendet. Dennoch frage ich mich, warum Stifte keine volle Opazität haben. – Julian

+0

'Pen' hat volle Deckkraft, aber in Ihrem Fall sind die Linien so dünn, dass sie verschwimmen und halbtransparent erscheinen. Lesen Sie meine Antwort für weitere Informationen und vorgeschlagene Lösungen :). Durch das Zeichnen von Rechtecken können Sie nur horizontale und vertikale Linien simulieren. Linien zeichnen, aber mit größerer Breite sollten den Trick machen;). –

Antwort

2

Der von Ihnen gepostete Code zeichnet mehrere dünne Linien nebeneinander. Jeder von ihnen ist antialiased und hat seine Seiten verwischt. Ich nehme an, der von Ihnen beschriebene Opazitäts-Mixing-Effekt tritt deshalb auf.

Wenn Sie eine dicke Linie gezeichnet haben (d. H. Mit einer Breite von 10), wird der Effekt nicht angezeigt. So

hängt die Lösung ab, was genau wollen Sie erreichen:

  • Sie können versuchen, Anti-Aliasing zu deaktivieren, wenn diese zufrieden stellend, um weitere Informationen zu diesem Thema finden Sie aktuelle hier: Disabling antialiasing on a WPF image
  • Zeichnen Sie Linien mit einem Stift, der eine größere Breite hat, dh new Pen(Brushes.Black, 2)
  • in diesem speziellen Fall von Zeichnungslinien nahe beieinander, können Sie den Zähler um 0,5f statt 1 erhöhen, so ersetzen for (int i = 0; i <= 100 - 1; i++) durch for (float i = 0.0f; i <= 100 - 1; i+=0.5f).
  • Wenn es Ihnen nichts ausmacht, mehr Code zu schreiben, können Sie Ihre eigene benutzerdefinierte Bitmap-Klasse erstellen, die Bilder nicht unscharf macht. Einige Lösung ist hier http://www.nbdtech.com/Blog/archive/2008/11/20/blurred-images-in-wpf.aspx erhältlich und auf der Website verwiesen wird dort
+0

Ich konnte keine 1px breite Linie zeichnen, aber die 2px Linie ist vollständig undurchsichtig gezeichnet. Hier ist ein gutes Beispiel: http://daniel-albuschat.blogspot.com/2011/04/avoiding-anti-aliasing-when-drawing.html – Monsignor

4

Es gibt zwei Probleme von Anti-Aliasing oder Unter pixeling, mit Rendertargetbitmap:

1.

Deaktivieren Unter pixeling für die Bitmap selbst (wenn es beispielsweise in einem UIElement gerendert wird). Dies wird gelöst durch Anwenden von:

RenderOptions.SetBitmapScalingMode(image1, BitmapScalingMode.NearestNeighbor); 

(wobei Bild1 das WPF-Bildobjekt ist).

Es wird nur für .NET 4 und höher unterstützt. In Ihrem speziellen Fall spielt es keine Rolle, da die Linien Pixel für Pixel gerendert werden.

2.

Deaktivieren Unter pixeling wenn sie in der Rendertargetbitmap-Rendering. Dies kann durch die Methode RenderOptions.SetEdgeMode mit dem Parameterwert von EdgeMode.Aliased erreicht werden.

Allerdings wird diese Methode funktioniert nur, wenn:

  • Das Verfahren für ein DrawingGroup Objekt aufgerufen wird.

  • Die Geometrie mit Antialiasing wird nur durch reguläres Zeichnungscomposite verschachtelt (wenn z. B. die DrawingGroup ein Rechteck enthält, in dem VisualBrush eine DrawingVisual kapselt, wird der Inhalt dieser DrawingVisual auch dann antialiasiert, wenn Sie diese Methode verwenden).

So können Sie Ihren Code wie folgt umschreiben:

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 funktioniert Beispiel. Vielen Dank! –

1

Weitere (einfacher) Art und Weise hier:

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

Für Ihr Beispiel, müssen Sie nur eine Klasse erstellen wie:

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

und Ihre DrawingVisual Instanz mit AliasedDrawingVisual ersetzen:

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;