Load an HBITMAP into SFML sf::Image container





5.00/5 (1 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).