我不清楚原生互操作的机制。
假设我执行以下操作:
IntPtr nativeArray = Marshal.AllocHGlobal(stride * height);
someNativeCallToFillRawImageData(nativeArray, width, stride, height);
return new Bitmap(width, height, stride, PixelFormat.Format24bppRgb, nativeArray);
我分配的数组然后是位图的来源(它可以工作),但我不确定它的内存是否会被清除?
或者,我可以执行以下操作(通过更改DLLImport签名...本机方法最初定义为(unsigned char * buff)):
byte[] managedArray = new byte[stride * height];
someNativeCallToFillRawImageData(managedArray, width, stride, height);
fixed (byte* ptr = managedArray)
{
return new Bitmap(width, height, stride, PixelFormat.Format24bppRgb, new IntPtr(ptr));
}
这也有效,但我并不清楚其中的区别。我也认为第一个变体更快,因为它不必跨越托管/非托管边界。
托管的Bitmap对象是否处理Scan0中的数据,即使它是由其他人分配的? bitmap.Dispose() - >在managedArray或nativeArray中分配内存会发生什么?
非常感谢你!
答案 0 :(得分:2)
如果使用Marshal.AllocHGlobal并且位图从指针复制数据,则应使用Marshal.FreeHGlobal释放它。 我建议你在BitMap构造函数上阅读MSDN,看它是复制数据还是仅使用指针;如果它只是使用指针你必须等待释放它。
答案 1 :(得分:1)
我认为你不需要自己分配内存。创建一个具有所需大小的空位图,然后调用LockBits来访问原始像素数据:
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
Rectangle rect = new Rectangle(width, height);
BitmapData data = null;
try
{
data = bmp.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
someNativeCallToFillRawImageData(data.Scan0, data.Width, data.Stride, data.Height);
}
finally
{
if (data != null)
bmp.UnlockBits(data);
}
这样,内存由Bitmap
对象处理,因此您无需担心。
答案 2 :(得分:1)
您应该在使用非托管资源(在您的情况下为nativeArray)的类中创建Dispose方法,并使用Marshal.FreeHGlobal(nativeArray )
释放它。像这样:
if(nativeArray != IntPtr.Zero)
Marshal.FreeHGlobal(nativeArray);
您有责任调用已创建的Dispose方法。