【问题标题】:DrawingContext.DrawLine: Pen has no full opacity?DrawingContext.DrawLine:笔没有完全不透明度?
【发布时间】:2012-06-15 14:00:24
【问题描述】:

当我画出这样的东西时(这里只是随机画):

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

DrawLine 和 DrawEllipse 的颜色混合在一起。(我发现它只适用于使用笔的 DrawLine,而不是使用 Brush 的其他形式,如 Rectangle 和 Ellipse)。奇怪的是,即使使用来自底层网格背景 (argh) 的 LinearGradientBrush 的颜色。 我希望它们都以完全不透明的方式进行 z 排序。

这里是 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>

感谢您的帮助。

【问题讨论】:

  • 我通过使用带有填充画笔的 DrawRectangle 用笔插入 DrawLine 做了一个解决方法。我仍然想知道为什么钢笔没有完全不透明度。
  • Pen 已完全不透明,但在您的情况下,线条太细以至于它们变得模糊并且似乎是半透明的。阅读我的答案以获取更多信息和建议的解决方案:)。绘制矩形允许您仅模拟水平线和垂直线。画线,但宽度更大应该可以解决问题;)。

标签: wpf transparency opacity z-order drawingcontext


【解决方案1】:

我在以编程方式渲染到DrawingContext 时遇到了同样的问题。唯一可行的方法是使用GuidelineSet:http://wpftutorial.net/DrawOnPhysicalDevicePixels.html

【讨论】:

    【解决方案2】:

    这里的另一种(更简单)方法:

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

    对于你的例子,你只需要创建一个类:

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

    并用 AliasedDrawingVisual 替换您的 DrawingVisual 实例:

        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;
    

    【讨论】:

      【解决方案3】:

      RenderTargetBitmap 有两个抗锯齿或亚像素问题:

      1.

      禁用位图本身的子像素化(例如,当它在 UIElement 中呈现时)。这是通过应用解决的:

          RenderOptions.SetBitmapScalingMode(image1, BitmapScalingMode.NearestNeighbor);
      

      (其中 image1 是 WPF Image 对象)。

      仅支持 .NET 4 及更高版本。 在您的特定情况下,这并不重要,因为线条是逐个像素渲染的。

      2.

      在渲染到 RenderTargetBitmap 时禁用子像素。可以通过RenderOptions.SetEdgeMode方法实现,参数值为EdgeMode.Aliased。

      但是,此方法仅在以下情况下有效:

      • 为 DrawingGroup 对象调用该方法。

      • 抗锯齿几何仅通过常规绘图复合嵌套(例如,如果 DrawingGroup 包含一个矩形,其 VisualBrush 封装了一个 DrawingVisual,即使您使用该方法,该 DrawingVisual 的内容也会被抗锯齿)。

      因此,您可以按如下方式重写代码:

          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;
      

      【讨论】:

        【解决方案4】:

        您发布的代码是在彼此旁边绘制多条细线。它们中的每一个都经过抗锯齿处理,并且其侧面变得模糊。我想你描述的不透明混合效果就是因为这个而发生的。

        如果你画了一条粗线(即宽度为 10),效果就不会出现。

        因此,解决方案取决于您要达到的目标:

        • 您可以尝试禁用抗锯齿,如果这令人满意,有关此的更多信息,请查看此处:Disabling antialiasing on a WPF image
        • 用宽度更大的钢笔画线,即new Pen(Brushes.Black, 2)
        • 在这种画线彼此靠近的特殊情况下,您可以将计数器增加 0.5f 而不是 1,因此将 for (int i = 0; i &lt;= 100 - 1; i++) 替换为 for (float i = 0.0f; i &lt;= 100 - 1; i+=0.5f)
        • 如果您不介意编写更多代码,您可以创建自己的自定义 Bitmap 类,该类不会使图像模糊。一些解决方案可以在这里http://www.nbdtech.com/Blog/archive/2008/11/20/blurred-images-in-wpf.aspx 和那里引用的网站中找到

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-23
        • 2012-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-01
        相关资源
        最近更新 更多