如何在没有大内存分配的情况下显示快速更新的图像?

我在超声波机器上有一个WPF应用程序,它以高达每秒30帧的速度显示用C ++生成的超声图像。

据我所知,在WPF中显示图像的正常过程是为您的图像创建一个BitmapSource,并为您的图像设置Source,然后使其无效并显示。

由于BitmapSources没有实现IDisposable,使用这种方法迫使我每秒创建30个BitmapSources。 对于具有32bppArgb格式的640×480图像,这是每秒分配大约30MB /秒的内存,然后每10秒进行一次垃圾处理,导致可见的延迟。 显然不是一个可以接受的解决方案。

我目前的解决方案是:

在C ++中:我在托管C ++中创建一个System.Drawing.Bitmap(WinForms位图),从指针填充图片做一个memcpy,使用Graphics对象做我需要的一些额外的绘图,并将其传递给C#/ WPF在ImageReceived事件期间。

在C#中, Image.Source设置为BitmapBuffer生成的源,这是访问位图源的原始数据的一种黑客方式:请参阅此链接。 我做了一个CopyMemory的P / Invoke来将Bitmap.Scan0中的数据复制到BitmapBuffer中。 然后我使Image无效以更新屏幕,然后Dispose()Drawing.Bitmap对象释放内存。

虽然这种方法已经工作了一段时间,但它似乎非常黑客,我发现很难相信除了通过reflection之外没有其他“适当”的方法来做到这一点。

问题:有更好的方法吗?

这里是我编写的一些代码*用于WPF BitmapSource和GDI Bitmap(用于我自己的项目)之间的别名(共享内存)

显然,你需要根据自己的需要进行调整,最终可能最终会减少“hacky”的感觉。

class AliasedBitmapSource : BitmapSource { private Bitmap source; public AliasedBitmapSource(Bitmap source) { this.source = source; this.pixelHeight = source.Height; this.pixelWidth = source.Width; this.dpiX = source.HorizontalResolution; this.dpiY = source.VerticalResolution; } public override event EventHandler DownloadCompleted; public override event EventHandler DownloadFailed; public override event EventHandler DecodeFailed; protected override Freezable CreateInstanceCore() { throw new NotImplementedException(); } private readonly double dpiX; public override double DpiX { get { return dpiX; } } private readonly double dpiY; public override double DpiY { get { return dpiY; } } private readonly int pixelHeight; public override int PixelHeight { get { return pixelHeight; } } private readonly int pixelWidth; public override int PixelWidth { get { return pixelWidth; } } public override System.Windows.Media.PixelFormat Format { get { return PixelFormats.Bgra32; } } public override BitmapPalette Palette { get { return null; } } public unsafe override void CopyPixels(Int32Rect sourceRect, Array pixels, int stride, int offset) { BitmapData sourceData = source.LockBits( sourceRect.ToRectangle(), ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); fixed (byte* _ptr = &((byte[])pixels)[0]) { byte* dstptr = _ptr; byte* srcptr = (byte*)sourceData.Scan0; for (int i = 0; i < pixels.Length; ++i) { *dstptr = *srcptr; ++dstptr; ++srcptr; } } source.UnlockBits(sourceData); } } public static class Extensions { public static Rectangle ToRectangle(this Int32Rect me) { return new Rectangle( me.X, me.Y, me.Width, me.Height); } public static Int32Rect ToInt32Rect(this Rectangle me) { return new Int32Rect( me.X, me.Y, me.Width, me.Height); } } 

*“写”我的意思是“在10分钟内聚集在一起”

如果你使用最新的WPF位检查WriteableBitmap ,你将不得不做更多的腿部工作,但你真的会快速更新。

做一个快速的谷歌,你会得到一些样品。