I have an application which loads some blob data out of a database which can represent png formatted or raw binary data for various bitmaps and icons. This is being stored
I'd use CreateCompatibleBitmap, and then call SetDIBits to fill it with your data. These are functions I have seen to work, and SetDIBits is quite flexible, although verbose.
In my MFC years, CreateBitmap was avoided due to suspected performance issues.
A slight variation on the answer provided by AJG85, that employs SHCreateMemStream in place of CreateStreamOnHGlobal. SHCreateMemStream was introduced as a public API in Windows Vista, and provides the benefit of creating an IStream over an existing region in memory, thus avoiding an additional memory allocation:
#include <Shlwapi.h>
#include <atlimage.h>
#include <comdef.h>
#include <comip.h>
#include <vector>
#pragma comment(lib, "Shlwapi.lib")
#if defined(_DEBUG)
# pragma comment(lib, "comsuppwd.lib")
#else
# pragma comment(lib, "comsuppw.lib")
#endif
HBITMAP from_data(std::vector<unsigned char> const& data)
{
if (data.empty())
{
_com_issue_error(E_INVALIDARG);
}
auto const stream { ::SHCreateMemStream(&data[0], static_cast<UINT>(data.size())) };
if (!stream)
{
_com_issue_error(E_OUTOFMEMORY);
}
_COM_SMARTPTR_TYPEDEF(IStream, __uuidof(IStream));
IStreamPtr sp_stream { stream, false };
CImage img {};
_com_util::CheckError(img.Load(sp_stream));
return img.Detach();
}
This implementation either throws a _com_error, or returns an HBITMAP that refers to the image constructed from the in-memory data.
When the function returns, the memory buffer can be safely freed. The returned HBITMAP is owned by the caller, and needs to be released with a call to DeleteObject.
Using GdiPlus I got something that works pretty well and doesn't involve pulling any teeth!
Gdiplus::Bitmap* pBitmap = NULL;
IStream* pStream = NULL;
HRESULT hResult = ::CreateStreamOnHGlobal( NULL, TRUE, &pStream );
if(hResult == S_OK && pStream)
{
hResult = pStream->Write(&bits[0], ULONG(bits.size()), NULL);
if(hResult == S_OK)
pBitmap = Gdiplus::Bitmap::FromStream(pStream);
pStream->Release();
}
Edit: Changed per Jegatheesh