簡體   English   中英

掃描BitMap中的特定像素顏色,並在c ++中給出x,y的位置

[英]Scan BitMap for Specific pixel color, and give x, y location in c++

我只想掃描給定像素給定像素的RGB值的內存中的特定顏色的位圖,如果找到,請給我該像素的x,y線。 我這里有將給定窗口的位圖存儲在內存中的代碼,並且工作正常。 但是,當我嘗試使用紅色值60檢索像素所在的位置時,會得到各種時髦的值。 這是我當前的代碼:

bool findColor(int x, int y, int w, int h, LPCSTR fname) {
HWND window = FindWindow(0, ("windownamehere"));
HDC hdcSource = GetDC(window);
HDC hdcMemory = CreateCompatibleDC(hdcSource);
int capX = GetDeviceCaps(hdcSource, HORZRES);
int capY = GetDeviceCaps(hdcSource, VERTRES);
HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, w, h);
HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
BitBlt(hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY);
SelectObject(hdcMemory, hBitmapOld);
//Added
HDC hdc = GetDC(0);
BITMAPINFO MyBMInfo = { 0 };
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
GetDIBits(hdcMemory, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS);
BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];
MyBMInfo.bmiHeader.biCompression = BI_RGB;
GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS);
BYTE red, blue, green;
char* pCurrPixel = (char*)lpPixels;
for (y = 0; y < h; y++)
{
    for (x = 0; x < w; x++)
    {
        red = pCurrPixel[0];
        green = pCurrPixel[1];
        blue = pCurrPixel[2];
        if ((red == 134))
            std::cout << x << ", " << y;
        pCurrPixel += 4;
    }
}
SelectObject(hdcMemory, hBitmapOld);
DeleteObject(hBitmap);
DeleteDC(hdcSource);
DeleteDC(hdcMemory);
return false;
}

hBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmapOld);

那將覆蓋hBitmap ,您不需要。 您應該將該行更改為:

SelectObject(hdcMemory, hBitmapOld);

然后您可以使用GetDIBits

另外,您已經將位圖復制到內存dc。 您可以使用GetPixel獲取顏色。 無需調用GetDIBits

HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
COLORREF color = GetPixel(hdcMemory, x, y);
BYTE red = GetRValue(color);
BYTE green = GetGValue(color);
BYTE blue = GetBValue(color);
...
SelectObject(hdcMemory, hBitmapOld);
DeleteObject(hBitmap);
DeleteDC(hdcMemory);
RleaseDC(0, hdcSource);

完成后,還請調用DeleteObject(hBitmap)

使用GetDIBits :32位位圖格式是BGRA而不是RGBA,因此第一個字節是藍色,而不是紅色。 在將這些位視為32位位圖之前,應特別請求32位位圖或檢查位計數。

#include <iostream>
#include <vector>
#include <Windows.h>

int main()
{
    HWND target = FindWindow("Notepad", 0);
    if(!target)
    {
        printf("error, no window\n");
        return 0;
    }

    RECT rc;
    GetWindowRect(target, &rc);
    int x = rc.left;
    int y = rc.top;
    int w = rc.right - rc.left;
    int h = rc.bottom - rc.top;

    int screen_w = GetSystemMetrics(SM_CXFULLSCREEN);
    int screen_h = GetSystemMetrics(SM_CYFULLSCREEN);

    HDC hdc = GetDC(HWND_DESKTOP);
    HBITMAP hbitmap = CreateCompatibleBitmap(hdc, screen_w, screen_h);
    HDC memdc = CreateCompatibleDC(hdc);
    HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
    BitBlt(memdc, 0, 0, w, h, hdc, x, y, CAPTUREBLT | SRCCOPY);
    SelectObject(memdc, oldbmp);

    BITMAPINFOHEADER infohdr = { sizeof(infohdr), w, h, 1, 32 };
    int size = w * h * 4;
    std::vector<BYTE> bits(size);
    int res = GetDIBits(hdc, hbitmap, 0, h, &bits[0], 
            (BITMAPINFO*)&infohdr, DIB_RGB_COLORS);
    if(res != h)
    {
        std::cout << "error\n";
        return 0;
    }

    BYTE *ptr = bits.data();
    //for(y = 0; y < h; y++)
    for(y = h - 1; y >= 0; y--) //bitmaps bits start from bottom, not top
    {
        for(x = 0; x < w; x++)
        {
            BYTE blu = ptr[0];
            BYTE grn = ptr[1];
            BYTE red = ptr[2];
            ptr += 4;
        }
    }

    SelectObject(memdc, oldbmp);
    DeleteObject(hbitmap);
    ReleaseDC(HWND_DESKTOP, hdc);
    DeleteDC(memdc);

    return 0;
}

請注意,如果用戶未使用默認DPI設置,則該過程應了解DPI。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM