Снимок экрана C ++ - как читать растровое изображение? - PullRequest
0 голосов
/ 16 мая 2018

Я хотел, чтобы программа (написанная на с ++) считывала пиксели с экрана, но получаемый ответ кажется беспорядочным, переменная start указывает положение мыши. Как правильно это сделать? Я использовал GetPixel () , который работал нормально, но мне нужна целая битовая карта для эффективности. Вот код:

#include <Windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;

int nScreenWidth;
int nScreenHeight;

HBITMAP GetScreenBmp(HDC hdc) {
    HDC hCaptureDC  = CreateCompatibleDC(hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap);
    BOOL bOK = BitBlt(hCaptureDC,0,0,nScreenWidth, nScreenHeight, hdc,0,0,SRCCOPY|CAPTUREBLT);

    SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
    DeleteDC(hCaptureDC);
    return hBitmap;
}

int main() {
    nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    HBITMAP hBitmap;

    int times = 0;
    while (!GetAsyncKeyState(VK_SPACE) && times<1000)
    {
        times++;

        POINT p;
        GetCursorPos(&p);

        HDC hdc = GetDC(0);

        hBitmap = GetScreenBmp(hdc);

        BITMAPINFO MyBMInfo = {0};
        MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

        if(0 == GetDIBits(hdc, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
            cout << "error" << endl;
        }

        BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

        MyBMInfo.bmiHeader.biCompression = BI_RGB;

        if(0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
            cout << "error2" << endl;
        }
        //**HERE** - position is wrong?
        int start = (p.y*nScreenWidth+p.x)*4;
        for(int i = start; i < start + 4; i+=4)
        {
            cout << "R:" << (int)lpPixels[i+2] << " G:" << (int)lpPixels[i+1] << " B:" << (int)lpPixels[i] << endl;
        }

        ReleaseDC(NULL, hdc);
        delete[] lpPixels;

        Sleep(1000);
    }
    DeleteObject(hBitmap);

    return 0;
}

1 Ответ

0 голосов
/ 16 мая 2018

Вы устанавливаете сжатие на BI_RGB, вы также можете установить первые 6 значений и вызывать GetDIBits только один раз.А поскольку высота растрового изображения начинается снизу вверх, вы должны указать отрицательную высоту для BITMAPINFOHEADER, в противном случае считайте снизу вверх.

Убедитесь, что процесс поддерживает DPI.Самый простой способ (но не предпочтительный способ) - позвонить SetProcessDPIAware().За каждое hBitmap выделение звонка DeleteObject(hBitmap)

int main()
{
    SetProcessDPIAware();
    int width = GetSystemMetrics(SM_CXSCREEN);
    int height = GetSystemMetrics(SM_CYSCREEN);
    while(!GetAsyncKeyState(VK_SPACE))
    {
        HDC hdc = GetDC(0);
        POINT p;
        GetCursorPos(&p);

        HDC memdc = CreateCompatibleDC(hdc);
        HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width, height);
        HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
        BitBlt(memdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY | CAPTUREBLT);
        SelectObject(memdc, oldbmp);
        DeleteDC(memdc);

        //use GetPixel for testing
        COLORREF c = GetPixel(hdc, p.x, p.y);
        printf("%02X%02X%02X\n", GetRValue(c), GetGValue(c), GetBValue(c));

        BITMAPINFO bi = { 0 };
        bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
        bi.bmiHeader.biWidth = width;
        bi.bmiHeader.biHeight = -height;
        bi.bmiHeader.biBitCount = 32; //32-bit bitmap
        bi.bmiHeader.biPlanes = 1;
        bi.bmiHeader.biCompression = BI_RGB;

        //allocate 4 bytes per pixel for 32-bit
        BYTE* lpPixels = new BYTE[height * width * 4]; 
        if(0 != GetDIBits(hdc, hbitmap, 0, height, lpPixels,
            &bi, DIB_RGB_COLORS))
        {
            int i = (p.y * width + p.x) * 4;
            printf("%02X%02X%02X\n\n", 
                        lpPixels[i + 2], lpPixels[i + 1], lpPixels[i + 0]);
        }
        DeleteObject(hbitmap);
        ReleaseDC(NULL, hdc);
        delete[] lpPixels;
        Sleep(1000);
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...