Click here to Skip to main content
15,885,141 members
Articles / Desktop Programming / Win32
Tip/Trick

Load an HBITMAP into SFML sf::Image container

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
5 Feb 2013CPOL 16.3K   1   2
Use the standard GDI API to load an HBITMAP into SFML.

Introduction

A simple function to load a bitmap in Win32 GDI to be used by the Sprite-class for SFML.

Using the code

The code is a simple function that you can copy and paste into your Win32 project:

C++
//////////////////////////////////////////////////////////////////////////
// Function created by: Lars Werner - http://lars.werner.no
//////////////////////////////////////////////////////////////////////////
// Inputs:    [in] HBITMAP hBitmap = A HBITMAP handle
//            [out] sf::Image *pPicture = A image in SFML as pointer
//
//////////////////////////////////////////////////////////////////////////
// Return:    True if loaded, False if not!
//            The pPicture is the variable set and to be used further on
//////////////////////////////////////////////////////////////////////////
// Version: 1.0 = Inital Release
//////////////////////////////////////////////////////////////////////////
bool SFMLLoadHBitmapAsImage(HBITMAP hBitmap, sf::Image *pPicture)
{
    //Create a DC to get hBitmap information
    HDC hDC = GetDC( ::GetDesktopWindow() );
 
    //Create BITMAPINFO variable, set size 
    BITMAPINFO MyBMInfo = {0};
    MyBMInfo.bmiHeader.biSize = sizeof( MyBMInfo.bmiHeader );
 
    //Get the BITMAPINFO structure from the bitmap
    if( 0 == GetDIBits(hDC, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS))
    {
        // error handling
        return false;
    }
 
    //Create the bitmap pixel array each element is [b,g,r]
    BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];
 
    //Setting up the structure of the buffer to be received
     MyBMInfo.bmiHeader.biCompression = BI_RGB;  // No-compression
 
    //Now get the actual data from the picture
    if (0 == GetDIBits(hDC, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS))
    {
        // error handling
        return false;
    }
 
    //Now create an array of SFML pixels we want to fill
    sf::Uint8 *lpPixelWithAlpha = new sf::Uint8[ MyBMInfo.bmiHeader.biSizeImage + 
          (MyBMInfo.bmiHeader.biSizeImage/3)/3 ]; //Add room for alpha
 
    //Loop through each pixel, with steps of four RGBA!
    for(int x=0;x<MyBMInfo.bmiHeader.biSizeImage;x+=4)
    {
        lpPixelWithAlpha[x] = lpPixels[x+2];    //lpPixels = r
        lpPixelWithAlpha[x+1] = lpPixels[x+1];    //lpPixels = g
        lpPixelWithAlpha[x+2] = lpPixels[x];    //lpPixels = b
        lpPixelWithAlpha[x+3] = 255;        //Nada alpha (just to adjust if you like)
    }
 
    //Remove old DIBsection
    delete[] lpPixels;
 
    //Load picture, now with correct pixels and alpha channel
    if( false == pPicture->LoadFromPixels(MyBMInfo.bmiHeader.biWidth, 
                  MyBMInfo.bmiHeader.biHeight, lpPixelWithAlpha))
    {
        // error handling
        return false;
    }
 
    //Remove the pixels with alphachannel
    delete[] lpPixelWithAlpha;
 
    //Release the DC
    ReleaseDC(::GetDesktopWindow(), hDC);
 
    //Notify ok!
    return true;
} 

To use the function in your load-procedure, use it like this. Note that the Screenshot function can be located here.

C++
//Create a container for the picture
sf::Image m_mypicture;
 
//Get a HBITMAP (see function from before)
HBITMAP hBitmap = ScreenShot( http://lars.werner.no/?p=627 <--- function and parameters here );
 
//Run the function
if( false == SFMLLoadHBitmapAsImage(hBitmap, &my_picture) )
{
// error handling
}
 
//Load your image into the sprite
sf::Sprite m_mysprite.SetImage(m_mypicture);
 
//The DIB section begins with the last pixels at the beginning.
//Since SFML have flip-functions I didn't care to fix it :)
m_mysprite.FlipY(true); 

Got any other ways to do this? Please comment. If other formats are needed, an integration with GDI+ could be made, it natively supports PNG, GIF, JPG, etc...

History   

  • v1.0 - First release (and probably the only release).
This article was originally posted at http://lars.werner.no?p=633

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer A/S Norske Shell (Dutch Shell)
Norway Norway
----------------------------------
Visit http://lars.werner.no/ for my blog!
----------------------------------
Retired programmer, Norway never had the jobs I wanted Smile | :)

Comments and Discussions

 
GeneralMy vote of 5 Pin
evan89714-Jan-13 12:18
evan89714-Jan-13 12:18 
GeneralRe: My vote of 5 Pin
Lars [Large] Werner15-Jan-13 11:17
professionalLars [Large] Werner15-Jan-13 11:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.