C++ Getting RGB from hBitmap

前端 未结 2 1964
野趣味
野趣味 2021-02-06 07:27

Working with bitmaps is very new to me so I\'ve been really struggling with the online tutorials and strategies that I\'ve read through. Basically my goal is to scan the screen

相关标签:
2条回答
  • 2021-02-06 07:56

    Your image size is specified in pixels, it should be specified in bytes

    **bmi.biSizeImage = ScreenX * ScreenY;**
    **bmi.biBitCount = 24;**
    bmi.biWidth = ScreenX;
    bmi.biHeight = -ScreenY;
    **bmi.biCompression = BI_RGB;**
    

    biSizeImage its defined units are bytes and you are specifying RGB 3 bytes per pixel.

    http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx

    biSizeImage The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.

    0 讨论(0)
  • 2021-02-06 08:13

    The issue is that your screen is actually 32bits deep not 24. The code below will give you the result you need:

    /* Globals */
    int ScreenX = 0;
    int ScreenY = 0;
    BYTE* ScreenData = 0;
    
    void ScreenCap() 
    {
        HDC hScreen = GetDC(NULL);
        ScreenX = GetDeviceCaps(hScreen, HORZRES);
        ScreenY = GetDeviceCaps(hScreen, VERTRES);
    
        HDC hdcMem = CreateCompatibleDC(hScreen);
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, ScreenX, ScreenY);
        HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);
        BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hScreen, 0, 0, SRCCOPY);
        SelectObject(hdcMem, hOld);
    
        BITMAPINFOHEADER bmi = {0};
        bmi.biSize = sizeof(BITMAPINFOHEADER);
        bmi.biPlanes = 1;
        bmi.biBitCount = 32;
        bmi.biWidth = ScreenX;
        bmi.biHeight = -ScreenY;
        bmi.biCompression = BI_RGB;
        bmi.biSizeImage = 0;// 3 * ScreenX * ScreenY;
    
        if(ScreenData)
            free(ScreenData);
        ScreenData = (BYTE*)malloc(4 * ScreenX * ScreenY);
    
        GetDIBits(hdcMem, hBitmap, 0, ScreenY, ScreenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
    
        ReleaseDC(GetDesktopWindow(),hScreen);
        DeleteDC(hdcMem);
        DeleteObject(hBitmap);
    }
    
    inline int PosB(int x, int y) 
    {
        return ScreenData[4*((y*ScreenX)+x)];
    }
    
    inline int PosG(int x, int y) 
    {
        return ScreenData[4*((y*ScreenX)+x)+1];
    }
    
    inline int PosR(int x, int y) 
    {
        return ScreenData[4*((y*ScreenX)+x)+2];
    }
    
    bool ButtonPress(int Key)
    {
        bool button_pressed = false;
    
        while(GetAsyncKeyState(Key))
            button_pressed = true;
    
        return button_pressed;
    }
    
    int main() 
    {
        while (true) 
        {
           if (ButtonPress(VK_SPACE))
           {  
    
              // Print out current cursor position
              POINT p;
              GetCursorPos(&p);
              printf("X:%d Y:%d \n",p.x,p.y);
              // Print out RGB value at that position
              std::cout << "Bitmap: r: " << PosR(p.x, p.y) << " g: " << PosG(p.x, p.y) << " b: " << PosB(p.x, p.y) << "\n";
    
           } else if (ButtonPress(VK_ESCAPE))
           {
              printf("Quit\n");
              break;
           } else if (ButtonPress(VK_SHIFT))
           {
              ScreenCap();
              printf("Captured\n");
           }
        }
    
        system("PAUSE");
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题