如何显示没有大的内存分配的快速更新的图像

如何显示没有大的内存分配的快速更新的图像

本文介绍了如何显示没有大的内存分配的快速更新的图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经得到了以每秒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"

这篇关于如何显示没有大的内存分配的快速更新的图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 01:11