【问题标题】:Anti-aliasing artifacts in WPFWPF 中的抗锯齿伪影
【发布时间】:2009-01-21 22:35:09
【问题描述】:

当我尝试在 WPF 中使用抗锯齿图形时,我遇到了一个奇怪的渲染问题。

这是一个简化版。

如果我使用以下 XAML

<Window x:Class="RenderingBug.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Width="300" Height="300">
    <Grid Name="myGrid" Background="AntiqueWhite" Width="250" Height="250">
        <ScrollViewer Name="myScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
            <Canvas Height="500" Width="500" Name="myCanvas" />
        </ScrollViewer>        
    </Grid>
 </Window>

还有下面的cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RenderingBug
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            PathFigureCollection pfc = new PathFigureCollection();
            PathFigure pf = new PathFigure();
            pf.StartPoint = new Point(100, 20);
            LineSegment ls = new LineSegment();
            ls.Point = new Point(20, 100);
            PathSegmentCollection psc = new PathSegmentCollection();
            psc.Add(ls);
            pf.Segments = psc;
            pfc.Add(pf);
            PathGeometry pg = new PathGeometry(pfc);

            RectangleGeometry clippingRectangle = new RectangleGeometry(new Rect(0, 0, 80, 80));

            Path p1 = new Path();
            p1.ClipToBounds = true;
            p1.Clip = clippingRectangle;
            p1.StrokeDashCap = PenLineCap.Square;
            p1.Stroke = Brushes.Black;
            p1.StrokeThickness = 30;
            p1.Data = pg;
            myCanvas.Children.Add(p1);

            Path p2 = new Path();
            p2.ClipToBounds = true;
            p2.Clip = clippingRectangle;
            p2.StrokeDashCap = PenLineCap.Square;
            p2.Stroke = Brushes.White;
            p2.StrokeThickness = 10;
            p2.Data = pg;
            myCanvas.Children.Add(p2);
        }
    }
}

我在裁剪矩形边缘所在的位置出现了一个奇怪的抗锯齿渲染问题(运行程序,它会相当明显,但它是一条模糊的灰线,裁剪矩形截断了路径。)

我尝试了各种技术,例如将控件与特定像素对齐,并在各种控件上设置 SnapsToDevicePixels,希望这能解决这个问题(移除额外的模糊灰色带),但似乎没有任何帮助。

有什么想法吗?

【问题讨论】:

    标签: .net wpf antialiasing


    【解决方案1】:

    事实证明,这是因为尽管窗口当然是在像素边界上对齐的,但窗口内的网格可能不是。解决这个问题并不太难,但可能需要一段时间才能弄清楚该怎么做。

    有一个很好的功能叫做 SnapsToDevicePixels 可以让所有东西都正确对齐。而且,可悲的是,无论出于何种原因,它似乎根本不起作用(这似乎是一个可以理解的错误)。那么该怎么办呢?

    首先,网格必须在像素边界处对齐(即不居中,或类似的东西,因为如果窗口在水平或垂直方向上具有奇数个像素,则网格,因此网格内容,会错位。)

    但是,还有其他问题需要处理...一旦您开始滚动滚动条,工件就会重新出现!这是因为滚动条不一定将内容滚动整数个像素。为了解决这个问题,我在 ScrollViewer 中捕获了一些事件,以将滚动位置设置为整数值。

    private void workingAreaScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        double w = e.NewSize.Width;
        double h = e.NewSize.Height;
        workingAreaScrollViewer.Width = Math.Round(w);
        workingAreaScrollViewer.Height = Math.Round(h);
    }
    
    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.A)
        {
            workingAreaCanvas.Children.Remove(p2);
        }
        if (e.Key == Key.Z && p2.Parent != workingAreaCanvas)
        {
            workingAreaCanvas.Children.Add(p2);
        }
    }
    

    这样做,一切似乎都很好。

    (作为旁注,对于在 ScrollViews 中遇到图像问题的人......如果您遇到同样的问题,这也应该可以解决这个问题,只要图像没有缩放、旋转,等等...只要您只是想将图像与像素边界对齐,这应该可以完成这项工作。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-23
      • 2014-02-18
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 2012-12-23
      相关资源
      最近更新 更多