Fra*_*ell 1 c# c++ pinvoke unmanaged computer-vision
我正在运行一个处理位图图像的应用程序。现在我正在寻找一种快速方法来交换“Format24bppRgb”位图图像的“红色”和“蓝色”值。在我的 C# 代码中,我的第一次尝试是使用不安全的代码片段:
var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadWrite, bmp.PixelFormat);
unsafe
{
byte* array = (byte*)bmpData.Scan0.ToPointer();
byte temp;
for (int x = 0; x < bmp.Width * bmp.Height * 3; x = x + 3) {
temp = *(array + x + 2);
*(array + x + 2) = *(array + x);
*(array + x) = temp;
}
}
Run Code Online (Sandbox Code Playgroud)
对于我使用的位图大小,这大约需要 50-70 毫秒。现在我尝试使用 pinvoke 调用在外部库(基于 C++)中完成这项工作:
[DllImport("ByteSwitch.dll")]
public static extern IntPtr ChangeRB(IntPtr data, int width, int height);
data = ChangeRB(bmpData.Scan0, bmp.Width, bmp.Height);
Run Code Online (Sandbox Code Playgroud)
其定义如下:
extern "C" __declspec(dllexport) void* ChangeRB(void* xArray, int xHeight, int xWidth);
void* ChangeRB(void* array, int height, int width)
{
unsigned char* _array = (unsigned char*)array;
char temp;
for (int x = 0; x < height * width * 3; x = x + 3)
{
temp = _array[x + 2];
_array[x + 2] = _array[x];
_array[x] = temp;
}
return _array;
}
Run Code Online (Sandbox Code Playgroud)
这个调用大约需要 1 毫秒!所以我无法解释这里巨大的性能差异 - 或者非托管 pinvoke 真的比“不安全”代码片段快得多吗?
性能问题既不是来自互操作,也不是来自 C#,而是来自您在循环中使用位图的Width
and的事实。Height
两者都在内部调用 GDI Plus API:
public int Width {
get {
int width;
int status = SafeNativeMethods.Gdip.GdipGetImageWidth(new HandleRef(this, nativeImage), out width);
if (status != SafeNativeMethods.Gdip.Ok)
throw SafeNativeMethods.Gdip.StatusException(status);
return width;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在 C/C++ 情况下,您不会执行此操作...您会传递预先计算的高度和宽度。因此,如果您为此更改 C# 版本:
unsafe
{
byte* array = (byte*)bmpData.Scan0.ToPointer();
byte temp;
var max = bmp.Width * bmp.Height * 3;
for (int x = 0; x < max; x = x + 3) {
temp = *(array + x + 2);
*(array + x + 2) = *(array + x);
*(array + x) = temp;
}
}
Run Code Online (Sandbox Code Playgroud)
它可能在全球范围内运行得更快。您还可以使用像这样的安全版本:
private static void ChangeSafe(Bitmap bmp, BitmapData bmpData)
{
var array = bmpData.Scan0;
byte temp;
var max = bmp.Width * bmp.Height * 3;
for (var x = 0; x < max; x = x + 3)
{
temp = Marshal.ReadByte(array + x + 2);
Marshal.WriteByte(array + x + 2, Marshal.ReadByte(array + x));
Marshal.WriteByte(array + x, temp);
}
}
Run Code Online (Sandbox Code Playgroud)
它稍微慢一些,但避免了对不安全代码的需要。
归档时间: |
|
查看次数: |
871 次 |
最近记录: |