Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何为32位位图生成单色位掩码_C++_C_Winapi_Bitmap_Gdi - Fatal编程技术网

C++ 如何为32位位图生成单色位掩码

C++ 如何为32位位图生成单色位掩码,c++,c,winapi,bitmap,gdi,C++,C,Winapi,Bitmap,Gdi,在Win32下,通过执行以下操作,从位图生成用于透明度的单色位掩码是一种常见的技术: SetBkColor(hdcSource, clrTransparency); VERIFY(BitBlt(hdcMask, 0, 0, bm.bmWidth, bm.bmHeight, hdcSource, 0, 0, SRCCOPY)); 这假设hdcSource是保存源图像的内存DC,hdcMask是保存相同大小的单色位图的内存DC(因此两者都是32x32,但源是4位颜色,而目标是1位单色) 然而,当源

在Win32下,通过执行以下操作,从位图生成用于透明度的单色位掩码是一种常见的技术:

SetBkColor(hdcSource, clrTransparency);
VERIFY(BitBlt(hdcMask, 0, 0, bm.bmWidth, bm.bmHeight, hdcSource, 0, 0, SRCCOPY));
这假设hdcSource是保存源图像的内存DC,hdcMask是保存相同大小的单色位图的内存DC(因此两者都是32x32,但源是4位颜色,而目标是1位单色)

然而,当源代码是32位color+alpha时,这似乎对我来说失败了。我没有在hdcMask中得到单色位图,而是得到了一个全黑的掩码。没有位被设置为白色(1)。而这适用于4位颜色源

我的搜索foo失败了,因为我似乎找不到任何关于这个特定问题的参考

我已经指出,这确实是我代码中的问题:即,如果我使用16色(4位)的源位图,它可以工作;如果我使用一个32位的图像,它会产生全黑的遮罩

在32位彩色图像的情况下,我是否应该使用其他方法?alpha通道是否存在覆盖上述技术正常行为的问题

感谢您可能提供的任何帮助

补遗:我仍然找不到一种为我的GDI+生成的源位图创建有效单色位图的技术

通过根本不生成单色位掩码,我在某种程度上缓解了我的特殊问题,取而代之的是使用TransparentBlt(),这似乎是正确的(但我不知道他们在内部做什么,这是允许他们正确屏蔽图像的任何不同)

拥有一个非常好的工作功能可能会很有用:

HBITMAP CreateTransparencyMask(HDC hdc, HBITMAP hSource, COLORREF crTransparency);

它总是创建一个有效的透明度遮罩,而不管hSource的颜色深度。

如果存在alpha通道,则无法执行此操作。 COLORREF将前8位用于多种用途,包括指定下3个字节是当前调色板的颜色表索引还是RGB三元组。因此,除了CLR的上字节中的0x00之外,不能指定任何内容

如果你有一个alpha位图,那么对于GDI来说,它仍然“不知道”alpha通道,没有一个明智的方法来实际比较位图中的24位BkColor和32位像素

我希望GDI将32bpp位图中的alpha通道视为“保留”,并且仅成功比较保留通道为零的像素。i、 你的面具颜色必须是完全透明的,这样才有成功的机会。
(而且,如果您制作了合法的预乘位图,这意味着RGV值也将为零,而不是限制您对遮罩颜色的选择:P)

另一种方法是自己扫描像素,并根据源颜色(或源alpha与阈值)生成黑白位图

请注意,如果您使用的是GDI+,则根据操作的不同,像素可能已被抗锯齿,导致它们都与您的“透明”颜色不完全匹配。

可以:)
正如上面“Chris Becke”所指出的,GDI只能在保留的Alpha通道为零时进行比较。
从BITMAP::GetHBITMAP()获取的HBITMAP返回一个Alpha通道全部设置为0xFF的HBITMAP。
这必须是0x00,SetBkColor()比较才能工作。
因此,Soln:循环通过每个像素并将Alpha组件设置为零

Bitmap img(L"X.bmp");
HBITMAP hBM;
img.GetHBITMAP(Color::White, &hBM);
BITMAP bm;
GetObject(g_hbmBall, sizeof(BITMAP), &bm);
for(UINT i = 0, n = -1; i < bm.bmHeight; i++)
    for(UINT j = 0; j < bm.bmWidth; j++)
    {
        n += 4; // Once per Pixel of 4 Bytes
        ((LPBYTE)bm.bmBits)[n] = 0;
    }
// Now SetBkColor and BitBlt will work as expected
位图img(L“X.bmp”); HBITMAP-hBM; img.GetHBITMAP(颜色:白色和hBM); 位图bm; GetObject(g_hbmBall、sizeof(位图)和bm); 对于(UINT i=0,n=-1;i< bm.bmHeight;i++) 对于(UINT j=0;j< bm.bmWidth;j++) { n+=4;//每像素4字节一次 ((LPBYTE)bm.bmBits)[n]=0; }
//现在SetBkColor和BitBlt将按预期工作
对我有效的方法是首先将位图从32位转换为24位

1. CreateCompatibleDC
2. CreateDIBSection with 24 as the biBitCount.
3. SelectObject
4. BitBlt from 32bit DC to 24 bit. This removes alpha.
5. BitBlt from 24 bit DC to the monochrome DC works as expected.

在我的机器上,这比Ujjwal答案中的双循环执行得更快。

在这种特殊情况下,问题是我从一个4位彩色位图开始。然后,为了在禁用时以一种好的方式显示它,我想对它进行灰度渲染,然后将其用作按钮面(像以前一样使用遮罩透明度技术)。但是我用来生成灰度的代码是基于GDI+的,我怀疑它创建的是32位彩色图像而不是24位彩色图像。@Mordachai:根据你刚才描述的,你能从原始的4位图像制作掩模并与GDI创建的图像一起使用吗?出于我的目的,我喜欢这个想法。但我仍然对通用的“如何为任何源HBITMAP创建单色位掩码”感兴趣。我认为为任何HBITMAP创建单色位掩码的唯一方法是编写自己的。普通GDI中的许多颜色映射技术都特定于基于调色板的图像,不适用于非调色板的图像。GDI的速度为24bpp。TransparentBlt()有点不寻常,它被记录为支持32bpp。也许是时候转到GDI+了。我将GDI+生成的灰度图像保存为32位深度的PNG,然后对绘画中的像素进行采样。他们没事。但是,我确实仔细检查了GDI+生成的HBITMAP(通过Bitmap::GetHBitmap()),它确实始终是32位深度,尽管底层位图实例是PixelFormat24bppRGB)。感谢您的想法。我最终决定根本不使用这种技术,所以这个编码分支现在已经不存在了。我以后可能会再谈这个问题,到时我会再次尝试这个想法为了让这个方法更清楚,a。3) SelectObject将使用CreateDIBSection创建的位图选择到1)b中创建的新DC中。为了创建掩码,您需要确保在1)中创建的新24位DC上调用SetBkColor,我意外地在32位DC上调用了SetBkColor,并花了一段时间进行故障排除。