ImageSource 来自 3 IntPtr
ImageSource from 3 IntPtr
我从外部库中获取了 RGB 通道数组的三个 IntPtr。
目前我将三个数组合并为一个并从新数组创建一个 ImageSource。
但是图像可能真的很大(目前高达 8000 x 4000 像素),所以转换已经在内存中的数据需要很长时间。
有没有办法在不复制的情况下使用这些指针在 canvas 中显示图像? IE。使用 costum OnRender 方法或其他方法派生的 ImageSource class?
我没有发现任何属于我的问题。
更新:
我当前的代码如下所示:
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;
WPF 图像源实际上是驻留在 GPU 上的纹理,因此它们必须具有非常特定的格式。这世上你的三阵过不去。
但是,8000x4000 仅为 32MB(乘以颜色字节),在 RAM 中没有什么可复制的。如果你真的将你的减速描述为与此有关,我敢打赌你做错了什么(使用 List<>
或类似的可增长数组而不是预先分配整个缓冲区,多次重做计算等)
作为我头脑中的一个优化技巧,我建议不要使用 3 个指针同时前进的简单实现,一次处理一个数组以将其保存在 L1 缓存中。
正确答案是:
摆脱循环中的高成本计算。在这种情况下,它是除法。具有高成本的计算是不在 CPU.
的指令集中的每个计算
第二个是,Parallel.For循环可以提高速度,但前提是循环的每个线程都有更大的工作量。否则处理成本太高
所以现在我更改了我的代码并为每一行使用一个 Parallel.For 循环,并为该行中的每个像素使用一个内部 for 循环。
现在我可以在 32 毫秒内转换大小为 8000x4000 24rgb 的图像(在我的系统上我可以说 1 百万像素 = 1 毫秒)。
对于未来:每个有问题的人都想知道,为什么他的问题被否决了。如果你不知道答案或者只写bull***t,请停止。
我从外部库中获取了 RGB 通道数组的三个 IntPtr。 目前我将三个数组合并为一个并从新数组创建一个 ImageSource。
但是图像可能真的很大(目前高达 8000 x 4000 像素),所以转换已经在内存中的数据需要很长时间。
有没有办法在不复制的情况下使用这些指针在 canvas 中显示图像? IE。使用 costum OnRender 方法或其他方法派生的 ImageSource class?
我没有发现任何属于我的问题。
更新: 我当前的代码如下所示:
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;
WPF 图像源实际上是驻留在 GPU 上的纹理,因此它们必须具有非常特定的格式。这世上你的三阵过不去。
但是,8000x4000 仅为 32MB(乘以颜色字节),在 RAM 中没有什么可复制的。如果你真的将你的减速描述为与此有关,我敢打赌你做错了什么(使用 List<>
或类似的可增长数组而不是预先分配整个缓冲区,多次重做计算等)
作为我头脑中的一个优化技巧,我建议不要使用 3 个指针同时前进的简单实现,一次处理一个数组以将其保存在 L1 缓存中。
正确答案是:
摆脱循环中的高成本计算。在这种情况下,它是除法。具有高成本的计算是不在 CPU.
的指令集中的每个计算第二个是,Parallel.For循环可以提高速度,但前提是循环的每个线程都有更大的工作量。否则处理成本太高
所以现在我更改了我的代码并为每一行使用一个 Parallel.For 循环,并为该行中的每个像素使用一个内部 for 循环。
现在我可以在 32 毫秒内转换大小为 8000x4000 24rgb 的图像(在我的系统上我可以说 1 百万像素 = 1 毫秒)。
对于未来:每个有问题的人都想知道,为什么他的问题被否决了。如果你不知道答案或者只写bull***t,请停止。