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

发布于 2024-09-27 06:32:11 字数 923 浏览 2 评论 0原文

我想在 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 在位图示例中所示的那样。这可能吗?

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

提前致谢

I would like to do some processing of images in a WPF application. However, I would like to modify the pixels of a BitmapSource in memory at runtime.

I'm currently managing to do this using 'unsafe' code against an old fashioned System.Drawing.Bitmap and it works a treat (lock a working area, fiddle with the pixels) job done. The approach is described in this post: http://blogs.msdn.com/b/ericgu/archive/2007/06/20/lost-column-2-unsafe-image-processing.aspx

To get this working in WPF I'm then creating a WPF BitmapSource using this approach:

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

However, this creates a lot of copies in memory and I really want to get in there and fiddle with the underlying bits inside the BitmapSource just like EricGu showed in the Bitmap example. Is this possible?

I realise that PixelShaders can probably do this but this is an academic exercise involving multiple threads (which is supported when editing a bitmap in unsafe mode).

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月亮是我掰弯的 2024-10-04 06:32:11

我会告诉你我所知道的一切。

首先,在将位图返回到主线程之前,您似乎已经了解了冻结位图。这是一个好的开始。

我曾经尝试通过从 BitmapSource 派生新的实现来减少复制,并覆盖将数据复制出位图的虚拟函数。它有效,但产生了大量的内存泄漏。一直没弄清楚。

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

您是否考虑过 WriteableBitmap?这是 WPF 团队对有关所有复制的常见抱怨的回应。

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

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

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

I'll tell you as much as I know.

First you appear to already know about Freezing bitmaps before giving them back to the main thread. That's a good start.

I have once tried to reduce copying by deriving a new implementation from BitmapSource, and override the virtual functions that copy your data out of the bitmap. It worked but produced massive memory leaks. Never figured it out.

You can also of course create a BitmapSource directly from an array of bytes (and lose overhead of the GDI bitmap). msdn docs

Have you considered a WriteableBitmap? That was the WPF team's response to the common complaint about all of the copying.

Edit: MSDN says explicitly (in WritableBitmap.BackBuffer documentation) that it can be used from a background thread:

You can pass the BackBuffer pointer to
external components and other threads
for processing, but if you do, you
must provide you own thread
coordination. In particular, you must
ensure that the UI thread specifies
changed areas by calling the
AddDirtyRect method, and that the UI
thread unlocks the buffer by calling
the Unlock method.

So if you let the UI thread aquire the lock and the pointer, you can let a worker thread write the pixels.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文