반응형

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#

반응형
Posted by Rainfly
l