首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF BitmapSource图像显示问题

WPF BitmapSource图像显示问题
EN

Stack Overflow用户
提问于 2018-12-21 13:22:34
回答 2查看 305关注 0票数 1

我需要显示一个原始字节数组中的8k RGB图像,这是我在wpf控制中以高fps速度获得的帧采集器。我能够成功地将字节数组转换为BitmapSource,并将其显示在WPF的图像窗口中。但是,由于抓取器在显示后以大约5FPS的速度生成图像,我正在释放对对象的保留,但GC需要时间收集内存,在此内存中,我的应用程序内存会增加,并冻结应用程序和我的系统。如何正确处理使用以下方法创建的BitmapSource(CachedBitmap)。请帮我处理使用后的物品。

我在图像更改时尝试了GC.Collect(),但它不起作用。

下面是我的字节数组到位图转换代码,

代码语言:javascript
复制
    int Width = 7680;
    int Height = 4320;
    PixelFormat PixelFormat = PixelFormats.Bgr24;
    int BytesPerPixel = 3;

    public BitmapSource ByteToImage(byte[] imageData)
    {            
        var stride = BytesPerPixel * Width;
        BitmapSource bitmapSource = BitmapSource.Create(Width, Height, 96d, 96d, PixelFormat, null, imageData, stride);
        bitmapSource.Freeze();
        return bitmapSource;
    }
EN

回答 2

Stack Overflow用户

发布于 2018-12-21 21:09:11

这听起来像是合成目标渲染的可能候选者,尝试将此添加到您的MainWindow构造函数中:

代码语言:javascript
复制
CompositionTarget.Rendering += CompositionTarget_Rendering;

然后实现函数本身:

代码语言:javascript
复制
void CompositionTarget_Rendering(object sender, EventArgs e)
{
    // dispose previous image, create and assign the new one
}

正确地这样做,它还应该处理目标机器无法跟上您期望的帧速率的情况。

更新: BitmapSource只使用常规内存,所以正确的行为是让GC清理它。如果在你的例子中没有发生这种情况,那么这意味着由于某种原因,可能是显示的原因,某些东西正在抓住那个内存。下面是一个使用CompositionTarget.Rendering的例子,我在收集之前和之后都转储了GC内存,这样你就可以很清楚地看到它被正确地收集了:

代码语言:javascript
复制
    public MainWindow()
    {
        InitializeComponent();
        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }       

    private void CompositionTarget_Rendering(object sender, EventArgs e)
    {
        // remove reference to old image
        this.theImage.Source = null;

        // invoke GC
        Debug.WriteLine(GC.GetTotalMemory(false));
        GC.Collect();
        Debug.WriteLine(GC.GetTotalMemory(false));

        // create and assign new image
        const int width = 1000;
        const int height = 1000;
        var pixels = new uint[width * height];
        uint color = (uint)((new Random((int)DateTime.Now.Ticks)).Next(0x1000000) | 0xff000000);
        for (int i = 0; i < width * height; i++)
            pixels[i] = color;
        this.theImage.Source = BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, pixels, width * 4);
    }
票数 0
EN

Stack Overflow用户

发布于 2018-12-25 03:03:42

也许你应该试试可写的位图:

代码语言:javascript
复制
        WriteableBitmap writeableBitmap = new WriteableBitmap(
            (int)width,
            (int)height,
            96,
            96,
            PixelFormats.Bgr32,
            null);

        int stride = width * writeableBitmap.Format.BitsPerPixel / 8

现在,当你收到一个帧时,你可以将它写入可写的位图中:

代码语言:javascript
复制
        writeableBitmap.Lock();
        writeableBitmap.WritePixels(new Int32Rect(0, 0, width, height), imageData, stride, 0);
        writeableBitmap.Unlock();

通过这种方式,您不需要创建新的映像。只需覆盖位图数据即可。但是要注意,始终要将数据从源抓取到同一个缓冲区数组中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53879583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档