gpt4 book ai didi

mfc - 如何绘制 32 位 Alpha channel 位图?

转载 作者:行者123 更新时间:2023-12-02 03:40:50 27 4
gpt4 key购买 nike

我需要创建一个自定义控件来显示带有 alpha channel 的 bmp 图像。背景可以用不同的颜色绘制,并且图像有阴影,所以我需要真正“绘制”Alpha channel 。

有人知道怎么做吗?

如果可能的话,我还想使用 Alpha channel 信息创建一个蒙版,以了解鼠标是否单击了图像或透明区域。

任何形式的帮助将不胜感激!

谢谢。

已编辑(JDePedro):正如你们中的一些人所建议的那样,我一直在尝试使用 alpha 混合来使用 alpha channel 绘制位图。这只是我实现的一个测试,我从资源加载 32 位位图,并尝试使用 AlphaBlend 函数绘制它:

void CAlphaDlg::OnPaint()
{
CClientDC dc(this);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);

CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP);

BITMAP BitMap;
bitmap.GetBitmap(&BitMap);
int nWidth = BitMap.bmWidth;
int nHeight = BitMap.bmHeight;
CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);

BLENDFUNCTION m_bf;
m_bf.BlendOp = AC_SRC_OVER;
m_bf.BlendFlags = 0;
m_bf.SourceConstantAlpha = 255;
m_bf.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(dc.GetSafeHdc(), 100, 100, nWidth, nHeight, dcMem.GetSafeHdc(), 0, 0,nWidth, nHeight,m_bf);

dcMem.SelectObject(pOldBitmap);

CDialog::OnPaint();
}

这只是一个测试,所以我将代码放在对话框的 OnPaint 中(我还尝试了 CDC 对象的 AlphaBlend 函数)。

非透明区域已正确绘制,但位图应透明的地方却变成白色。

有什么帮助吗???

这是一个屏幕截图..不太容易看到,但蓝色圆圈周围有一个白色矩形: alt text http://img385.imageshack.us/img385/7965/alphamh8.png

好的。我得到了它!我必须预乘每个像素的 alpha 值。有人可以建议优化的方法吗?

最佳答案

对于 future 的谷歌用户,这里有一个有效的预乘函数。请注意,这取自 http://www.viksoe.dk/code/alphatut1.htm .

inline void PremultiplyBitmapAlpha(HDC hDC, HBITMAP hBmp)
{
BITMAP bm = { 0 };
GetObject(hBmp, sizeof(bm), &bm);
BITMAPINFO* bmi = (BITMAPINFO*) _alloca(sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
::ZeroMemory(bmi, sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BOOL bRes = ::GetDIBits(hDC, hBmp, 0, bm.bmHeight, NULL, bmi, DIB_RGB_COLORS);
if( !bRes || bmi->bmiHeader.biBitCount != 32 ) return;
LPBYTE pBitData = (LPBYTE) ::LocalAlloc(LPTR, bm.bmWidth * bm.bmHeight * sizeof(DWORD));
if( pBitData == NULL ) return;
LPBYTE pData = pBitData;
::GetDIBits(hDC, hBmp, 0, bm.bmHeight, pData, bmi, DIB_RGB_COLORS);
for( int y = 0; y < bm.bmHeight; y++ ) {
for( int x = 0; x < bm.bmWidth; x++ ) {
pData[0] = (BYTE)((DWORD)pData[0] * pData[3] / 255);
pData[1] = (BYTE)((DWORD)pData[1] * pData[3] / 255);
pData[2] = (BYTE)((DWORD)pData[2] * pData[3] / 255);
pData += 4;
}
}
::SetDIBits(hDC, hBmp, 0, bm.bmHeight, pBitData, bmi, DIB_RGB_COLORS);
::LocalFree(pBitData);
}

那么你的 OnPaint 就变成了:

void MyButton::OnPaint()
{
CPaintDC dc(this);

CRect rect(0, 0, 16, 16);

static bool pmdone = false;
if (!pmdone) {
PremultiplyBitmapAlpha(dc, m_Image);
pmdone = true;
}

BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;

HDC src_dc = m_Image.GetDC();
::AlphaBlend(dc, rect.left, rect.top, 16, 16, src_dc, 0, 0, 16, 16, bf);
m_Image.ReleaseDC();
}

以及图像的加载(在控件的构造函数中):

if ((HBITMAP)m_Image == NULL) {
m_Image.LoadFromResource(::AfxGetResourceHandle(), IDB_RESOURCE_OF_32_BPP_BITMAP);
}

关于mfc - 如何绘制 32 位 Alpha channel 位图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/307348/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com