This is what happens. Your structure is the so-called variable-length structure. Pixel data is contained within a row in the structure, starting from offset to 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
Your API returns pImage
, which is an IntPtr
that points to unmanaged data of type ABS_IMAGE
. However, if you look at the native code, you will see that ABS_VARLEN
is 1
. This is because struct
must be defined statically at compile time. In fact, the pixel data will have a length determined by height, width, and color.
You can continue to use Marshal.PtrToStructure
to get most of the fields. But you cannot get into the ImageData
field this way. This will require a little more work.
Instead, declare the structure as follows:
[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; }
When you need to get image data, follow these steps:
IntPtr ImageData = pImage + Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData"); Marshal.Copy(ImageData, data, 0, length);
If you have not yet entered .net 4, you need to perform a casting to compile arithmetic:
IntPtr ImageData = (IntPtr) (pImage.ToInt64() + Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData").ToInt64());
Finally, I think that you are not calculating length
correctly. Of course you need to use Height*Width
. Also, you did not specify the color depth. For example, a 32-bit color would be 4 bytes per pixel.