在 WPF 框架提供方便进行像素读写的 WriteableBitmap 类,本文来告诉大家在咱写下像素到 WriteableBitmap 渲染,底层的逻辑
之前我使用 WriteableBitmap 进行 CPU 高性能绘图时,在性能调试遇到一个问题,写入到 WriteableBitmap 的像素会经过两次拷贝。其中一次是我自己拷贝到 WriteableBitmap 而另一次拷贝就在 WriteableBitmap 里面。无论设置 WriteableBitmap 的脏区多大,渲染的时候是整个图片渲染 。本来按照我的阅读顺序,当前还没有阅读到 WriteableBitmap 的代码,但是有小伙伴和我报告了 WriteableBitmap 的坑,因此我就开始阅读 WriteableBitmap 详细请看 dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 后台线程创建 WriteableBitmap 锁住主线程
在开始之前,先聊聊 WriteableBitmap 是什么?在 WPF 和 UWP 中提供的 WriteableBitmap 是支持对像素写入而更改渲染的图片,当然,本文只聊 WPF 的源代码,关于 UWP 部分,咱只知道使用就可以。通过 WriteableBitmap 可以用来实现高性能的 CPU 渲染,以下是我的其他 WriteableBitmap 博客
在 WriteableBitmap 进行绘制时,有一个重要的功能是设置 DirtyRect 来告诉 WPF 层,当前需要更新的是 WriteableBitmap 的哪个内容。在调试时,可以看到如果 DirtyRect 很小,那么 CPU 占用也将会很小,但渲染时依然是渲染整个图片。在聊到 WriteableBitmap 的渲染和更新,就一定需要先聊到 AddDirtyRect 方法,下面咱看一下 AddDirtyRect 方法的实现
public void AddDirtyRect(Int32Rect dirtyRect)
{
WritePreamble();
if (_lockCount == 0)
{
throw new InvalidOperationException(SR.Get(SRID.Image_MustBeLocked));
}
//
// Sanitize the dirty rect.
//
dirtyRect.ValidateForDirtyRect("dirtyRect", _pixelWidth, _pixelHeight);
if (dirtyRect.HasArea)
{
MILSwDoubleBufferedBitmap.AddDirtyRect(
_pDoubleBufferedBitmap,
ref dirtyRect);
_hasDirtyRects = true;
}