How to get the colored pixels on a bitmap loaded by a hdc?

270 Views Asked by At

I followed a tutorial to get a window on a HDC. I converted it to a bitmap to search a specific pixel. Normally this is faster than searching directly on a hdc. So I did it but when I loop to look the pixels it returns me 0 or 4294967295. I searched for this problem a long time but I can't find a solution.. I hope you can help me!

Here is my code:

void getPixel(HWND& _window) {
    
    COLORREF color;
    RECT rect;
    GetWindowRect(_window, &rect);
    HDC hdc = GetDC(_window);

    HDC hMemoryDC = CreateCompatibleDC(hdc);
    HBITMAP hbitmap = CreateCompatibleBitmap(hMemoryDC, rect.right - rect.left, rect.bottom - rect.top);
    HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hbitmap));
    
    BitBlt(hMemoryDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hdc, rect.left, rect.top, SRCCOPY);
    

    for (int i = 0; i < 2000; i++) {
        for (int j = 0; j < 2000; j++) {
            color = GetPixel(hMemoryDC, i, j);
            std::cout << "color = " << color << " " << GetRValue(color) << " " << GetGValue(color) << " " << GetBValue(color) << std::endl;
        }
    }
    

    ReleaseDC(_window, hdc);
    DeleteDC(hMemoryDC);
    DeleteObject(hbitmap);
    DeleteObject(hOldBitmap);
}

HWND _window returns me the correct window, I can print it with "PrintWindow" function and it works, so the problem is not there.

I put 2000 in the for loop but even with rect.right - rect.left and rect.bottom - rect.top it doesn't work. I tried to change this function: BitBlt(hMemoryDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hdc, 0, 0, SRCCOPY); or: BitBlt(hMemoryDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdc, 0, 0, SRCCOPY);

I tried also to change GetDC(_window) to GetDC(NULL) but nothing works..

Hope you can help me! Thanks!

1

There are 1 best solutions below

2
Remy Lebeau On

4294967295 (hex 0xFFFFFFFF) is CLR_INVALID, which means you are accessing invalid pixels. You should be using the window's actual width/height dimensions in your loop.

But also, you are retrieving, and copying pixels from, the window's HDC, but you are using the window's screen coordinates in the x1/y1 parameters of BitBlt(). Those parameters should be 0/0 instead, respectively, since the HDC represents just the window and not the whole screen.

Try this instead:

void getPixel(HWND hwnd) {
    
    RECT rect;
    GetWindowRect(hwnd, &rect);
    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    HDC hDC = GetDC(hwnd);
    HDC hMemoryDC = CreateCompatibleDC(hDC);
    HBITMAP hMemoryBmp = CreateCompatibleBitmap(hMemoryDC, width, height);
    HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hMemoryBmp));
    
    BitBlt(hMemoryDC, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
    
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            COLORREF color = GetPixel(hMemoryDC, i, j);
            std::cout << "color = " << color << " " << GetRValue(color) << " " << GetGValue(color) << " " << GetBValue(color) << std::endl;
        }
    }
    
    SelectObject(hMemoryDC, hOldBitmap);
    DeleteObject(hMemoryBmp);
    DeleteDC(hMemoryDC);
    ReleaseDC(hwnd, hDC);
}