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