[英]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.