2012-06-12 2 views
5

quand je dessine quelque chose comme ça (seulement ici au hasard des dessins):DrawingContext.DrawLine: Le stylo n'a pas d'opacité complète?

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

les couleurs de mélange DrawLine et DrawEllipse. (J'ai compris que c'est seulement avec DrawLine qui utilise un stylo, et pas avec d'autres formes comme Rectangle et Ellipse, qui utilisent un pinceau). Étrangement même avec les couleurs du LinearGradientBrush d'un fond de grille sous-jacent (argh). Je voudrais qu'ils soient z-commandés avec une opacité complète chacun.

Voici le code 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> 

Merci pour toute aide.

+0

J'ai fait une solution de contournement en utilisant DrawRectangle avec un pinceau de remplissage installé DrawLine avec un stylo. Je me demande encore pourquoi les stylos n'ont pas d'opacité complète. – Julian

+0

'Pen' a une opacité totale, mais dans votre cas, les lignes sont si fines qu'elles deviennent floues et semblent être semi-transparentes. Lisez ma réponse pour plus d'informations et des solutions suggérées :). Les rectangles de dessin vous permettent de simuler uniquement des lignes horizontales et verticales. Dessin lignes, mais avec une plus grande largeur devrait faire l'affaire;). –

Répondre

2

Le code que vous avez affiché dessine plusieurs lignes fines les unes à côté des autres. Chacun d'eux est anti-aliasé et ses flancs sont flous. Je suppose que l'effet de mélange d'opacité que vous avez décrit se produit à cause de cela.

Si vous avez dessiné une ligne épaisse (c'est-à-dire avec une largeur de 10), l'effet n'apparaît pas.

Ainsi, la solution dépend exactement ce que vous essayez d'atteindre:

  • vous pouvez essayer de désactiver l'anticrénelage, si cela est satisfaisant, pour plus d'informations à ce sujet, jetez un coup d'oeil ici: Disabling antialiasing on a WPF image
  • lignes d'étirage avec un stylo qui a obtenu une plus grande largeur, à savoir new Pen(Brushes.Black, 2)
  • dans ce cas particulier de tracer des lignes à proximité de l'autre, on peut incrémenter le compteur de 0.5f au lieu de 1, donc remplacer for (int i = 0; i <= 100 - 1; i++) avec for (float i = 0.0f; i <= 100 - 1; i+=0.5f).
  • Si cela ne vous dérange pas d'écrire plus de code, vous pouvez créer votre propre classe Bitmap personnalisée qui ne rend pas les images floues. Une solution est disponible ici http://www.nbdtech.com/Blog/archive/2008/11/20/blurred-images-in-wpf.aspx et dans le site référencé il
+0

Je n'ai pas réussi à dessiner une ligne de largeur 1px, mais la ligne 2px est complètement opaque. Voici un bon exemple: http://daniel-albuschat.blogspot.com/2011/04/avoiding-anti-aliasing-when-drawing.html – Monsignor

4

Il y a deux questions de anticrénelage, ou sous-pixellation, avec RenderTargetBitmap:

1.

Désactivation sous-pixellation pour le bitmap lui-même (par exemple, quand il est rendu dans un UIElement). ceci est résolu en appliquant:

RenderOptions.SetBitmapScalingMode(image1, BitmapScalingMode.NearestNeighbor); 

(où image1 est l'objet image WPF).

Il est uniquement pris en charge pour .NET 4 et versions ultérieures. Dans votre cas, cela n'a pas d'importance car les lignes sont rendues pixel par pixel.

2.

Désactivation sous-pixellation lors du rendu dans le RenderTargetBitmap. Cela peut être réalisé par la méthode RenderOptions.SetEdgeMode avec la valeur du paramètre EdgeMode.Aliased.

Cependant, cette méthode ne fonctionnera que si:

  • La méthode est appelée pour un objet DrawingGroup. La géométrie anti-aliasée est imbriquée uniquement à l'aide d'un composite de dessin standard (par exemple, si DrawingGroup contient un rectangle avec un VisualBrush encapsulant un DrawingVisual, le contenu de ce DrawingVisual sera anti-crénelé même si vous avez utilisé cette méthode).

Ainsi vous pouvez réécrire votre code comme suit:

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

C'est un exemple de travail. Merci! –

1

Un autre (plus facile) façon ici:

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

Pour exemple, il vous suffit de créer une classe comme:

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

et remplacer votre instance DrawingVisual avec 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;