是否有可能从另一个线程中“不安全”地修改内存中的WPF BitmapSource

时间:2010-10-13 12:40:05

标签: c# wpf bitmap imaging bitmapsource

我想在WPF应用程序中对图像进行一些处理。但是,我想在运行时修改内存中BitmapSource的像素。

我目前正在使用针对旧式System.Drawing.Bitmap的“不安全”代码来执行此操作,并且它可以完成工作(锁定工作区域,完成像素)。这篇文章描述了这种方法:http://blogs.msdn.com/b/ericgu/archive/2007/06/20/lost-column-2-unsafe-image-processing.aspx

为了在WPF中工作,我正在使用这种方法创建一个WPF BitmapSource:

    BitmapSource destination;
    IntPtr hBitmap = bitmap.GetHbitmap();
    BitmapSizeOptions sizeOptions = BitmapSizeOptions.FromEmptyOptions();
    destination = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, sizeOptions);
    destination.Freeze();
    return destination;

然而,这会在内存中创建大量副本,我真的想进入那里,并在BitmapSource中调整底层位,就像EricGu在Bitmap示例中所示。这可能吗?

我意识到PixelShaders可能会这样做,但这是一个涉及多个线程的学术练习(在不安全模式下编辑位图时支持)。

提前致谢

1 个答案:

答案 0 :(得分:3)

我会尽可能多地告诉你。

首先,您似乎已经知道冻结位图,然后再将它们返回主线程。这是一个好的开始。

我曾尝试通过从BitmapSource派生新实现来减少复制,并覆盖将数据复制出位图的虚函数。它工作但产生了大量的内存泄漏。从未弄明白。

当然,您也可以直接从字节数组创建BitmapSource(并减少GDI位图的开销)。 msdn docs

您考虑过WriteableBitmap吗?这就是WPF团队对所有复制的共同抱怨的回应。

编辑:MSDN明确说明(在WritableBitmap.BackBuffer文档中)它可以在后台线程中使用:

  

您可以将BackBuffer指针传递给   外部组件和其他线程   处理,但如果你这样做,你   必须为您提供自己的线程   协调。特别是,你必须   确保UI线程指定   通过调用来改变区域   AddDirtyRect方法,即UI   线程通过调用解锁缓冲区   解锁方法。

因此,如果您让UI线程获取锁和指针,您可以让工作线程写入像素。