我在超声波机上有一个 WPF 应用程序,以每秒 30 帧的速度显示 C++ 生成的超声图像。
据我所知,在 WPF 中显示图像的正常流程是为您的图像创建 BitmapSource,并设置 Image 的 Source,然后它会失效并显示。
由于 BitmapSources 不实现 IDisposable,使用此方法强制我每秒创建 30 个 BitmapSources。对于一个 640x480 的 32bppArgb 格式图像,这大约是每秒分配 30MB 的内存,然后每 10 秒进行垃圾回收,导致可见的延迟。显然,这不是一个可接受的解决方案。
我的当前解决方案是:
在 C++ 中:我在托管的 C++ 中创建了一个 System.Drawing.Bitmap(WinForms 位图),通过指针执行 memcpy 来填充图片,使用 Graphics 对象执行一些额外的绘图操作,并在 ImageReceived 事件期间将其传递到 C#/WPF 中。
在 C# 中,Image.Source 设置为由 BitmapBuffer 生成的源,这是一种访问位图源原始数据的 hack 方法:请参阅 此链接。我使用 P/Invoke 调用 CopyMemory 将数据从 Bitmap.Scan0 复制到 BitmapBuffer。然后我使 Image 失效以更新屏幕,并 Dispose() Drawing.Bitmap 对象以释放内存。
虽然这种方法已经运作一段时间,但它似乎非常 hacky,我很难相信除了通过反射之外没有其他“适当”的方法来做到这一点。
据我所知,在 WPF 中显示图像的正常流程是为您的图像创建 BitmapSource,并设置 Image 的 Source,然后它会失效并显示。
由于 BitmapSources 不实现 IDisposable,使用此方法强制我每秒创建 30 个 BitmapSources。对于一个 640x480 的 32bppArgb 格式图像,这大约是每秒分配 30MB 的内存,然后每 10 秒进行垃圾回收,导致可见的延迟。显然,这不是一个可接受的解决方案。
我的当前解决方案是:
在 C++ 中:我在托管的 C++ 中创建了一个 System.Drawing.Bitmap(WinForms 位图),通过指针执行 memcpy 来填充图片,使用 Graphics 对象执行一些额外的绘图操作,并在 ImageReceived 事件期间将其传递到 C#/WPF 中。
在 C# 中,Image.Source 设置为由 BitmapBuffer 生成的源,这是一种访问位图源原始数据的 hack 方法:请参阅 此链接。我使用 P/Invoke 调用 CopyMemory 将数据从 Bitmap.Scan0 复制到 BitmapBuffer。然后我使 Image 失效以更新屏幕,并 Dispose() Drawing.Bitmap 对象以释放内存。
虽然这种方法已经运作一段时间,但它似乎非常 hacky,我很难相信除了通过反射之外没有其他“适当”的方法来做到这一点。
问题:有更好的方法吗?