【问题标题】:Is it possible to modify a WPF BitmapSource in memory 'unsafe'ly from another thread是否可以从另一个线程“不安全”地修改内存中的 WPF BitmapSource
【发布时间】:2011-04-24 20:01:03
【问题描述】:

我想在 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 可能可以做到这一点,但这是一个涉及多个线程的学术练习(在不安全模式下编辑位图时支持)。

提前致谢

【问题讨论】:

  • 我在另一台机器上有一些很好的代码。如果你在几个小时内没有得到回复,我会抓住它。我相信我虽然使用了 BitmapImage。它派生自 BitmapSource。我不记得了,但我有一种感觉,你总是需要将它转换为位图。不过,还有更优雅的转换方式。

标签: c# wpf bitmap imaging bitmapsource


【解决方案1】:

我会告诉你我所知道的。

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

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

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

你考虑过WriteableBitmap吗?这是 WPF 团队对所有复制的普遍抱怨的回应。

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

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

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

【讨论】:

  • 谢谢,我确实知道 WriteableBitmap 但这只能由单线程 IIRC 更新。我真的很想在后台线程中播放图像,我认为 WritableBitmap 是可能的,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2023-04-10
  • 2021-07-17
  • 2019-02-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多