问题描述
我已经得到了以每秒30帧的速度向上显示++用C产生超声图像的超声机器上的WPF应用程序。
I've got a WPF application on an ultrasound machine that displays ultrasound images generated in C++ at a speed upwards of 30 frames per second.
据我了解,在WPF显示图像的正常程序是为您创造图像的BitmapSource并设置源为您的图片,然后使其失效和显示。
From what I understand, the normal process for displaying images in WPF is to create a BitmapSource for your image and set the Source for your Image, which then causes it to invalidate and display.
由于BitmapSources不实现IDisposable,用这种方法逼我创造30 BitmapSources第二。对于32bppArgb格式的640×480的图像,这大约是30MB /内存秒被分配一秒钟,然后垃圾处置每隔10秒,造成明显的滞后性。显然不是一个可以接受的解决办法。
Since BitmapSources do not implement IDisposable, using this method forced me to create 30 BitmapSources a second. For a 640x480 image with 32bppArgb format, this is around 30MB/sec of memory being allocated a second and then garbage disposed every 10 seconds, causing visible lag. Obviously not an acceptable solution.
我目前的解决方案是:
在C ++:我创建托管C ++一个System.Drawing.Bitmap(的WinForms位图),从一个指针做的memcpy来填充画面,使用Graphics对象做一些额外的图纸,我需要和过程中传递到C#/ WPF这ImageReceived事件。
In C++: I create a System.Drawing.Bitmap (WinForms bitmap) in Managed C++, do a memcpy from a pointer to populate the picture, use the Graphics object to do some additional drawing I need, and pass this into the C#/WPF during an ImageReceived event.
在C#中 Image.Source被设定为BitmapBuffer生成的来源,这是访问原始数据的劈路位图来源:请参见我。做一个的P / CopyMemory的的调用来将数据从Bitmap.Scan0入BitmapBuffer复制。然后,我无效图像更新屏幕,和Dispose()的Drawing.Bitmap对象来释放内存。
In C# Image.Source is set to a source generated by BitmapBuffer, which is a hack-way of accessing the raw data of the bitmap source: See this link. I do a P/Invoke of CopyMemory to copy the data from the Bitmap.Scan0 into the BitmapBuffer. I then invalidate the Image to update the screen, and Dispose() the Drawing.Bitmap object to free the memory.
虽然这种方法已经一段时间的工作,似乎。非常哈克,我很难相信,有没有其他的适当的方式来做到这一点不是通过反射
While this method has worked for a while, it seems very hacky and I find it hard to believe that there is no other "appropriate" way to do this than through reflection.
问:是有没有更好的办法?
Question: Is there a better way?
推荐答案
下面是一个WPF的BitmapSource和GDI位图之间的一些代码,我写了*的别名(共享内存) (我自己的项目)
Here's some code I wrote* for aliasing (sharing memory) between a WPF BitmapSource and a GDI Bitmap (for my own project)
显然,你需要调整它自己的需要,它可能会最终有一个不那么哈克的感觉了。结束
Obviously, you'll need to tweak it for your own needs, it'll probably end up with a less "hacky" feel in the end.
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<ExceptionEventArgs> DownloadFailed;
public override event EventHandler<ExceptionEventArgs> 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分钟
*by "wrote" I mean "threw together in 10 minutes"
这篇关于如何显示没有大的内存分配的快速更新的图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!