HBITMAP 添加透明度/Alpha 通道
我正在尝试向 hbitmap 对象添加透明度,但它从不绘制任何内容:/
这是我用来绘制句柄的代码:
HDC hdcMem = CreateCompatibleDC(hDC);
HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, m_hBitmap);
BLENDFUNCTION blender = {AC_SRC_OVER, 0, (int) (2.55 * 100), AC_SRC_ALPHA}; // blend function combines opacity and pixel based transparency
AlphaBlend(hDC, x, y, rect.right - rect.left, rect.bottom - rect.top, hdcMem, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, blender);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
这是应该向 hbitmap 添加 alpha 通道的代码
BITMAPINFOHEADER bminfoheader;
::ZeroMemory(&bminfoheader, sizeof(BITMAPINFOHEADER));
bminfoheader.biSize = sizeof(BITMAPINFOHEADER);
bminfoheader.biWidth = m_ResX;
bminfoheader.biHeight = m_ResY;
bminfoheader.biPlanes = 1;
bminfoheader.biBitCount = 32;
bminfoheader.biCompression = BI_RGB;
HDC windowDC = CreateCompatibleDC(0);
unsigned char* pPixels = new unsigned char[m_ResX * m_ResY * 4];
GetDIBits(windowDC, m_hBitmap, 0, m_ResY, pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS); // load pixel info
// add alpha channel values of 255 to every pixel if bmp
for (int count = 0; count < m_ResX * m_ResY; count++)
{
pPixels[count * 4 + 3] = 255; <---- here i've tried to change the value to test different transparency, but it doesn't change anything
}
SetDIBits(windowDC, m_hBitmap, 0, GetHeight(), pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS); // save the pixel info for manipulation later
DeleteDC(windowDC);
编辑:
这是代码如何我创建位图 我稍后在一些代码中填充像素数据
m_hBuffer = CreateBitmap( m_ResX, m_ResY, 1, 32, nullptr );
I'm trying to add transparency to a hbitmap object but it never draws anything :/
This is the code i use to draw the handle:
HDC hdcMem = CreateCompatibleDC(hDC);
HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, m_hBitmap);
BLENDFUNCTION blender = {AC_SRC_OVER, 0, (int) (2.55 * 100), AC_SRC_ALPHA}; // blend function combines opacity and pixel based transparency
AlphaBlend(hDC, x, y, rect.right - rect.left, rect.bottom - rect.top, hdcMem, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, blender);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
and this is the code which should add a alpha channel to the hbitmap
BITMAPINFOHEADER bminfoheader;
::ZeroMemory(&bminfoheader, sizeof(BITMAPINFOHEADER));
bminfoheader.biSize = sizeof(BITMAPINFOHEADER);
bminfoheader.biWidth = m_ResX;
bminfoheader.biHeight = m_ResY;
bminfoheader.biPlanes = 1;
bminfoheader.biBitCount = 32;
bminfoheader.biCompression = BI_RGB;
HDC windowDC = CreateCompatibleDC(0);
unsigned char* pPixels = new unsigned char[m_ResX * m_ResY * 4];
GetDIBits(windowDC, m_hBitmap, 0, m_ResY, pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS); // load pixel info
// add alpha channel values of 255 to every pixel if bmp
for (int count = 0; count < m_ResX * m_ResY; count++)
{
pPixels[count * 4 + 3] = 255; <---- here i've tried to change the value to test different transparency, but it doesn't change anything
}
SetDIBits(windowDC, m_hBitmap, 0, GetHeight(), pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS); // save the pixel info for manipulation later
DeleteDC(windowDC);
edit:
This is the code how I create the bitmap
I fill the pixeldata later in some code
m_hBuffer = CreateBitmap( m_ResX, m_ResY, 1, 32, nullptr );
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这很有趣!
猜猜这会打印出什么?
答案:254 - 不是 255。这里发生了两件事:
浮点通常不精确 - 2.55 不能用精确表示 2.55 的二进制值表示 - 它可能类似于 2.5499963...(我刚刚编出来的) ,但你明白了 - 本质上这个数字被表示为 2 的分数之和 - 因为二进制是以 2 为基数 - 所以像 0.5 或 0.25 这样的东西可以可能会精确表示,但大多数其他数字将表示为近似值,您通常不会注意到这一点,因为浮点打印例程将转换回以 10 为基数进行显示,这实际上会引入另一种不精确性,最终会抵消第一个数字:因此,您所看到的分配值或打印输出值并不完全是存储在内存中的表示值。
转换为 int 截断 - 即向下舍入。
把它们放在一起,你的 (2.55 * 100) 得到的是 254,而不是 255 - 并且你必须有神奇值 255 才能使每个像素 alpha 工作。
所以这里的教训是坚持纯整数。或者,如果您确实需要从浮点转换为整数,请注意发生了什么,并解决它(例如,添加 0.5,然后截断 - 或使用类似的技术。)
顺便说一句,这是其中之一逐行执行代码并在每一步检查所有输入和输出的情况(调试时永远不能太偏执!)可能已经显示了问题;在进入 AlphaBlend 之前,当您将鼠标悬停在该参数上时(假设使用 DevStudio 或类似编辑器),您应该会看到 254,并意识到出现了问题。
This is a fun one!
Guess what this prints out?
Answer: 254 - not 255. Two things happening here:
Floats are often inexact - that 2.55 doesn't get represented by a binary value that represents 2.55 exactly - it's probably something like 2.5499963... (I just made that up, but you get the idea - essentially the number is represented as a sum of fractions of 2 - since binary is base 2 - so something like .5 or .25 can likely be represented exactly, but most other numbers will be represented as an approximation. You typically don't notice this because float print routines will convert back to base 10 for display, which essentially introduces another inexactness that ends up cancelling out the first one: so what you see as the assigned value or the printed out value are not exactly the value of the representation as stored in memory).
Casting to int truncates - ie rounds down.
Put these together, and your (2.55 * 100) is getting you 254, not 255 - and you have to have the magic value 255 for per-pixel alpha to work.
So lesson here is stick with pure integers. Or, if you ever do need to convert from float to integers, be aware of what's going on, and work around it (eg. add .5, then truncate - or use a similar technique.)
By the way, this is one of those cases where stepping through code line by line and checking all inputs and outputs at each step (you can never be too paranoid when debugging!) might have shown the issue; right before you step into AlphaBlend, you should see a 254 when you hover over that param (assuming using DevStudio or similar editor) and realize that something's up.