【问题标题】:BitmapSource access with pointers使用指针访问 BitmapSource
【发布时间】:2014-01-26 16:22:55
【问题描述】:

有没有办法使用 c# 指针访问 BitmapImage 对象的底层内存?

我知道有一个 CopyPixels 方法,但它会将像素数组的副本复制到一个新数组中(复制内存要求)。如果您打开一个大图像(2gb),它会分配很多无用的东西。如果你想操作某种精细化,比如 CCLA,它需要大量的内存。

我只需要读取像素数组。

是否可以像在System.Drawing.Bitmap 中那样直接寻址像素?

我为System.Drawing.Bitmap 编写了一个快速位图访问,但由于我使用的是 WPF,我需要为BitmapSource 提供相同的功能。否则我必须复制图像加载(旧方法的位图和 BitmapSource 在 WPF 中显示图像)占用大量内存和时间。

谢谢 洛伦佐

【问题讨论】:

    标签: c# wpf image-processing bitmap bitmapsource


    【解决方案1】:

    位图源不一定具有整个图像的后备内存。一个例子是延迟加载的磁盘上的图像文件。

    您对 WIC 以及 WPF 的唯一访问权限是 CopyPixels 方法。 BitmapSource 的某些子类将允许访问缓冲区,但它们在内部只是分配内存并自己调用 CopyPixels

    我会假设任何操作都不需要一次访问整个图像。如果是这样,您可以将CopyPixels 调用到较小的缓冲区,并窗口化您对图像的访问。大多数解码器,当请求单个像素时,将缓冲整个步幅,或者在 JPEG 的情况下,然后是整个块。

    我不确定 CCLA 是什么,也找不到合适的定义,但如果它是对源图像的某种变换,您可以将其实现为 BitmapSource。这样你就可以compose a full chain

    仔细注意源图像上使用的CacheOption 以及转换的顺序,您应该能够访问任意大的图像而不会显着影响内存。

    如果您已经有了 GDI 的高性能算法 (System.Drawing),那么重新实现它是没有意义的。您仍然可以使用 Imaging.CreateBitmapSourceFromHBitmap 或使用 WindowsFormsHost 来托管您之前构建的控件来显示最终位图。

    【讨论】:

    • CCLA 代表 Connected component labeling algorithm HERE。为了工作,它需要整个图像分配。是的,我有一个刚刚用 System.Drawing 编写的算法。当我加载 2-4gb 的图像时,使用您建议的方法它会创建位图的副本以渲染图像 (CreateBitmapSourceForHBitmap)。同样,CCLA 需要一个 int 数组来标记图像,我需要大约 14~15gb 的内存来完成这项工作。没有图像转换,我只需要 ~9gb 的内存。
    • 使用WriteableBitmap.BackBuffer直接访问图片怎么样?你认为是个好主意吗?您认为可写位图会创建原始位图的副本吗?
    • 可写位图只能调用CopyPixels。如果您将其设为唯一存在的副本,那么我认为访问WritableBitmapBackBuffer 是一个好主意。我也会在开窗后继续通过CreateBitmapSourceForHBitmap 使用GDI 算法或使用WindowsFormsHost,但这只是我。
    猜你喜欢
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2017-07-18
    • 2011-02-03
    相关资源
    最近更新 更多