3. DDB位图编程
先看DDB加载按钮的单击事件代码:
void CBitMapExampleDlg::OnLoadddbpic() { 1: CBitmap bmpDraw; 2: bmpDraw.LoadBitmap( IDB_LOADED_BITMAP );//装入要加载的DDB位图 3: BITMAP bmpInfo; 4: bmpDraw.GetBitmap( &bmpInfo ); //获取要加载DDB位图的尺寸 5: CDC memDC;//定义一个兼容DC 6: CClientDC dc( this ); 7: memDC.CreateCompatibleDC( &dc );//创建兼容DC 8: CBitmap* pbmpOld = memDC.SelectObject( &bmpDraw );//保存原有DDB,并选入新DDB入DC
9: dc.BitBlt( 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY );
10: memDC.SelectObject( pbmpOld );//选入原DDB } |
上述代码将产生如图1所示的效果,位图被安置在对话框(0,0)坐标开始的位置上。
图1 加载DDB位图资源
|
我们来逐行解析上述代码是怎样产生图1的效果的。
第1、2行定义了一个CBitmap对象,并调用其成员函数LoadBitmap加载工程中的位图资源IDB_LOADED_BITMAP。第3、4行定义了BITMAP结构体的实例并调用CBitmap的成员函数GetBitmap获得位图信息,BITMAP结构体定义在<wingdi.h>头文件中,其形式为:
/* Bitmap Header Definition */ typedef struct tagBITMAP { LONG bmType; //必需为0 LONG bmWidth; //位图的宽度(以像素为单位) LONG bmHeight; //位图的高度(以像素为单位) LONG bmWidthBytes; //每一扫描行所需的字节数,应是偶数 WORD bmPlanes; //色平面数 WORD bmBitsPixel; //色平面的颜色位数 LPVOID bmBits; //指向存储像素阵列的数组 } BITMAP, *PBITMAP, NEAR *NPBITMAP, FAR *LPBITMAP; |
第5~8行的作用是:构建一个CDC对象,调用CDC::CreateCompatibleDC创建一个兼容的内存设备上下文,接着调用CDC::SelectObject将DDB选入内存设备上下文中。
第9行调用函数CDC::BitBlt绘制位图,CDC::BitBlt的原型为:
CDC::BitBlt(int x, int y, int nWidth, int nHeight, CDC *pSrcDC, int xSrc, int ySrc, DWORD dwRop) |
CDC::BitBlt执行的操作为将源DC中位图复制到目的DC中。其中前四个参数为目的区域的坐标(x,y)及长度和宽度(Width, nHeight),第五个参数是源DC指针,接下来的参数是源DC中的起始坐标,最后一个参数为光栅操作的类型。
第10行调用CDC::SelectObject把原来的DDB选入到内存设备上下文中并使新DDB脱离出来。
与CDC::BitBlt对应的还有另一个函数CDC::StretchBlt,它具有缩放功能,其原型为:
BOOL CDC::StretchBlt(int x, int y, int nWidth, int nHeight, CDC *pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop); |
该函数把位图从源矩形拷贝到目的矩形中,如果源和目的矩形尺寸不同,那么将缩放位图的功能以适应目的矩形的大小。函数的大部分参数与BitBlt的相同,但多了两个参数nSrcWidth和nSrcHeight用来指定源矩形的宽和高。
如果我们将函数CBitMapExampleDlg::OnLoadddbpic() 中的第9行改为:
CRect clientRect; GetClientRect(&clientRect); //获得对话框窗口的大小 dc.StretchBlt(0, 0, clientRect.right, clientRect.bottom, &memDC, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY); |
则单击加载按钮后的对话框如图2所示,位图被拉伸至整个对话框的范围。
图2 拉伸位图
|
CDC::BitBlt和dc.StretchBlt函数中的dwRop参数较为有用,它定义光栅操作的类型。请看"DDB位图"父菜单下"标记"子菜单单击事件的消息处理函数代码:
void CBitMapExampleDlg::OnMarkDdbpic() { CBitmap bmpDraw; bmpDraw.LoadBitmap(IDB_YESKY_BITMAP); //装入天极网logo DDB位图资源 BITMAP bmpInfo; bmpDraw.GetBitmap(&bmpInfo); //获取天极网logo位图的尺寸
CDC memDC; //定义一个兼容DC CClientDC dc(this); memDC.CreateCompatibleDC(&dc); //创建DC
CBitmap *pbmpOld = memDC.SelectObject(&bmpDraw); //保存原有DDB,并选入天极网logo位图入DC dc.BitBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCAND); memDC.SelectObject(pbmpOld); //选入原DDB } |
单击该按钮后,将产生如图3的效果,天极网的logo被透明地添加到了位图中!
图3 在DDB位图中加入天极网logo
|
能产生这个效果的原因在于我们在代码行:
dc.BitBlt ( 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCAND ); |
中使用了参数SRCAND(不同于先前代码中SRCCOPY,它仅仅意味着复制源位图到目的位图),它的含义为源和目的间进行AND操作。我们不知道天极网的编辑同志是怎么为文章中的图片加logo的,有可能他们就使用了具有自动AND功能的图像加logo批处理软件。的确,我们可以利用例程中的原理写一个批处理软件,一次对一堆图片自动添加logo。
参数dwRop除了可以为SRCAND和SRCCOPY外,还可以有如下取值:
BLACKNESS:输出区域为黑色
DSTINVERT:反转目的位图
MERGECOPY:用与操作把图案(Pattern)与源位图融合起来
MERGEPAINT:用或操作把反转的源位图与目的位图融合起来
NOTSRCCOPY:把源位图反转然后拷贝到目的地
NOTSRCERASE:用或操作融合源和目的位图,然后再反转
PATCOPY:把图案拷贝到目的位图中
PATINVERT:用异或操作把图案与目的位图相融合
PATPAINT:用或操作融合图案和反转的源位图,然后用或操作把结果与目的位图融合
SRCERASE:先反转目的位图,再用与操作将其与源位图融合
SRCINVERT:用异或操作融合源位图和目的位图
SRCPAINT:用或操作融合源位图和目的位图
WHITENESS:输出区域为白色
合理利用这些取值将帮助我们制作出特定要求的图像处理软件。
从上述实例我们可以看出,在VC中使用CBitmap类,必须将位图放入工程的资源中,并使用类 CBitmap的成员函数LoadBitmap加载之,再通过CDC类的成员函数BitBlt进行DC拷贝等操作达到显示的目的。CBitmap有显示的不足:
(1) 位图需要放入工程资源中,这将导致工程的可执行文件变大;
(2) 因为位图需放入工程资源中,而资源中不能无穷无尽地包含位图,应用程序无法自适应地选取其它位图,能使用的位图十分有限的;
(3) 类CBitmap只是DDB位图操作API的封装,不能独立于平台。
DIB位图则可以解决上述问题,其特点是以.BMP位图文件格式存储独立于平台的图像数据,下面我们来详细分析。
分享到:
相关推荐
DDB与DIB位图编程,讲的比较好~值得学习
将ddb的位图转换成DIB的位图 用VS2005,C++
Vs2005 C++ dib类 将DDB的位图转换为DIB的位图 绘制DIB的图片
位图中DDB与DIB的区别介绍,以及编程全攻略,文档中有代码的
Converting DDB to DIB将一个设备相关的位图转换成设备无关的位图(6KB)
DDB2DIB转变源代码
我遇到了这个问题,于是在网上查了好多资料,搞了一天才写出了两个函数进行转化,将32位的DDB和DIB互相转换。(包含详细的注释) 如果你需要转换其他格式的,可以自己设定参数。 网上下的那些代码都有问题,我这个是...
第1章 Visual C++与数字图像处理 1 1.1 数字图像处理概述 2 1.1.1 图像与数字图像 2 1.1.2 数字图像处理研究的内容 4 1.1.3 数字图像处理的应用 6 1.2 Visual C++概述 8 1.2.1 C++语言简介 8 1.2.2 Visual C++简介 ...
用CreateDIBitamp函数和LoadImage函数实现DIB到DDB位图的转换和百叶窗效果。
ConvertDDBToDIB从ddb到dib转换的类
Converting DIB to DDB将一个设备无关的位图转换成设备相关的位图(5KB)
转换DDB到DIB.pdf
对于刚学图像处理的人往往分不清DIB,DDB和DIBSection的区别,这个文档很好地说明了它们之间的区别。
基础知识,图像处理的基本知识,很多人都在问,看了这个就明白了
1.4与设备无关的位图(DIB) 11.5动画控件 11.6媒体控制接口(MCI). 11,7小结 第十二章 多线程与串行通信 12.1 多任务、进程和线程 12.2 线程的同步 12.3 串行通信与重叠I/O 12.4 一个通信...
VS2005 C# Dib 处理设备无关图像 DDB转化为DIB 绘制DIB
实现DIB与DDB图像相互转换 读取 显示 储存 简易vc++代码 睡不着 无聊的写的代码 绝对好用
VS2005 C++ CDib 处理设备无关图像 DDB转化为DIB 绘制DIB
VS2005 设备相关转为设备无关 已测试过