1

I'm trying to take an 100 by 100 square screenshot of the upper left of my screen and then print all the pixel color hexadecimal values to the console. Right now it is just printing blank spaces.

Here's my code:

#include <wingdi.h>
#include <windows.h>
#include <iostream>

using namespace std;

int main(){

    HWND desktop = GetDesktopWindow();
    HDC desktopHdc = GetDC(desktop);
        HDC hdc = CreateCompatibleDC(desktopHdc);
      HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hdc, 100, 100);
        SelectObject(hdc, hCaptureBitmap);


    BITMAPINFO bmi = {0};
    bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
    bmi.bmiHeader.biWidth = 100;
    bmi.bmiHeader.biHeight = 100;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;


RGBQUAD *pPixels = new RGBQUAD[100 * 100];

            BitBlt(hdc, 0, 0, 100, 100, desktopHdc, 0, 0, SRCCOPY);

            GetDIBits(hdc, hCaptureBitmap, 0, 100, pPixels, &bmi, DIB_RGB_COLORS);

            

                for (int i = 0; i < 10000; i++){

                      cout << static_cast<unsigned int>(pPixels[i].rgbRed) << static_cast<unsigned int>(pPixels[i].rgbGreen) << static_cast<unsigned int>(pPixels[i].rgbBlue) << "\n";

                }


}

P.S. I'm pretty sure I'm supposed to use 'BitBLT' to get a square of pixels, but was confused on how to use that function, so any tips on that would be great too.

Thanks!

NO_GUI
  • 444
  • 8
  • 12
  • The members of `RGBQUAD` are `unsigned char` which `cout` will try to print as a character by default. If you cast them to `unsigned int` (e.g. `cout << static_cast(pPixels[i].rgbRed)` then you'll see something. But you'll also just see zeroes because you're not actually blitting from the screen into `hCaptureBitmap`. As you suggested, you can use `BitBlt` for that. – Jonathan Potter Aug 01 '20 at 20:47
  • Does this help? [c/c++ assign RGBQUAD array to a bitmap](https://stackoverflow.com/questions/17271944/c-c-assign-rgbquad-array-to-a-bitmap) – Thomas Matthews Aug 01 '20 at 20:49
  • @JonathanPotter Ok thank you, I'll try that! – NO_GUI Aug 01 '20 at 20:50
  • 1
    I recommend printing as a *hex dump*. If you feel adventurous, you can annotate as well. – Thomas Matthews Aug 01 '20 at 20:50
  • @ThomasMatthews Oh!, what's the syntax for a hex dump? – NO_GUI Aug 01 '20 at 20:51
  • See the `ios::hex` print modifier. Also `width`. The big item is that you need to cast as an integer before printing; otherwise you'll get weird characters printed. – Thomas Matthews Aug 01 '20 at 20:52
  • @JonathanPotter I edited my code to use a BitBLT and cast the output as integers and it prints all zeros, is BitBLT Done right? – NO_GUI Aug 01 '20 at 20:57
  • You have to do the blit before `GetDIBits`, not after. – Jonathan Potter Aug 01 '20 at 20:58
  • Oh whoops, thanks for the tip! – NO_GUI Aug 01 '20 at 21:00
  • @JonathanPotter Hmm i switched the order and it's still giving me zero's. Maybe I used BitBLT wrong? – NO_GUI Aug 01 '20 at 21:04

1 Answers1

1

Here's a helpful function:

void Print_RGBQUAD(const RGBQUAD& r)
{
    std::cout << " " << setw(2) << hex << (unsigned int)(r.rgbRed);
    std::cout << " " << setw(2) << hex << (unsigned int)(r.rgbGreen);
    std::cout << " " << setw(2) << hex << (unsigned int)(r.rgbBlue);
    std::cout << "    ";
}

This example shows one fundamental method for printing an RGBQUAD structure.
The order is changed to RGB. The structure, defined by Microsoft Docs, is:

typedef struct tagRGBQUAD {
  BYTE rgbBlue;
  BYTE rgbGreen;
  BYTE rgbRed;
  BYTE rgbReserved;
} RGBQUAD;
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154