3

I'm trying to get the pixels of a bitmap using the GetDIBits function. As I have not studied the Windows GDI/API, I'm very unsure about the first argument, HDC. I've searched countless posts here on SO and the web but have been unable to find information or example about how to initialize HDC in this specific case. Here's how far I've gone reading pixel values:

    HBITMAP hBitmap = (HBITMAP) LoadImage(0, L"C:/tmp/Foo.bmp" ,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    // check hBitmap for error

    BITMAP bm;
    ::GetObject( hBitmap , sizeof(bm) , &bm );

    // TODO: GetDIBits()


Solution:

After scouring the web some more I've been able to cobble together the following:

    /* Omitting error checks for brevity */
    HDC dcBitmap = CreateCompatibleDC ( NULL );
    SelectObject( dcBitmap, hBitmap );

    BITMAPINFO bmpInfo;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = bm.bmWidth;
    bmpInfo.bmiHeader.biHeight = -bm.bmHeight;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 24;
    bmpInfo.bmiHeader.biCompression = BI_RGB;        
    bmpInfo.bmiHeader.biSizeImage = 0;        

    COLORREF* pixel = new COLORREF [ bm.bmWidth * bm.bmHeight ];
    GetDIBits( dcBitmap , hBitmap , 0 , bm.bmHeight , pixel , &bmpInfo , DIB_RGB_COLORS );
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Olumide
  • 5,397
  • 10
  • 55
  • 104
  • I'm not sure I understand what the question is. The first parameter (`hdc`) is a *device context*. You get one of those when you handle a `WM_PAINT` event, when you call the [`GetDC` function](http://msdn.microsoft.com/en-us/library/dd144871.aspx), or do a host of other GDI-related activities. The function takes [any] one of those. – Cody Gray - on strike Dec 28 '11 at 14:52
  • Well, it depends on what you want to do with the bitmap. Still, having palettized bitmaps or video adapter modes only mattered in the previous century. GetDesktopWindow + GetWindowDC will work just fine if you don't have your own window. Consider GDI+ and Bitmap::LockBits() instead. – Hans Passant Dec 28 '11 at 15:08
  • @CodyGray I am not handling events, neither do I have a window. I am writing a console application and all I want to open a file and read the pixel values. I am at a loss of which HDC to use and I do not wish to guess. – Olumide Dec 28 '11 at 15:14
  • 2
    The hdc is the target where you intend to display the bitmap. This is important if the bitmap says "You know what? Instead of giving you RGB values, [I'm just going to give you indices into my target device's color table, and you can get the RGB values from there](http://msdn.microsoft.com/en-us/library/ms969897.aspx)." `LoadImage` also uses it to decide the color format for the bitmap. If you pass a 24bpp device context, then you will get a 24bpp bitmap. – Raymond Chen Dec 28 '11 at 15:52
  • 1
    @RaymondChen I'm confused. AS afar as I can see, ` LoadImage ` does not accept an HDC. – Olumide Dec 28 '11 at 16:21
  • Oops, you're right. I got it confused with `CreateDIBitmap`. Since your original message asked where to get a HDC from and the only call was `LoadBitmap`, I assumed it was the `LoadBitmap` that needed the HDC. – Raymond Chen Dec 28 '11 at 17:02
  • possible duplicate: http://stackoverflow.com/questions/3962237/what-is-the-hdc-for-in-getdibits – Adrian McCarthy Dec 28 '11 at 17:11
  • Note also that you are requesting the bits in 24bpp format, but you're passing an array of COLORREFs, which are 32-bit pixels values. – Raymond Chen Dec 28 '11 at 17:14
  • @RaymondChen I've since fixed that, and I've found the reason for why I was getting `(255,255,255)` values. I wasn't incrementing the pixel index and was thus reading the first pixel over and over again. – Olumide Dec 28 '11 at 17:20

2 Answers2

1

The source bitmap is typically a device-dependent bitmap. Although it's less common nowadays, that might mean that the bitmap's pixel values are stored as indexes into a color table. In those cases GetDIBits would need access to the color table, which is stored in a device context.

If your bitmap uses RGB values instead of indexes, then the device context should be irrelevant, though in my experience you must still provide a valid one (see What is the HDC for in GetDIBits?), perhaps it looks at other aspects of the device context, like the color depth.

Community
  • 1
  • 1
Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
1

Is your goal to get the pixel color values, or to call GetDIBits? If you just want the pixel content, you can use GetObject to get the BITMAP structure corresponding to your HBITMAP handle, the bmBits pointer in that structure gives access to the pixels (note: it will be in the bitmap's original format, which might not be 24bpp, so check the other fields of the structure to see what the format is).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720