Our website is made possible by displaying online advertisements to our visitors. Please consider supporting us by whitelisting our website.

Load a HBITMAP into SFML sf::Image container

I have been working on a SFML project for quite some time.
This project are hookup up with existing Win32 coded stuff, so I had to handle HBITMAP.

After hours of searching and trial&error, I got this solution.
The LoadFromMemory-part didn’t work so well, so I decided to get pixels.
It works for me, but should have more checks, use at own risk.


//////////////////////////////////////////////////////////////////////////
// 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;xLoadFromPixels(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;
}

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

Any comments, errors or bad design, please let me know in the comment section!