GetPixel 太慢了 [英] GetPixel is WAY too slow

查看:72
本文介绍了GetPixel 太慢了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一堆方块,每个方块都有我需要识别的特定身份/符号.到目前为止,我有类似的东西:

I have a bunch of squares and each has a specific identity/symbol I need to identify. So far I have something like:

#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 多个像素,也需要很长时间.我什至无法想象会发生什么.每次重复需要一秒钟,也许两秒钟.我能做什么?必须有一种更快的方法来做到这一点.如果我不能查询单个像素,有没有办法获取屏幕区域?该区域不在我的程序窗口内.

Obviously it only scans one block so far. The problem is somehow even though it's only just over 100 pixels, it takes an INSANELY long time. I can't even imagine what could be going on. It takes well over a second, maybe two seconds, for each repetition. What can I do? There has to be a faster way to do this. If I can't query individual pixels, would there be a way to get a region of the screen? The zone is not inside my program's window.

推荐答案

Jonathan 在问题中评论了如何使用 DIB,但没有答案显示如何使用.为了完整起见,这里是 B 先生的代码:

Jonathan comments in the question to use DIB, but there's no answer showing how. For the sake of completeness, here's Mister B's code:

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 在评论中指出的那样,这仍然很慢,解决方案是使用这些构建块一次复制整个区域.你的代码会变成这样:

This is still very slow as Ben points out in a comment, and the solution is to use these building blocks to copy the entire area at once. Your code would become something like this:

#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;
}

这篇关于GetPixel 太慢了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆