来自3 IntPtr的ImageSource

时间:2015-11-27 18:10:57

标签: c# wpf pointers imagesource

我从外部库获取RGB通道数组的三个IntPtr。 目前,我将三个数组合并为一个,并从新数组创建一个ImageSource。

但是图像可能非常庞大(目前高达8000 x 4000像素),因此已经存储在内存中的数据转换时间过长。

有没有办法使用这些指针在画布中显示图像而不复制?即带有Costum OnRender方法的ImageSource的派生类?

我没有发现任何属于我的问题。

更新 我目前的代码如下:

int unmapByes = Math.Abs(stride) - (width * 3);
        byte* _ptrR = (byte*)ptrR;
        byte* _ptrG = (byte*)ptrG;
        byte* _ptrB = (byte*)ptrB;
        BitmapSource bmpsrc = null;
        App.Current.Dispatcher.Invoke(() =>
        {
            bmpsrc = BitmapSource.Create(width,
                                                  height,
                                                  96,
                                                  96,
                                                  PixelFormats.Bgr24,
                                                  null,
                                                  new byte[bytes],
                                                  stride);
        });
        BitmapBuffer bitmapBuffer = new BitmapBuffer(bmpsrc);
        byte* buffer = (byte*)bitmapBuffer.BufferPointer;


        Parallel.For(0, bytes / 3 - height, (offset) =>
        {
            int i = offset * 3 + (((offset + 1) / width)) * unmapByes;
            *(buffer + i) = *(_ptrB + offset);
            *(buffer + i + 1) = *(_ptrG + offset);
            *(buffer + i + 2) = *(_ptrR + offset);
        });
        return bmpsrc;

2 个答案:

答案 0 :(得分:0)

WPF图像源实际上是驻留在GPU上的纹理,因此它们必须具有非常特定的格式。在这个世界上你用三个阵列赢得了胜利。

但是,8000x4000只有32MB(彩色字节的倍数),没有什么可以在RAM中复制。如果你真的描述了你的减速情况,我会打赌你做错了(使用List<>或类似的可增长数组而不是预先分配整个缓冲区,重做计算不止一次等等。)

作为我头脑中的一个优化提示,我建议不要使用同时推进的3个指针的naive实现,一次执行一个数组以将其保留在L1缓存中。

答案 1 :(得分:0)

正确的答案是:

摆脱循环中的计算,这些计算成本很高。在这种情况下,它是分裂。高成本的计算是每次计算都不在CPU的指令集中。

第二个是,Parallel.For循环可以提高速度,但前提是循环的每个Thread都有更多的工作量。否则处理成本太高。

所以现在我改变了我的代码并为每一行使用了Parallel.For循环,并为此行中的每个像素使用了一个内部for循环。

现在我可以在32毫秒内转换大小为8000x4000 24rgb的图像(在我的系统上我可以说1百万像素= 1毫秒)。

对于未来:每个有疑问的人都想知道,为什么他的问题被否决了。如果你不知道答案或只写公牛,请停止它。