[opencv][C#] Bitmap(C#) to cv::Mat

Bitmap 클래스에는 getHbitmap() 이란 함수가 있다.

반환형은 IntPtr 이며, Bitmap 자체의 포인터를 돌려준다.(복사X)

이를 C++ 측에서 인수로 받아 HBITMAP 으로 형변환을 해준뒤 아래의 함수를 호출하면 된다.

HWND GetHwnd() {
	DWORD pid = GetCurrentProcessId();
	if (pid == 0 || pid == -1)return NULL;
	LPARAM tmp = 0;
	tmp = (LPARAM)pid;
	EnumWindows([](HWND hwnd, LPARAM lparam)->BOOL {
		HANDLE hTarget = NULL;
		DWORD dwID = 0;
		DWORD dwSrcID = (DWORD)(*(DWORD*)lparam);
		GetWindowThreadProcessId(hwnd, &dwID);
		if (dwID == dwSrcID) {
			*((int*)lparam) = *(DWORD*)hwnd;
			*(((int*)lparam) + 1) = 1;
			return FALSE;
		}
		return TRUE;
	}, (LPARAM)&tmp);
	if (((int)(tmp >> 32))) {
		return (HWND)tmp;
	}
	return GetConsoleWindow();
}
cv::Mat HBITMAP2cvMat(HBITMAP hbmp) {
	static HWND hwnd = nullptr;
	if (hwnd == nullptr) {
		hwnd = GetHwnd();
	}
	cv::Mat img;
	HDC hdc = GetDC(hwnd);
	BITMAPINFO bmi;
	BITMAPINFOHEADER* bmih = &(bmi.bmiHeader);
	ZeroMemory(bmih, sizeof(BITMAPINFOHEADER));
	bmih->biSize = sizeof(BITMAPINFOHEADER);
	if (GetDIBits(hdc, hbmp, 0, 0, NULL, &bmi, DIB_RGB_COLORS)) {
		int height = (bmih->biHeight > 0) ? bmih->biHeight : -bmih->biHeight;
		img = cv::Mat(height, bmih->biWidth, CV_8UC3);
		
		bmih->biBitCount = 24;
		bmih->biCompression = BI_RGB;
		GetDIBits(hdc, hbmp, 0, height, img.data, &bmi, DIB_RGB_COLORS);
	}
	ReleaseDC(NULL, hdc);
	cv::flip(img, img, 0);
	return img;
}

HBITMAP을 IplImage로 바꾸는 코드는 아래와 같다.

IplImage* HBMPtoIPL(HBITMAP hbmp) {
	static HWND hwnd = nullptr;
	if (hwnd == nullptr) {
		char pszNewWindowTitle[1024];
		char pszOldWindowTitle[1024];
		GetConsoleTitleA(pszOldWindowTitle, 1024);
		sprintf(pszNewWindowTitle, "%d/%d", GetTickCount(), GetCurrentProcessId());
		SetConsoleTitleA(pszNewWindowTitle);
		while (hwnd == nullptr) {
			hwnd = FindWindowA(NULL, pszNewWindowTitle);
			Sleep(1);
		}
		SetConsoleTitleA(pszOldWindowTitle);
	}
	HDC hdc = GetDC(hwnd);
	IplImage* Image = NULL;
	BITMAPINFO bmi;
	BITMAPINFOHEADER* bmih = &(bmi.bmiHeader);

	ZeroMemory(bmih, sizeof(BITMAPINFOHEADER));
	bmih->biSize = sizeof(BITMAPINFOHEADER);

	if (GetDIBits(hdc, hbmp, 0, 0, NULL, &bmi, DIB_RGB_COLORS)) {
		int height = (bmih->biHeight > 0) ? bmih->biHeight : -bmih->biHeight;
		Image = cvCreateImage(cvSize(bmih->biWidth, height), IPL_DEPTH_8U, 3);
		Image->origin = (bmih->biHeight > 0);
		bmih->biBitCount = 24;
		bmih->biCompression = BI_RGB;
		GetDIBits(hdc, hbmp, 0, height, Image->imageData, &bmi, DIB_RGB_COLORS);
	}

	ReleaseDC(NULL, hdc);
	return Image;
}