从内存缓冲区创建 HBITMAP
我有一个应用程序可以从数据库中加载一些 blob 数据,该数据库可以表示各种位图和图标的 png 格式或原始二进制数据.这被存储在 std::vector
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 in a std::vector<unsigned char>
我正在使用 CImageList
对象在树视图、工具栏图像等中显示各种图像,但问题是从内存中的数据创建位图变得模糊,好像在执行时缺少像素一样类似于以下内容:
I'm using CImageList
objects to display various images in tree views, toolbar images, etc but the problem is creating bitmaps from the data in memory are coming out fuzzy as if it's missing pixels when doing something like below:
std::vector<unsigned char> bits;
HBITMAP hbitmap = CreateBitmap(16, 16, 1, 32, bits.data());
为了暂时解决这个问题,我只是将向量中的 data() 写入临时文件,然后使用 LoadImage 将其读回并从中创建 HBITMAP.这非常有效,但无可否认这是一种无耻的黑客行为,我希望完全没有必要.
To work around this issue for now I am simply writing out the data() in the vector to a temporary file and then using LoadImage to read it back in and creating the HBITMAP from that. This works perfectly however that is admittedly a shameless hack and should be completely unnecessary I would hope.
我在网上环顾四周,但没有找到任何关于如何从内存正确"创建 hbitmap 的真正好的例子.如果可能,我希望能够创建这些位图以添加到图像列表中,而无需任何文件输入/输出和有限数量的数据复制.
I've looked around online but haven't found any really good examples of how to "properly" create hbitmaps from memory. I would like to be able to create these bitmaps to be added to the image list without any file i/o and limited amounts of copying the data around if possible.
寻找执行此操作的最佳方法,显然 Windows 特定代码很好.
Looking for the best way to do this and obviously windows specific code is fine.
更新:
根据 jdv 的回答,我开始使用 CreateCompatibleBitmap、CreateDIBitmap,最后是 CreateDIBSection.所有这些最终都创建了可爱的黑色位图而不是之前的模糊位图,所以我一定又做错了,我的猜测是因为这个位图创建是在一个没有屏幕 dc 或窗口概念的对象中完成的,使用 GetDC(NULL)
和 CreateCompatibleDC(NULL)
不好用.示例代码:
Based on jdv's answer I began playing with CreateCompatibleBitmap, CreateDIBitmap, and finally CreateDIBSection. All of these ended up creating lovely black bitmaps instead of the previous fuzzy bitmaps so I must be doing something wrong again and my guess is since this bitmap creation is being done in an object that has no concept of the screen dc or window that using GetDC(NULL)
and CreateCompatibleDC(NULL)
are no good. Sample code:
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biHeight = 16;
bmi.bmiHeader.biWidth = 16;
bmi.bmiHeader.biPlanes = 1;
HDC dc = CreateCompatibleDC(NULL);
HBITMAP hbitmap = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (void**)blobData.GetMember<FILEDATAFIELD_DATA>().data(), NULL, 0);
我现在当然认为必须有一种更简单的方法来解决这个问题,也许是完全避免使用 HBITMAP 并直接使用 CBitmap
类?当涉及到将图像添加到 CImageList
时,我无论如何都在使用 CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask)
.有谁知道从 std::vector
初始化 CBitmap
对象的简单方法?
I am now of course thinking there has got to be a simpler way to go about this perhaps by avoiding the HBITMAP altogether and working directly with CBitmap
class? When it comes down to adding the image to the CImageList
I'm using CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask)
anyway. Does anyone know a simple way to initialize a CBitmap
object from a std::vector<unsigned char>
?
推荐答案
使用 GdiPlus 我得到了一些效果很好并且不涉及拔牙的东西!
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();
}
根据 Jegatheesh 进行了更改
Changed per Jegatheesh
相关文章