我发现了几种用于优化WPF中位图处理的模式.但是,我不了解何时使用每种模式.我认为这是一个常见问题,我总结了我的理解和猜测,并请求您的帮助.如果您可以添加模式,解释它们的不同之处,解释它们是否使用CPU或GPU,并教授何时使用它们以及如何组合它们,这将是一个巨大的帮助!
上下文 - 图像"网格"场景:
我的应用程序必须显示许多位图图像.图像以行和列网格状组织显示在屏幕上(不一定是Grid或UniformGrid类,想想Window Media Player的Album视图).图像可能在不同的网格单元之间移动 任意单元格中的某些图像可能会被其他图像替换.图像应该是可点击的,应该提供一个上下文菜单,应该是可选择的,可拖动的等等.换句话说,"将小虫子组合成一个大的位图"是不适用的,至少不是天真的.
模式0:黑客
将小虫子组合成位图(如何绘制上下文?),并将其用作背景.使用空内容处理命中,上下文菜单,事件等的图像叠加此图像.
优点是我们这里只讨论两个位图:当前显示的位图和应该替换它的位图.这应该非常快.然而,我多年的经历引发了危险的危险.你的评论?
模式1:减小图像大小
如果您事先知道要调整大小的图像大小,以及当您准备丢失性能的详细信息(颜色)时,这是一个明智的做法:
见代码在这里.
模式2:背景预取
当您认为可以利用用户注视屏幕上的图像时,此模式适用,并提前准备要显示的下一个图像.除了内存开销之外,项目的缺点是它必须支持.Net Framework 4目标而不仅仅是客户端配置文件,因此它可能会在客户端上进行安装.你自己将不得不忍受异步编程的痛苦.
在此模式中,您可以精确创建所需数量的图像控件.当需要添加,移动或删除位图时,您只需修改Image控件的BitmapSource(s).BackgroundWorker任务负责预取BitmapSource(可能使用上面的"Reduce Image Size"模式)并将它们插入MemoryCache.
为此,您必须将BitmapImage的CacheOption设置为OnLoad,以便将工作卸载到后台工作程序.
模式3:绘制上下文
这是从在MSDN WPF论坛Microsoft支持建议谢尔登Ziao 这里.有关DrawingContext的说明,请参阅Adam Nathan的WPF 4中的第494页,第15章"2D图形".我不能说我理解它.根据这里的答案,我认为这将改善几何图纸的处理,而不是位图.接下来,我认为这不会支持图像的焦点和事件要求(我不好在论坛上没有更好地解释要求)而且,我很担心这本书的总结句:"注意使用DrawingContext不会改变您在保留模式系统中运行的事实.指定的图纸不会立即发生; 命令由WPF保留,直到需要它们为止."这意味着一旦我们的偶数处理程序恢复,我们就无法利用"背景预取"中的并行性.
模式4:可写位图
这里的MSDN文档将其描述为双缓冲系统:您的UI线程更新缓冲区; WPF的渲染线程将其移动到视频内存.
预期用法(参见此处)适用于在显示等视频电影中发生重大变化的位图.我不确定,但可能会被黑客攻击并与背景预取模式结合并在网格场景中使用.
模式5:缓存的位图
关于MSDN的信息不多(这里).在WPF论坛存档(这里),它解释说"BitmapCache API旨在缓存你的内容(当在硬件中渲染时)在视频内存中,这意味着它仍然驻留在你的GPU上.这样可以节省在将内容绘制到屏幕时重新呈现内容的成本."这似乎是一个好主意.但是,我不确定是什么陷阱以及如何使用它.
模式6:RenderTargetBitmap
RenderTargetBitmap将Visual转换为位图.我不确定这里是否相关.看到这里.
编辑:关于Paul Hoenecke的问题:我写过"我的应用程序必须显示许多位图".我没有提到,我需要显示约800图像并发.
人们可以阅读我的问题所涉及的性能问题WPF Bitmap性能以及如何使WPF上的图像显示更加"活泼"?
我已经修改了模式1的描述,以突出显示未创建或删除图像控件的概念(除非我们想要显示更大或更小的网格).只有它们的Sources被设置为不同的,新的或null的BitmapSources.
编辑: …
我正在创建一个WPF映射程序,它可能会在任何时候将数百个文件加载并绘制到屏幕上,用户可能想要缩放和平移此显示.其中一些文件类型可能包含数千个点,这些点很可能作为某种路径连接.其他支持的格式将包括TIFF文件.
具有单个DrawingVisual以获取所有数据的性能是否更好?或者我应该为每个加载的文件创建新的DrawingVisual?
如果有人可以就此提出任何建议,我将不胜感激.