我想在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可能会这样做,但这是一个涉及多个线程的学术练习(在不安全模式下编辑位图时支持)。
提前致谢
答案 0 :(得分:3)
我会尽可能多地告诉你。
首先,您似乎已经知道冻结位图,然后再将它们返回主线程。这是一个好的开始。
我曾尝试通过从BitmapSource派生新实现来减少复制,并覆盖将数据复制出位图的虚函数。它工作但产生了大量的内存泄漏。从未弄明白。
当然,您也可以直接从字节数组创建BitmapSource(并减少GDI位图的开销)。 msdn docs
您考虑过WriteableBitmap吗?这就是WPF团队对所有复制的共同抱怨的回应。
编辑:MSDN明确说明(在WritableBitmap.BackBuffer文档中)它可以在后台线程中使用:
您可以将BackBuffer指针传递给 外部组件和其他线程 处理,但如果你这样做,你 必须为您提供自己的线程 协调。特别是,你必须 确保UI线程指定 通过调用来改变区域 AddDirtyRect方法,即UI 线程通过调用解锁缓冲区 解锁方法。
因此,如果您让UI线程获取锁和指针,您可以让工作线程写入像素。