Windows AlphaBlend和16位颜色模式

Windows AlphaBlend和16位颜色模式,windows,graphics,alphablending,Windows,Graphics,Alphablending,Win32 graphics不是我的专长,但我必须做一些alpha混合。下面的代码在32位颜色模式下工作正常,但在16位模式下除了白色背景外什么也不显示。抱歉这么长,但我不知道哪里出了问题。这是我能做的最紧凑的 hbm是一种32位ARGB位图,每像素alpha值不同,大小为16x16(因此,cx=cy=16) //创建一个内存DC来构造位 HDC HDC=GetDC(hWnd); HDC hdcMem=CreateCompatibleDC(HDC); HBITMAP hbmMem=创建位图(cx

Win32 graphics不是我的专长,但我必须做一些alpha混合。下面的代码在32位颜色模式下工作正常,但在16位模式下除了白色背景外什么也不显示。抱歉这么长,但我不知道哪里出了问题。这是我能做的最紧凑的

hbm
是一种32位ARGB位图,每像素alpha值不同,大小为16x16(因此,cx=cy=16)

//创建一个内存DC来构造位
HDC HDC=GetDC(hWnd);
HDC hdcMem=CreateCompatibleDC(HDC);
HBITMAP hbmMem=创建位图(cx、cy、1、32、NULL);
选择对象(hdcMem、hbmMem);
//填充背景
RECT rc={0,0,cx,cy};
FillRect(hdcMem,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH));
//获取位图位
BITMAPINFO bmi;
零内存(&bmi,sizeof(bmi));
bmi.bmiHeader.biSize=sizeof(BitMapInfo头文件);
bmi.bmiHeader.biWidth=cx;
bmi.bmiHeader.biHeight=cy;
bmi.bmiHeader.biBitCount=32;
bmi.bmiHeader.biPlanes=1;
bmi.bmiHeader.biCompression=BI_RGB;
std::唯一的ptr pvBits(新字节[cx*cy*4]);
GetDIBits(hdcMem、hbm、0、cy、reinterpret_cast(pvBits.get())、bmi、DIB_RGB_颜色);
//按每像素alpha对所有颜色通道值进行预乘。
int-ctPixels=cx*cy;
字节*prgba=pvBits.get();
对于(int i=0;i对于(int j=0;j根据每像素alpha值,仅支持32位位图。
SetDIBits
如果显示器使用16位颜色,且16位DDB没有空间存储alpha值,则将32位DIB转换为16位DDB。您必须将
bfn.SourceConstantAlpha
设置为alpha值,以将其转换为work。在这种情况下,您也不需要对位图进行预乘。

不幸的是,我们不能使用SourceConstantAlpha,因为它不是常量。alpha从不透明到完全透明(我已将此添加到问题中)。一定有办法做到这一点,因为我们发现WPF可以。好吧,WPF不使用GDI,它使用Direct3D。因此,如果切换到Direct3D是一个可行的选项。否则我想你必须自己去做。将你的窗口渲染到内存DC,获取位,混合它们并将它们设置回原来的位置。Dang。好的,谢谢你的信息。带进来ct3D只是为了这个太过分了,所以我想我们将自己做混合。再次感谢。
// Create a memory DC to construct the bits
HDC hdc = GetDC(hWnd);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmMem = CreateBitmap(cx, cy, 1, 32, NULL);
SelectObject(hdcMem, hbmMem);

// Fill the BG
RECT rc = { 0, 0, cx, cy };
FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH));

// Get the bitmap bits
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = cx;
bmi.bmiHeader.biHeight = cy;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
std::unique_ptr<BYTE[]> pvBits(new BYTE[cx * cy * 4]);
GetDIBits(hdcMem, hbm, 0, cy, reinterpret_cast<void*>(pvBits.get()), &bmi, DIB_RGB_COLORS);

// Premultiply all color channel values by the per-pixel alpha.
int ctPixels = cx * cy;
BYTE *prgba = pvBits.get();
for (int i = 0; i < ctPixels; ++i)
    {
    int alpha = *(prgba + 3);
    for (int j = 0; j <= 2; ++j)
        {
        int k = *prgba;
        *prgba++ = k * alpha / 255;
        }
    ++prgba;
    }

// Put the new bits back
SetDIBits(hdcMem, hbm, 0, cy, reinterpret_cast<void*>(pvBits.get()), &bmi, DIB_RGB_COLORS);

// Alpha blend into memory DC
HDC hdcSrc = CreateCompatibleDC(hdcMem);
HBITMAP hbmOld = static_cast<HBITMAP>(SelectObject(hdcSrc, hbm));
BLENDFUNCTION bfn = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
AlphaBlend(hdcMem, 0, 0, cx, cy, hdcSrc, 0, 0, cx, cy, bfn);
SelectObject(hdcSrc, hbmOld);
DeleteDC(hdcSrc);

// Blit the memory DC to the screen
BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY);