有没有关于Bitblt最后一个参数SRCAND更为详细的用法说明

w_anthony 2010-01-21 12:43:56
MSDN解释如下:SRCAND Combines the colors of the source and destination rectangles by using the Boolean AND operator.
实际应用中,发现它对于源是单色DDB和单色DIB这两种格式位图的处理方法完全不同,如果是源是单色DDB格式,可以对目标HDC用SetBkColor和SetTextColor控制AND的部分是黑是白,而如果源是单色DIB格式,需要对源HDC做SetDIBColorTable决定AND的部分是黑是白。而且对付DDB的控制方法对DIB无效,反过来也同样无效。测试机器XP-SP3,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

//#define MASK_USE_DIB

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
HDC hMemDC = CreateCompatibleDC(NULL);
if (hMemDC != NULL)
{
BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = bih.biHeight = 32;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biSizeImage = 32 * 32 * 3;
void* lpBits = NULL;
HBITMAP hMem = CreateDIBSection(NULL, (BITMAPINFO*)&bih, DIB_RGB_COLORS, &lpBits, NULL, 0);
if (hMem)
{
HBITMAP hTempMem = (HBITMAP)SelectObject(hMemDC, hMem);
//填一个全红图
SetBkColor(hMemDC, RGB(255, 0, 0));
RECT rc = {0, 0, 32, 32};
ExtTextOut(hMemDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
//创建单色掩码图
HDC hMaskDC = CreateCompatibleDC(NULL);
if (hMaskDC != NULL)
{
#ifdef MASK_USE_DIB
char chBif[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)] = {0};
BITMAPINFO& bif = (BITMAPINFO&)chBif;
bif.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bif.bmiHeader.biWidth = bif.bmiHeader.biHeight = 32;
bif.bmiHeader.biPlanes = 1;
bif.bmiHeader.biBitCount = 1;
bif.bmiHeader.biSizeImage = 32 / 8 * 32;
((DWORD&)bif.bmiColors[1]) = 0xFFFFFF;
void* lpMaskBits = NULL;
HBITMAP hMask = CreateDIBSection(NULL, &bif, DIB_RGB_COLORS, &lpMaskBits, NULL, 0);
#else
HBITMAP hMask = CreateBitmap(32, 32, 1, 1, NULL); //创建一个DDB单色HBITMAP
#endif
if (hMask)
{
HBITMAP hTempMask = (HBITMAP)SelectObject(hMaskDC, hMask);
//填一个全白图
SetBkColor(hMaskDC, RGB(255, 255, 255));
RECT rc = {0, 0, 32, 32};
ExtTextOut(hMaskDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
//画一个圆
SelectObject(hMaskDC, GetStockObject(BLACK_PEN));
SelectObject(hMaskDC, GetStockObject(BLACK_BRUSH));
Ellipse(hMaskDC, 0, 0, 32, 32);
//SRCAND一下
#ifdef MASK_USE_DIB
RGBQUAD ct[2] = {0};
GetDIBColorTable(hMaskDC, 0, 2, ct);
const RGBQUAD t = ct[0];
ct[0] = ct[1];
ct[1] = t;
SetDIBColorTable(hMaskDC, 0, 2, ct);
#else
SetBkColor(hMemDC, RGB(0, 0, 0));
SetTextColor(hMemDC, RGB(255, 255, 255));
#endif
if (BitBlt(hMemDC, 0, 0, 32, 32, hMaskDC, 0, 0, SRCAND))
{
BITMAPFILEHEADER bfh = {0};
bfh.bfType = 'MB';
bfh.bfOffBits = sizeof(bfh) + sizeof(bih);
bfh.bfSize = bfh.bfOffBits + bih.biSizeImage;
HANDLE hFile = CreateFile("a.bmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile != NULL)
{
DWORD dwUseless = 0;
WriteFile(hFile, &bfh, sizeof(bfh), &dwUseless, NULL);
WriteFile(hFile, &bih, sizeof(bih), &dwUseless, NULL);
WriteFile(hFile, lpBits, bih.biSizeImage, &dwUseless, NULL);
CloseHandle(hFile);
}
}
//结束
SelectObject(hMaskDC, hTempMask);
DeleteObject(hMask);
}
DeleteDC(hMaskDC);
}
SelectObject(hMemDC, hTempMem);
DeleteObject(hMem);
}
DeleteDC(hMemDC);
}
return 0;
}

以上代码用是否定义MASK_USE_DIB来控制使用单色DDB还是DIB位图,效果是在当前文件夹下生成一张黑底红圆的位图。
这个SRCAND的这种特性有文档明确指出么?还是说这只是一个巧合,其他系统无法保证其效果?
...全文
1064 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
w_anthony 2010-01-22
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 ringphone 的回复:]

那这个是跟DDB图有关,跟SRCAND没什么关系,SRCAND就是忠实的进行源与目标的AND运算,SetBkColor和SetTextColor只是在SRCAND之前把源图数据改变一下罢了。
[/Quote]

从DIB的效果看,确实SRCAND就是忠实的进行源与目标的AND运算(SetDIBColorTable交换色彩表相当于对源做反色)。
怪就怪在DDB是对目标HDC作SetBkColor和SetTextColor才有效,而不是对源HDC做设置。
不知道这行为是undefined还是undocument。
w_anthony 2010-01-22
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ringphone 的回复:]
#else
                    SetBkColor(hMemDC, RGB(0, 0, 0));
                    SetTextColor(hMemDC, RGB(255, 255, 255));
#endif
                    if (BitBlt(hMemDC, 0, 0, 32, 32, hMaskDC, 0, 0, SRCAND))
----------------
SetBkColor,SetTextColor跟绘制文字有关,不影响BitBlt吧?这两句注释掉结果有变化吗?
[/Quote]

DDB图就是通过SetBkColor和SetTextColor控制AND的部分认为黑算是1还是0,如果把两者设置的颜色反过来,那么结果是生成一张红底黑圆的图片(原来是黑底红圆)。
ringphone 2010-01-22
  • 打赏
  • 举报
回复
#else
SetBkColor(hMemDC, RGB(0, 0, 0));
SetTextColor(hMemDC, RGB(255, 255, 255));
#endif
if (BitBlt(hMemDC, 0, 0, 32, 32, hMaskDC, 0, 0, SRCAND))
----------------
SetBkColor,SetTextColor跟绘制文字有关,不影响BitBlt吧?这两句注释掉结果有变化吗?
岁月小龙 2010-01-22
  • 打赏
  • 举报
回复
SRCAND 使用布尔AND操作符合并目标像素和源位图。

w_anthony 2010-01-22
  • 打赏
  • 举报
回复
没人知道吗?
klkvc386 2010-01-22
  • 打赏
  • 举报
回复
Mark
ringphone 2010-01-22
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 w_anthony 的回复:]

DDB图就是通过SetBkColor和SetTextColor控制AND的部分认为黑算是1还是0,如果把两者设置的颜色反过来,那么结果是生成一张红底黑圆的图片(原来是黑底红圆)。

[/Quote]

那这个是跟DDB图有关,跟SRCAND没什么关系,SRCAND就是忠实的进行源与目标的AND运算,SetBkColor和SetTextColor只是在SRCAND之前把源图数据改变一下罢了。
norsd 2010-01-21
  • 打赏
  • 举报
回复 1
SRCAND 一般和 SRCPAINT 一起配合使用, 画出透明的效果.
w_anthony 2010-01-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 norsd 的回复:]
SRCAND 一般和 SRCPAINT 一起配合使用, 画出透明的效果.
[/Quote]

答非所问

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧