GetPixel 太慢了 [英] GetPixel is WAY too slow
问题描述
我有一堆方块,每个方块都有我需要识别的特定身份/符号.到目前为止,我有类似的东西:
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屋!