C++中扫描内存位图特定RGB像素并获取坐标的问题
Hey there! Let's figure out why your red=60 pixel search is returning wonky results. Based on what you've shared, these are the most common pitfalls and fixes to get accurate x/y coordinates:
1. You're Using RGB Order Instead of BGR
Windows GDI bitmaps store pixel data in BGR order (blue first, green middle, red last) by default—this is a super easy mistake to make! If you're checking the first byte of a pixel as red, you're actually looking at blue. Here's how to correctly extract the red channel:
// Assuming you have a pointer to your bitmap's raw bits (BYTE* pBits) // And you've calculated the correct pitch (stride) of the bitmap int pixelOffset = (y * pitch) + (x * 3); // For 24-bit color (3 bytes per pixel) BYTE blue = pBits[pixelOffset]; BYTE green = pBits[pixelOffset + 1]; BYTE red = pBits[pixelOffset + 2]; // This is the actual red value! if (red == 60) { // Found your target pixel—return x and y here return true; }
2. Ignoring Bitmap Pitch/Stride Alignment
Bitmap rows are padded to the nearest 4-byte boundary by Windows, so the pitch (stride) isn't just width * 3 for 24-bit images. If you skip this alignment, you'll read off-byte data and get incorrect color values. Here's how to calculate the correct pitch:
BITMAPINFO bmi = {0}; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = w; bmi.bmiHeader.biHeight = h; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; // 24-bit color (no alpha) bmi.bmiHeader.biCompression = BI_RGB; // Calculate aligned pitch int pitch = (w * 3 + 3) & ~3; // Rounds up to next multiple of 4 int bitmapSize = pitch * h; BYTE* pBits = new BYTE[bitmapSize]; // Extract bits from your captured bitmap GetDIBits(hdcSource, hBitmap, 0, h, pBits, &bmi, DIB_RGB_COLORS);
3. Misaligned Capture Coordinates
Double-check that the x,y,w,h parameters you're passing to findColor are relative to the window's client area (not screen coordinates). If you're using screen coordinates, convert them with ScreenToClient:
POINT screenPos = {x, y}; ScreenToClient(window, &screenPos); // Use screenPos.x and screenPos.y for your BitBlt or GetDIBits call
4. Incomplete Bitmap Capture Cleanup
If you don't properly select the original bitmap back into the memory DC before cleaning up, you might corrupt your bitmap data. Make sure your capture code follows this flow:
HWND window = FindWindowA(NULL, "windownamehere"); HDC hdcWindow = GetDC(window); HDC hdcMem = CreateCompatibleDC(hdcWindow); HBITMAP hBitmap = CreateCompatibleBitmap(hdcWindow, w, h); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap); // Copy window content to memory DC BitBlt(hdcMem, 0, 0, w, h, hdcWindow, x, y, SRCCOPY); // Extract bits and search for color here... // Critical cleanup steps SelectObject(hdcMem, hOldBitmap); // Re-select original bitmap DeleteDC(hdcMem); ReleaseDC(window, hdcWindow); DeleteObject(hBitmap);
Putting it all together, your corrected findColor function should account for BGR order, aligned pitch, and proper coordinate handling. That should fix those unexpected results!
内容的提问来源于stack exchange,提问作者Billy Penley

