WPF:如果经常更新位图,则呈现WriteableBitmap的最佳方法

时间:2013-01-20 12:29:13

标签: wpf bitmap

我目前正在WPF中使用WriteableBitmap实现宽带声纳显示。 宽带声纳“瀑布”显示从顶部开始,随着时间的推移,历史数据向下移动,第一个“行”始终显示当前情况。

从技术上讲,我首先用WriteableBitmap.CopyPixels()向下移动Bitmap的内容,之后我更新数组以更新Display的当前行(顶部)。

我现在的问题是 - 在更新位图时 - 屏幕闪烁。我试着编写自己的WritePixels实现:

 public static unsafe void WritePixels(WriteableBitmap writeableBitmap, BitmapProperties bitmapProperties)
    {

       writeableBitmap.Lock();
       IntPtr buff = writeableBitmap.BackBuffer;

       byte* pbuff = (byte*)buff.ToPointer();

        for (int i = 0; i < bitmapProperties.BitmapArray.Length; i += bitmapProperties.BytesPerPixel)
        {
            pbuff[i] = bitmapProperties.BitmapArray[i];
            pbuff[i + 1] = bitmapProperties.BitmapArray[i + 1];
            pbuff[i + 2] = bitmapProperties.BitmapArray[i + 2];
            pbuff[i + 3] = bitmapProperties.BitmapArray[i + 3];

        }

        writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, (int)writeableBitmap.Width, (int)writeableBitmap.Height));
        writeableBitmap.Unlock();

    }

不幸的是,ouctome是一样的。

我在这里看到了一些类似的问题(实现了医学超声波显示),但这里的用例略有不同,因为我不是第三方c ++界面的图片,而是我'画'并自己复制位图(改变/复制位图数组)。 渲染(位图的更新)应每〜250毫秒进行一次。

这里我最好的选择是什么?使用缓存的位图?我在WPF中的低级位图操作方面没有太多经验(我使用的是WPF 4.5)。

感谢。

编辑:我把它与用C ++ / DirectX编写的参考应用程序进行了比较:令我惊讶的是,即使发生这种情况,我也会看到“闪烁”。这可能是一些光学效应,扰乱了眼睛等。然而,问题仍然是有效的,如果有一个比我目前的实施更好的方法。

2 个答案:

答案 0 :(得分:0)

您是否尝试过测量刷新整个图像是否需要太长时间?也许双缓冲可以帮助你:

  • 复制整个位图
  • 添加更改或在后台线程中替换图像副本
  • 如果工作完成,请使用当前可见图像从后台线程切换准备好的图像
  • 再次对当前不可见的图像进行更改等等......

答案 1 :(得分:0)

也许您可以在kernel32.dll中使用CopyMemory,这会更快

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

private Data2Image(int width, int height, IntPtr data, WriteableBitmap)
{
    writeableBitmap.Lock();            
    try
    {
        CopyMemory(writeableBitmap.BackBuffer, data, (uint)(width * height * 4));
        writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
    }
    finally
    {
        writeableBitmap.Unlock();
    }
}