【问题标题】:Rendering 1 pixel lines with DrawingVisual使用 DrawingVisual 渲染 1 像素线
【发布时间】:2011-04-06 19:21:54
【问题描述】:

我已经看到了几个在 WPF 中渲染 1 像素线的示例,但似乎没有一个适用于我的情况。我正在使用 DrawingVisual 和 DrawingContext 来绘制一些形状,并使用 RenderTargetBitmap 和 PngBitmapEncoder 来生成图像。在许多情况下,即使我将其设置为 1,矩形也有 2 个像素的边框。我猜这是由于使用了与分辨率无关的渲染。

我找到了几个解决方案,但它们要么在 XAML 中,要么适用于绘图控件。我发现的最接近的东西是 XSnappingGuidelines/YSnappingGuidelines,但我找不到一个如何使用它的示例。这些属性的文档非常缺乏。

如何禁用 DrawingVisual 的分辨率无关渲染?

更新: 这是我想要做的:

声明一个绘图视觉对象:

DrawingVisual mainTemplate = new DrawingVisual();

获取上下文:

using (DrawingContext context = mainTemplate.RenderOpen())

画矩形:

penToUse = new Pen(new SolidColorBrush(Color.FromRgb(0xFF, 0xFF, 0xFF)), 1.0);
penToUse.DashStyle = DashStyles.Dash;
context.DrawRectangle(brushToUse, penToUse, new Rect(left, top, width, height));

在哪里设置渲染模式以对齐像素?

jorj

【问题讨论】:

  • 如果你能发布一些示例代码会很有帮助。
  • 请注意,XAML 中可能发生的任何事情在代码中也可能发生。
  • 当您使用矩形时,您是否将 BorderThickness 设置为仅使用一侧?像“0,1,0,0”。否则你会得到所有的侧面。

标签: c# wpf


【解决方案1】:

在 WPF 中,当您绘制一条线时,该线以您指定的坐标为中心。因此,如果在具有 96 DPI 的设备上绘制一条从 10、10 到 10、20 的垂直线,并且笔的宽度为 1,则该线实际上将在 9.5 和 10.5 之间绘制,占用两个像素。如果要对齐像素边缘上的线,则需要将其移动 0.5。在 120 DPI 显示器上,线宽应为 0.8 以获取单个像素,您需要将其移动 0.4 以对齐像素边缘。

您不必使用 GuidelineSet,因为它所做的不仅仅是这个简单的转换,而是不必要地使代码复杂化。

【讨论】:

  • 这很有趣。使用指南时,必须添加或删除笔宽的一半。不管是加还是减,都可以。但是使用笔的坐标却没有。奇怪。
  • 使用指南可能与 DPI 无关?毕竟笔宽和指南的校正(见我上面的评论)是使用相同的值定义的。抱歉,DPI 对 WPF 的影响确实令人困惑。我想不只是为了我:-)
【解决方案2】:

我最接近能够在 WPF 中使用 DrawingContext 渲染单像素线的是:

GuidelineSet guidelines = new GuidelineSet();
guidelines.GuidelinesX.Add(_bgRect.Left - 0.5);
guidelines.GuidelinesX.Add(_bgRect.Right + 0.5);
guidelines.GuidelinesY.Add(_bgRect.Top - 0.5);
guidelines.GuidelinesY.Add(_bgRect.Bottom + 0.5);
dc.PushGuidelineSet(guidelines);
dc.DrawRectangle(Background, _outlinePen, _bgRect);
if (BorderThickness.Left > 1)
    dc.DrawLine(_leftPen, _bgRect.TopLeft, _bgRect.BottomLeft);
if (BorderThickness.Top > 1)
    dc.DrawLine(_topPen, _bgRect.TopLeft, _bgRect.TopRight);
if (BorderThickness.Right > 1)
    dc.DrawLine(_rightPen, _bgRect.TopRight, _bgRect.BottomRight);
if (BorderThickness.Bottom > 1)
    dc.DrawLine(_bottomPen, _bgRect.BottomRight, _bgRect.BottomLeft);
dc.Pop();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    • 1970-01-01
    相关资源
    最近更新 更多