C#기준, Image RawData를 가져오기.... 그리고, C++ DLL을 사용하다보면,
구조체 포인터형으로 결과를 얻어오거나 하는 경우... 난감할 때가 있습니다.
언어가 다르다보니,
아무래도 api guide 문서의 함수 선언, 정의 등을 보아도 Exception 난리가 날 경우가 있는데
어떻게 다뤄야 하는지 나에 의해.. 나를 위한.. 내가 나중에 보려고 메모를 해둔다...
난 맨날 까먹으니깐...
일단 먼저... 이미지를 가지고 뭔가를 할 때,
이미지의 RawData까지 직접 추출해서 사용해야되는 경우가 있습니다.
뭐 이미지의 Buffer 라고 애기하기도 하는데..
사실 Core쪽이 아닌 이상, 이미지 파일의 byte stream정도로 생각할 수 있는데
그게 아니고, 순수 이미지에 body 정도만 가져온다라고 생각하면 될 것 같아요...
다른 이미지 포맷은 모르겠고.. bitmap으로 해봤다..
using을 쓴다면, 이정도 추가하면 되지 않을까 싶음
//System.Drawing
//System.Drawing.Imaging
public static byte[] GetBitmapData(string imagePath)
{
using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(imagePath))
{
// 비트맵 이미지의 너비와 높이 구하기
int width = bitmap.Width;
int height = bitmap.Height;
// 이미지 데이터를 저장할 바이트 배열 생성
int bytesPerPixel = System.Drawing.Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;
int stride = width * bytesPerPixel;
byte[] imageData = new byte[stride * height];
// 비트맵 데이터 가져오기
System.Drawing.Imaging.BitmapData bitmapData =
bitmap.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);
try
{
IntPtr ptr = bitmapData.Scan0;
Marshal.Copy(ptr, imageData, 0, imageData.Length);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
return imageData;
}
}
이렇게 하면, byte[] array 형식으로 이미지의 RawData를 뽑아오게 됩니다.
그건 그렇고, C++ DLL을 쓰다보면, 아까 말한대로 마샬링이 필요할 때가 있는데...
C++에서 아래처럼 *result 를 파라미터로 가져가라는 함수가 있다면..
EXTERN_FUNCTION(void) TestAPI(result* pResult);
C#에서 어떻게 이걸 선언해놔야 쓸 수 있는건가... 젠장..
C++ 에서는 아래처럼 정의가 되어있다고 치자.
//result라는 놈은 아래와 같고....
typedef struct result
{
item itemInfo[5];
} result;
//item이라는 놈은 또 아래와 같고..
typedef struct item
{
wchar_t* strxxx;
Rect region;
int bExist;
int isValid;
} item;
//Rect는 아래와 같다고 치자...
typedef struct Rect
{
int left;
int top;
int right;
int bottom;
} Rect;
C# 에서 EXTERN_FUNCTION(void) TestAPI(result* pResult); 이건 어떻게 선언해놔야 될까..
[DllImport(DLL_PATH)]
public static extern void TestAPI( ??? );
대충 이럴 것 같은데....
이런저런 시도 끝에... 답이 맞는진 모르겠지만,,,
우선 위에 관련있는 C++에서 사용된 저 구조체 타입들을 아래처럼 정의했다.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct clsResult
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public clsItem[] itemInfo;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct clsItem
{
public IntPtr strxxx;
public Rect region;
public int bExist;
public int isValid;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
그리고.. 선언부는 아래처럼 했다.
[DllImport(DLL_PATH)]
public static extern void TestAPI(ref clsResult result);
드뎌 된다.... ㅠ^ㅠ 흐엉
아? public IntPtr strxxx; 이런거를 string으로 뽑아낼 때엔....
아래글을 참고...
2023.07.17 - [I.T/Programming] - [C#] Intptr to String, PtrToString, 마샬링 Use C++ parameter in C#
'I.T > Programming' 카테고리의 다른 글
[C#] RGB Color to Int, 칼라 변환 (0) | 2024.11.13 |
---|---|
[C#] Intptr to String, PtrToString, 마샬링 Use C++ parameter in C# (0) | 2023.07.17 |
[C#] 클래스가 등록되지 않았습니다. HRESULT 0x80040154 (REGDB_E_CLASSNOTREG) exe 실행 안됨 (0) | 2022.08.25 |
[C#] cmd창 안보이게, hidden 처리 (0) | 2022.07.15 |
[C#] Ldap Server User 인증하기 (0) | 2016.11.10 |