2012-05-25 83 views
4

我使用非託管庫,它生成灰度圖像(大約100x200像素,或多或少)。圖像包含一個結構,它看起來像在C中:使用C#從IntPtr複製字節數組與Marshal.Copy不起作用

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; 
} 

拼搶的形象和marshallign的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

有沒有人有想法?

回答

5

這就是發生了什麼事。你的結構就是所謂的變長結構。像素數據被內嵌在結構中,從偏移量開始到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; 
} 

當你需要得到的圖像數據做到這一點:

​​

如果你還沒有在.NET 4中,那麼你需要鑄造做算術編譯:

IntPtr ImageData = (IntPtr) (pImage.ToInt64() + 
    Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData").ToInt64()); 

最後,我想你是計算length不正確。當然你需要使用Height*Width。你也沒有考慮到顏色深度。例如,32位顏色將是每個像素4個字節。

+1

就是這樣,非常感謝你:) – mrsubwoof

相關問題