【WPF.NET开发】优化性能:二维图形和图像处理

news/2024/7/21 7:29:13 标签: wpf, .net, 图像处理, c#, ui, 性能优化

本文内容

  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。

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel>
  
    <Path Data="F0 M10,100 L100,100 100,50Z" 
      StrokeThickness="1" Stroke="Black"/>

  </StackPanel>
</Page>

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


http://www.niftyadmin.cn/n/5360065.html

相关文章

详解 Prim 算法的实现

一、算法思路 Prim 算法是用来求最小生成树的&#xff0c;它的思想也有点类似于贪心——逐个将离当前集合最近的点加入到集合中&#xff0c;直至发现图不连通或所有点都被加到集合中&#xff0c;算法即宣告终止。它的具体做法是&#xff1a; step 1&#xff1a;初始时&#xf…

【JVM调优及常见的JVM调优参数以及作用】

JVM调优及常见的JVM调优参数以及作用 JVM调优通常涉及以下几个方面&#xff1a;1. 堆内存调优&#xff1a;2. 垃圾回收调优&#xff1a;3. 线程调优&#xff1a;4. 类加载调优&#xff1a;JVM的优化配置可以通过设置JVM的启动参数来实现。以下是一些常用的JVM优化配置参数及其示…

代码随想录 Leetcode77.组合

题目&#xff1a; 代码&#xff08;首刷看解析 2024年2月1日&#xff09;&#xff1a; class Solution { public:vector<vector<int>> res;vector<int> path;void backtracing(int n, int k, int startIndex) {if (path.size() k) {res.push_back(path);re…

Springboot集成Camunda并完成一条流程实例

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;设计流程定…

Qt/C++音视频开发65-切换声卡/选择音频输出设备/播放到不同的声音设备/声卡下拉框

一、前言 近期收到一个用户需求&#xff0c;要求音视频组件能够切换声卡&#xff0c;首先要在vlc上实现&#xff0c;于是马不停蹄的研究起来&#xff0c;马上查阅对应vlc有没有自带的api接口&#xff0c;查看接口前&#xff0c;先打开vlc播放器&#xff0c;看下能不能切换&…

MySQL中where和having的区别

前言 数据库中的 WHERE 和 HAVING 子句在 SQL 查询中扮演着关键的角色&#xff0c;帮助我们有效地筛选和过滤数据。这两个子句虽然都用于限定结果集&#xff0c;但它们的应用场景和操作对象存在明显的区别。在理解和运用这两个子句的过程中&#xff0c;我们能够更灵活地进行数据…

clickhouse行转列的转换

1、原表select * from test 2、一个人的每个科目作为一行记录 改为一个人的所有科目作为一行记录 方式1 select name, sum(case when subject‘语文’ then score else 0 end) as chinese, sum(case when subject‘数学’ then score else 0 end) as math from test group by …

Kotlin 协程:深入理解 ‘async { }‘

Kotlin 协程&#xff1a;深入理解 ‘async { }’ Kotlin 协程是一种强大的异步编程工具&#xff0c;它提供了一种简洁、易读的方式来处理并发和异步操作。在 Kotlin 协程库中&#xff0c;async {} 是一个关键的函数&#xff0c;它允许我们启动一个新的协程&#xff0c;并返回一…