本文内容

  1. 绘图和形状
  2. StreamGeometry 对象
  3. DrawingVisual 对象
  4. 映像

WPF 提供了多种可按应用程序要求进行优化的 2D 图形和图像处理功能。 本主题提供有关这些方面性能优化的信息。

1、绘图和形状

WPF 提供Drawing和Shape对象来表示图形绘制内容。 但是,Drawing对象是比Shape对象更为简单的构造,且提供更好的性能特征。

通过Shape可将图形形状绘制到屏幕。 因为其派生自FrameworkElement类,所以Shape对象可用于面板和大多数控件内。

WPF 为图形和绘制服务提供多层访问。 在顶层,Shape对象易于使用,且提供了布局和事件处理等众多实用功能。 WPF 提供了许多现成可用的形状对象。 所有形状对象都继承自Shape类。 可用的形状对象包括Ellipse、Line、Path、Polygon、Polyline和Rectangle。

另一方面,Drawing对象不是派生自FrameworkElement类,且对于绘制形状、图像和文本提供了更轻量的实现。

有四种类型的Drawing对象:

  • GeometryDrawing绘制形状。

  • ImageDrawing绘制图像。

  • GlyphRunDrawing绘制文本。

  • DrawingGroup绘制其他图形。 使用绘图组将其他绘图合并到单个复合绘图。

GeometryDrawing对象用于绘制几何内容。Geometry类及其派生的具体类(例如CombinedGeometry、EllipseGeometry和PathGeometry)提供绘制 2D 图形的方式以及命中测试和剪裁支持。 几何对象可用于定义控件的区域或定义应用于图像的剪裁区域等。 几何对象可以是简单区域(例如矩形和圆形),或者是由两个或多个几何对象创建的复合区域。 通过合并PathSegment派生对象(例如ArcSegment、BezierSegment和QuadraticBezierSegment),可创建更复杂的几何区域。

表面上看,Geometry类和Shape类非常相似。 二者都用于绘制 2D 图形,且都具有相似的具体派生类,例如EllipseGeometry和Ellipse。 但是,这两个类集之间存在重大区别。 一方面,Geometry类缺少Shape类的部分功能,例如绘制自身的功能。 若要绘制几何对象,必须使用另一个类(例如 DrawingContext、Drawing 或 Path(值得注意的是 Path 是一个 Shape))来执行绘制操作。 填充、笔划和笔划粗细等绘制属性位于绘制几何对象的类上,而形状对象中包含这些属性。 可以这样来理解这种差别:几何对象定义区域(例如圆形),而形状对象定义区域、定义如何填充区域和设置区域边框并参与布局系统。

由于Shape对象派生自FrameworkElement类,因此使用这些对象会使应用程序的内存消耗显著增加。 如果对于图形内容确实不需要FrameworkElement功能,请考虑使用更轻量的Drawing对象。

2、StreamGeometry 对象

在创建几何形状时,StreamGeometry对象是对PathGeometry的轻量替代。 需要描述复杂几何时使用StreamGeometry。StreamGeometry非常适合用于处理许多PathGeometry对象,且与使用众多单独的PathGeometry对象相比,其性能更佳。

以下示例使用特性语法在 XAML 中创建三角形StreamGeometry。

3、DrawingVisual 对象

DrawingVisual对象是一个轻量绘图类,用于绘制形状、图像或文本。 此类之所以为轻量类是因为它不提供布局或事件处理,从而性能得以提升。 因此,绘图非常适用于背景和剪贴画。

4映像

WPF 图像处理大幅改进了 Windows 先前版本的图像处理功能。 显示位图或在公共控件上使用图像等图像处理功能以前主要由 Microsoft Windows 图形设备接口 (GDI) 或 Microsoft Windows GDI+ 应用程序编程接口 (API) 处理。 这些 API 提供基线图像处理功能,但缺少编解码器扩展性支持和高保真图像支持等功能。 WPF 图像处理 API 已经过重新设计,克服了 GDI 和 GDI+ 的缺点,提供一组新的 API,用于在应用程序内显示和使用图像。

使用图像时,为使性能更佳,请考虑以下建议:

  • 如果应用程序要求显示缩略图,请考虑创建一个缩略版图像。 默认情况下,WPF 会加载图像并将其解码到最大尺寸。 如果仅需要图像的缩略版本,WPF 会先将图像解码为完整尺寸,然后将其缩放为缩略图大小,这个过程是多余的。 若要避免这个多余的过程,可请求 WPF 将图像解码到缩略图大小,或者请求 WPF 加载缩略图大小的图像。

  • 请务必将图像解码到所需大小而不是默认大小。 如上所述,请求 WPF 将图像解码为所需大小而不是默认的最大尺寸。 这样不仅会减小应用程序的工作集,还会减慢其执行速度。

  • 如果可能,请将多个图像合并到单个图像中,例如由多个图像构成的胶卷条。

BitmapScalingMode

对任何位图缩放进行动画处理时,默认的高质量图像重采样算法有时可能由于消耗过多系统资源导致帧速率下降,继而导致动画明显变慢。 通过将RenderOptions对象的BitmapScalingMode属性设置为LowQuality,缩放位图时可创建更为流畅的动画。 处理图像时,LowQuality模式会通知 WPF 绘制引擎从质量优化算法切换至速度优化算法。

下面的示例演示如何为图像对象设置BitmapScalingMode。

// Set the bitmap scaling mode for the image to render faster.RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality);

CachingHint

默认情况下,WPF 不会缓存TileBrush对象的绘制内容,例如DrawingBrush和VisualBrush。 在静态方案中,内容和场景中TileBrush的使用皆不会发生改变,这样具有一定意义,因为可节省视频内存。 以非静态方式使用具有静态内容的TileBrush时(例如静态DrawingBrush或VisualBrush映射到旋转 3D 对象的图面时),这样做的意义不大。 WPF 的默认行为是对每个帧重新绘制DrawingBrush或VisualBrush的整个内容(即使内容未改变也是如此)。

通过将RenderOptions对象的CachingHint属性设置为Cache,可使用缓存版平铺画笔对象来提升性能。

CacheInvalidationThresholdMinimum和CacheInvalidationThresholdMaximum属性值为相对大小值,这些值决定由于比例更改而应何时重新生成TileBrush对象。 例如,通过将CacheInvalidationThresholdMaximum属性设置为 2.0,TileBrush的缓存仅需在其大小超过当前缓存大小两倍时重新生成。

如下示例演示如何对DrawingBrush使用缓存提示选项。

DrawingBrush drawingBrush = new DrawingBrush();// Set the caching hint option for the brush.RenderOptions.SetCachingHint(drawingBrush, CachingHint.Cache);// Set the minimum and maximum relative sizes for regenerating the tiled brush.// The tiled brush will be regenerated and re-cached when its size is// 0.5x or 2x of the current cached size.RenderOptions.SetCacheInvalidationThresholdMinimum(drawingBrush, 0.5);RenderOptions.SetCacheInvalidationThresholdMaximum(drawingBrush, 2.0);