[英]Copying byte array with Marshal.Copy from IntPtr using C# doesn't work
我正在使用一个非托管库,它可以生成灰度图像(大约100x200像素,或多或少)。 图像包含在结构中,在C中如下所示:
typedef struct abs_image {
ABS_DWORD Width;
ABS_DWORD Height;
ABS_DWORD ColorCount;
ABS_DWORD HorizontalDPI;
ABS_DWORD VerticalDPI;
ABS_BYTE ImageData[ABS_VARLEN];
} ABS_IMAGE
typedef unsigned int ABS_DWORD;
typedef unsigned char ABS_BYTE;
在这里我的C#包装器结构:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ABS_IMAGE {
public uint Width;
public uint Height;
public uint ColorCount;
public uint HorizontalDPI;
public uint VerticalDPI;
public IntPtr ImageData;
}
ABS_IMAGE
图像并对ABS_IMAGE
结构进行编组可以正常工作。 在以前的版本中,我尝试使用固定长度的字节数组用于ImageData,有时会崩溃。 我想这发生了,因为图像尺寸没有修复。 现在我尝试在以后读取图像字节数组,之后我可以计算实际的数组长度。 这里有相关代码:
ABS_Type_Defs.ABS_IMAGE img =
(ABS_Type_Defs.ABS_IMAGE)Marshal.PtrToStructure(
pImage,
typeof(ABS_Type_Defs.ABS_IMAGE));
int length = ((int)img.Height - 1) * ((int)img.Width - 1);
byte[] data = new byte[length];
Marshal.Copy(img.ImageData, data, 0, length);
现在我的问题:每次我想执行Marshal.Copy读取图像字节时,我得到一个AccessViolationException
。
有没有人有想法?
这就是正在发生的事情。 您的结构是所谓的可变长度结构。 像素数据在结构中包含内联,从ImageData
的偏移量开始。
typedef struct abs_image {
ABS_DWORD Width;
ABS_DWORD Height;
ABS_DWORD ColorCount;
ABS_DWORD HorizontalDPI;
ABS_DWORD VerticalDPI;
ABS_BYTE ImageData[ABS_VARLEN];
} ABS_IMAGE
您的API返回pImage
,它是一个IntPtr
,指向ABS_IMAGE
类型的非托管数据。 但是,如果查看本机代码,则会看到ABS_VARLEN
等于1
。 这是因为必须在编译时静态定义struct
。 实际上,像素数据的长度由高度,宽度和颜色计数字段确定。
您可以继续使用Marshal.PtrToStructure
来获取大多数字段。 但是你无法以这种方式获得ImageData
字段。 这需要更多的工作。
相反地声明这样的结构:
[StructLayout(LayoutKind.Sequential)]
public struct ABS_IMAGE {
public uint Width;
public uint Height;
public uint ColorCount;
public uint HorizontalDPI;
public uint VerticalDPI;
public byte ImageData;
}
当您需要获取图像数据时,请执行以下操作:
IntPtr ImageData = pImage + Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData");
Marshal.Copy(ImageData, data, 0, length);
如果您尚未使用.net 4,则需要进行转换以进行算术编译:
IntPtr ImageData = (IntPtr) (pImage.ToInt64() +
Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData").ToInt64());
最后,我认为你的计算length
不正确。 当然你需要使用Height*Width
。 你还没有考虑颜色深度。 例如,32位颜色将是每像素4个字节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.