C# Marshal.copy从bitmap.scan0复制到float[]

C# Marshal.copy从bitmap.scan0复制到float[],c#,bitmap,mono,marshalling,C#,Bitmap,Mono,Marshalling,我正在尝试将托管位图复制到非托管浮点数组(用于Opencl.net包装器的Cl.CreateImage2D)。不幸的是,我得到了一个异常,但是如果我将数组长度(srcIMGBytesSize)除以4,我就成功了。我的数组长度有问题吗?图像格式为32bppargb。我用的是单声道 System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(inputImage); bitmapData = bmpImage.LockBits( new Re

我正在尝试将托管位图复制到非托管浮点数组(用于Opencl.net包装器的Cl.CreateImage2D)。不幸的是,我得到了一个异常,但是如果我将数组长度(srcIMGBytesSize)除以4,我就成功了。我的数组长度有问题吗?图像格式为32bppargb。我用的是单声道

System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(inputImage);
bitmapData = bmpImage.LockBits( new Rectangle(0, 0, bmpImage.Width, bmpImage.Height), ImageLockMode.ReadOnly, inputImage.PixelFormat);
IntPtr srcBmpPtr = bitmapData.Scan0;
int bitsPerPixel = Image.GetPixelFormatSize( inputImage.PixelFormat );
srcIMGBytesSize = bitmapData.Stride * bitmapData.Height;
float[] srcImage2DData = new float[srcIMGBytesSize];
Marshal.Copy(srcBmpPtr, srcImage2DData, 0, srcIMGBytesSize);   //Exception at this line
bmpImage.UnlockBits( bitmapData );
尝试将数据复制到float[]数组时出现以下异常:

System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception.
   at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object destination, Int32 startIndex, Int32 length)
   at System.Runtime.InteropServices.Marshal.Copy(IntPtr source, Single[] destination, Int32 startIndex, Int32 length)
谢谢大家!

请从MSDN中查看此内容

非托管的C样式数组不包含边界信息,这 防止验证startIndex和length参数。 因此,与源参数对应的非托管数据 填充托管阵列,而不考虑其用途。你必须 在调用之前,使用适当的大小初始化托管阵列 这个方法

基本上,您正在尝试将字节数组复制到浮点数组,每个浮点(单个)的大小为4字节,因此,非托管数组中的每四个字节都将使用Marshal存储在一个浮点值中。copy,您可以通过执行以下代码来检查这一点:

byte[] byteSrcImage2DData = new byte[srcIMGBytesSize];
Marshal.Copy(srcBmpPtr, byteImage2DData, 0, srcIMGBytesSize);
它之所以有效,是因为整个源数组将使用目标数组的所有字段,而不是第一次尝试时仅使用第一个季度的字段

您可以使用此代码解决您的问题。您可以先将非托管数组复制到字节数组,然后再将字节数组复制到浮点数组:

System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(inputImage);
BitmapData bitmapData = bmpImage.LockBits(new Rectangle(0, 0, bmpImage.Width, bmpImage.Height), ImageLockMode.ReadOnly, inputImage.PixelFormat);
IntPtr srcBmpPtr = bitmapData.Scan0;
int bitsPerPixel = Image.GetPixelFormatSize(inputImage.PixelFormat);
int srcIMGBytesSize = bitmapData.Stride * bitmapData.Height;
byte[] byteSrcImage2DData = new byte[srcIMGBytesSize];
Marshal.Copy(srcBmpPtr, byteSrcImage2DData, 0, srcIMGBytesSize);
float[] srcImage2DData = new float[srcIMGBytesSize];
Array.Copy(byteSrcImage2DData, srcImage2DData,srcIMGBytesSize);   //Exception at this line
bmpImage.UnlockBits(bitmapData);

非常感谢,这很有道理@Ilya:如果使用堆栈上的指针,如果不安全,可能会跳过最后3行。还有一个问题-如何将最终数组转换为IntPtr?所以基本上我要做的是将bitmapData.scan0从指向byte[]的指针转换为指向float[]的指针。检查堆栈,您应该只创建floatArray的数组。长度*4