将Alpha通道添加到位图或将位图转换为32位
Adding Alpha channel to bitmap or converting bitmap to 32bit
已解决:当前代码示例:
HBITMAP TwoBitmap(HDC &hdc, RECT &rc)
{
HDC hdcmem = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, rc.right-rc.left, rc.bottom-rc.top);
SelectObject(hdcmem, hbitmap);
HBRUSH hBrush = GetSysColorBrush(2);
FillRect(hdcmem, &rc, hBrush);
DeleteObject((HBRUSH)hBrush);
DeleteDC(hdcmem);
return hbitmap;
}
void CreateTransparentBitmap(HBITMAP &hBitmap)
{
BITMAP TemporaryBitmap;
GetObject(hBitmap, sizeof(BITMAP), &TemporaryBitmap);
HDC MemoryDC = CreateCompatibleDC(NULL);
BITMAPINFO BitmapInfo;
ZeroMemory(&BitmapInfo,sizeof(BITMAPINFO));
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = TemporaryBitmap.bmWidth;
BitmapInfo.bmiHeader.biHeight = TemporaryBitmap.bmHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
RGBQUAD* pArgb = NULL;
HBITMAP hTemporaryBitmap = CreateDIBSection(MemoryDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pArgb, NULL, 0);
GetDIBits(MemoryDC, hBitmap, 0, BitmapInfo.bmiHeader.biHeight, pArgb, &BitmapInfo, DIB_RGB_COLORS);
for (int i = 0; i < BitmapInfo.bmiHeader.biWidth * BitmapInfo.bmiHeader.biHeight; i++)
pArgb[i].rgbReserved = 255;
DeleteDC(MemoryDC);
DeleteObject(hBitmap);
hBitmap = hTemporaryBitmap;
}
case WM_PAINT:
{
PAINTSTRUCT p;
HDC hDC = BeginPaint(hWnd, &p);
HDC hdcmem = CreateCompatibleDC(hDC);
HBITMAP hImage = TwoBitmap(hDC, p.rcPaint);
CreateTransparentBitmap(hImage);
SelectObject(hdcmem, hImage);
BLENDFUNCTION bfn;
bfn.BlendOp = AC_SRC_OVER;
bfn.BlendFlags = 0;
bfn.SourceConstantAlpha = 10;
bfn.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(hDC, 0, 0, 100, 64, hdcmem, 0, 0, 100, 64, bfn);
bfn.SourceConstantAlpha = 80;
AlphaBlend(hDC, 200, 0, 100, 64, hdcmem, 0, 0, 100, 64, bfn);
bfn.SourceConstantAlpha = 255;
AlphaBlend(hDC, 400, 0, 100, 64, hdcmem, 0, 0, 100, 64, bfn);
BitBlt(hDC, 0, 100, 100, 64, hdcmem, 0, 0, SRCCOPY);
DeleteDC(hdcmem);
DeleteObject(hImage);
EndPaint(hWnd, &p);
}
break;
对于这个例子,我有一个使用CreateCompatibleBitmap()创建的简单位图:
HBITMAP TwoBitmap(HDC &hdc, RECT &rc)
{
HDC hdcmem = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, rc.right-rc.left,
rc.bottom-rc.top);
SelectObject(hdcmem, hbitmap);
HBRUSH hBrush = GetSysColorBrush(3);
FillRect(hdcmem, &rc, hBrush);
DeleteObject((HBRUSH)hBrush);
DeleteDC(hdcmem);
return hbitmap;
}
现在,我试图实现的是将alpha通道添加到这个位图中(如果它还没有的话)。使用下面的代码,我尝试创建一个32位位图,然后将旧位图复制到这个新位图中。最后,我使用AlphaBlend()和BitBlt()函数打印出新的位图到屏幕上,像往常一样,我得到了单色的alpha混合图像和完美的BitBlt图像。
所以我的问题来了——我错过了什么,做错了什么?我在这里迷路了。我的代码(不要介意GDI泄漏):
编辑:
多亏了PhoenixX_2我才解开了这个谜团,我只需要将Alpha位设置为255。下面是我的代码,请记住它不是无泄漏的。
PAINTSTRUCT p;
HDC hDC = BeginPaint(hWnd, &p);
HDC BufferDC = CreateCompatibleDC(NULL);
BITMAPINFO BufferInfo;
ZeroMemory(&BufferInfo,sizeof(BITMAPINFO));
BufferInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BufferInfo.bmiHeader.biWidth = p.rcPaint.right-p.rcPaint.left;
BufferInfo.bmiHeader.biHeight = p.rcPaint.bottom-p.rcPaint.top;
BufferInfo.bmiHeader.biPlanes = 1;
BufferInfo.bmiHeader.biBitCount = 32;
BufferInfo.bmiHeader.biCompression = BI_RGB;
RGBQUAD* pArgb;
HBITMAP BufferBitmap = CreateDIBSection(BufferDC, &BufferInfo, DIB_RGB_COLORS,
(void**)&pArgb, NULL, 0);
HBITMAP hImage = TwoBitmap(hDC, p.rcPaint);
GetDIBits(BufferDC, hImage, 0, BufferInfo.bmiHeader.biHeight, pArgb,
&BufferInfo, DIB_RGB_COLORS);
//----------------------------------the part I was missing
for (int i = 0; i < BufferInfo.bmiHeader.biWidth
* BufferInfo.bmiHeader.biHeight; i++)
pArgb[i].rgbReserved = 255;
//----------------------------------
SelectObject(BufferDC, BufferBitmap);
BLENDFUNCTION bfn;
bfn.BlendOp = AC_SRC_OVER;
bfn.BlendFlags = 0;
bfn.SourceConstantAlpha = 10;
bfn.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(hDC, 0, 0, 100, 64, BufferDC, 0, 0, 100, 64, bfn);
bfn.SourceConstantAlpha = 80;
AlphaBlend(hDC, 200, 0, 100, 64, BufferDC, 0, 0, 100, 64, bfn);
bfn.SourceConstantAlpha = 255;
AlphaBlend(hDC, 400, 0, 100, 64, BufferDC, 0, 0, 100, 64, bfn);
BitBlt(hDC, 0, 100, 100, 64, BufferDC, 0, 0, SRCCOPY);
DeleteDC(BufferDC);
DeleteObject((HBITMAP)BufferBitmap);
EndPaint(hWnd, &p);
我真的建议您使用像FreeImage这样的库。该库的好处,除了它是相当轻量级和非常开放的许可证之外,还在于它可以轻松地处理所有图像类型。然后,从任何格式(包括不同的位图格式)转换为32位都是微不足道的。渲染和其他任务也是如此。
除此之外,如果你对使用库不感兴趣,只需自己操作像素数据即可。从24位转换为32位是相当琐碎的两点和铸造。应该这样做:
uint8_t* pArgb;
uint8_t* pRgb;
GetDIBits(BufferDC, hImage, 0, BufferInfo.bmiHeader.biHeight, pRgb, &BufferInfo, DIB_RGB_COLORS);
pArgb = (uint8_t*)malloc(4 * BufferInfo.bmiHeader.biWidth * BufferInfo.bmiHeader.biHeight);
for (int i = 0; i < BufferInfo.bmiHeader.biWidth * BufferInfo.bmiHeader.biHeight; ++i) {
*(int*)pArgb = 0xff000000 | (*(int*)(pRgb) >> 8);
pArgb += 4;
pRgb += 3;
}
相关文章:
- 使用 GDI+ 旋转位图,然后转换为 HDC
- 将 8bpp 位图转换为 32bpp 位图C++
- 错误 C2440:无法将"系统::D rawing::位图"转换为"系统::对象"
- 如何将屏幕截图位图转换为 cv::Mat
- 如何正确将位图转换为 OpenCV 灰度垫
- 将 GDI Plus 位图转换为 QPixmap
- 将位图转换为opencv :: mat in Jni
- 在C++中将彩色位图转换为灰度
- 将 32bpp 位图转换为 256 种颜色
- 将原始位图转换为QT中的png
- 在内存中将屏幕截图位图转换为jpeg
- 将Alpha通道添加到位图或将位图转换为32位
- 将C#中的位图转换为C++
- 如何在C++中将Windows位图转换为Actionscript位图
- 如何将位图转换为可以用C++(ANN)处理的"矩阵"?
- 如何在c++中将16位RGBA4444位图转换为16位灰度
- 什么库可以用来将位图转换为矢量
- 将位图转换为Mat
- 将位图转换为unsigned char的向量
- 如何将内存中的位图转换为 PIX