Click here to Skip to main content
Click here to Skip to main content

Load an HBITMAP into SFML sf::Image container

, 5 Feb 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

//////////////////////////////////////////////////////////////////////////
// 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.

//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).

License

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

Share

About the Author

Lars [Large] Werner
Engineer
Norway Norway
I'm looking for new opportunities in Norway, contact me on email, twitter or Facebook
Not able to travel (a lot) so either home office or in Telemark area, Norway.
 
----------------------------------
Visit http://lars.werner.no/ for my techno-blog!
----------------------------------
 
Projects
* Adito - Simple Windows installer for Adito/OpenVPN ALS!
* Unpacker - Auto extract of multiple archives (RAR/ZIP) with queue support and cleanup options!
* SizeMe - Ultimate tool for maximize your output on CD/DVDs!
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 5 Pingroupevan89714-Jan-13 13:18 
GeneralRe: My vote of 5 PinmemberLars [Large] Werner15-Jan-13 12:17 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141223.1 | Last Updated 5 Feb 2013
Article Copyright 2013 by Lars [Large] Werner
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid