GetPixel is WAY too slow

GetPixel is WAY too slow

本文关键字:slow too WAY is GetPixel      更新时间:2023-10-16

我有一堆正方形,每个正方形都有一个我需要识别的特定标识/符号。到目前为止,我有这样的代码:

#include <iostream>
#include <windows.h>
using namespace std;
int main() {
    HDC dc = GetDC(0);
    COLORREF color;
    int sum, x, y;
    while (true) {
        sum = 0;
        Sleep(100);
        for (x = 512; x < 521; x++) {
            for (y = 550; y < 565; y++) {
                color = GetPixel(dc, x, y);
                sum = GetRValue(color) + GetBValue(color) + GetGValue(color);
            }
        }
        cout << "SUM: " << sum << endl;
    }
    return 0;
}

显然它目前只扫描了一个块。问题是,即使只有100多像素,也要花很长时间。我甚至无法想象会发生什么。每次重复要花一秒钟多一点,也许两秒钟。我能做什么?一定有更快的方法。如果我不能查询单个像素,是否有办法获得屏幕的一个区域?

Jonathan在问题中评论说要使用DIB,但是没有答案说明如何使用。为了完整起见,下面是先生B的代码:

COLORREF getcolor(POINT pt) {
    HDC hDc = GetDC(0);
    HDC hDcmem = CreateCompatibleDC(0);
    HBITMAP hBmp = CreateCompatibleBitmap(hDc, 1, 1);
    SelectObject(hDcmem, hBmp);
    BitBlt(hDcmem, 0, 0, 1, 1, hDc, pt.x, pt.y, SRCCOPY);
    LPBITMAPINFO lpbmi = new BITMAPINFO;
    lpbmi->bmiHeader.biBitCount = 24;
    lpbmi->bmiHeader.biCompression = BI_RGB;
    lpbmi->bmiHeader.biPlanes = 1;
    lpbmi->bmiHeader.biHeight = 1;
    lpbmi->bmiHeader.biWidth = 1;
    lpbmi->bmiHeader.biSize = sizeof(BITMAPINFO);
    BYTE lpvBits[4];
    GetDIBits(hDcmem, hBmp, 0, 1, lpvBits, lpbmi, DIB_RGB_COLORS);
    COLORREF currColor = RGB(lpvBits[2], lpvBits[1], lpvBits[0]);
    delete lpbmi;
    DeleteObject(hBmp);
    DeleteDC(hDcmem);
    ReleaseDC(0, hDc);
    return currColor;
}

正如Ben在评论中指出的那样,这仍然非常慢,解决方案是使用这些构建块一次复制整个区域。你的代码会变成这样:

#include <iostream>
#include <vector>
#include <windows.h>
int main() {
    int const startX = 512;
    int const endX = 521;
    int const startX = 550;
    int const endY = 565;
    int const width = endX - startX;
    int const height = endY - startY;
    HDC const hDc = GetDC(0);
    HDC const hDcmem = CreateCompatibleDC(0);
    HBITMAP const hBmp = CreateCompatibleBitmap(hDc, width, height);
    auto const oldBmp = SelectObject(hDcmem, hBmp);
    BITMAPINFO bmi{};
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biHeight = height;
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
    std::vector<RGBQUAD> pixels(height * width);
    while (true) {
        Sleep(100);
        BitBlt(hDcmem, 0, 0, width, height, hDc, startX, startY, SRCCOPY);
        GetDIBits(hDcmem, hBmp, 0, height, &pixels[0], &bmi, DIB_RGB_COLORS);
        int sum = 0;
        for (int i = 0; i < height * width; ++i) {
            sum = pixels[i].R + pixels[i].G + pixels[i].B;
        }
        std::cout << "SUM: " << sum << std::endl;
    }
    SelectObject(hDcmem, oldBmp);
    DeleteObject(hBmp);
    DeleteDC(hDcmem);
    ReleaseDC(0, hDc);
    return 0;
}