Creating HBITMAP from memory buffer

后端 未结 3 1655
青春惊慌失措
青春惊慌失措 2020-11-30 15:21

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

相关标签:
3条回答
  • 2020-11-30 15:32

    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.

    0 讨论(0)
  • 2020-11-30 15:35

    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.

    0 讨论(0)
  • 2020-11-30 15:37

    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

    0 讨论(0)
提交回复
热议问题