使用
GetDIBits
读取32位像素数据,循环遍历位并将 alpha 设置为
0xFF
。
bool Save(CBitmap *bitmap)
{
if(!bitmap)
return false;
BITMAP bm;
bitmap->GetBitmap(&bm);
if(bm.bmBitsPixel < 16)
return false;
DWORD size = bm.bmWidth * bm.bmHeight * 4;
BITMAPINFOHEADER bih = { sizeof(bih), bm.bmWidth, bm.bmHeight, 1, 32, BI_RGB };
BITMAPFILEHEADER bfh = { 'MB', 54 + size, 0, 0, 54 };
CClientDC dc(0);
std::vector<BYTE> vec(size, 0xFF);
int test = GetDIBits(dc, *bitmap, 0, bm.bmHeight, &vec[0],
(BITMAPINFO*)&bih, DIB_RGB_COLORS);
for(DWORD i = 0; i < size; i += 4)
vec[i + 3] = 0xFF;
CFile fout;
if(fout.Open(filename, CFile::modeCreate | CFile::modeWrite))
{
fout.Write(&bfh, sizeof(bfh));
fout.Write(&bih, sizeof(bih));
fout.Write(&vec[0], size);
return true;
}
return false;
}
作为替代方案(但我不确定这是否可靠),使用
0xFF
初始化内存。
GetDIBits
将设置RGB部分,但不会覆盖alpha值:
std::vector<BYTE> vec(size, 0xFF)
GetDIBits...
或使用GDI+。
bool Save(CBitmap *bitmap)
{
if(!bitmap)
return false;
BITMAP bm;
bitmap->GetBitmap(&bm);
if(bm.bmBitsPixel < 16)
return false;
Gdiplus::GdiplusStartupInput tmp;
ULONG_PTR token;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
Gdiplus::Bitmap *src = Gdiplus::Bitmap::FromHBITMAP(*bitmap, NULL);
Gdiplus::Bitmap *dst = src->Clone(0, 0, src->GetWidth(), src->GetHeight(),
PixelFormat32bppARGB);
LPCOLESTR clsid_bmp = L"{557cf400-1a04-11d3-9a73-0000f81ef32e}";
CLSID clsid;
CLSIDFromString(clsid_bmp, &clsid);
bool result = dst->Save(L"file.bmp", &clsid) == 0;
delete src;
delete dst;
Gdiplus::GdiplusShutdown(token);
return result;
}
CImage
只是一个HBITMAP
的包装器,没有任何关于Alpha通道的概念。 - zett42CImage::Save()
源代码,它检查m_bHasAlphaChannel
(这是由您的SetHasAlphaChannel()
调用设置的),并使用PixelFormat32bppARGB
创建GDI+位图。因此,它应该保留您拥有的任何alpha通道数据。在调用您的Save()
函数之前,您只需要设置alpha通道值即可。 - zett42SetHasAlphaChannel
设置一个标志并在最后创建一个32位图像,或者用于带有透明度的绘制,但它不影响可能仍为零的 alpha。 - Barmak Shemirani