依赖于设备的位图(DDB) ,CreateCompatibleBitmap用法
DDB(Device-dependent bitmap)依赖于具体设备,这主要体现在以下两个方面:
DDB的颜色模式必需与输出设备相一致。例如,如果当前的显示设备是256色模式,那么DDB必然也是256色的,即一个像素用一个字节表示。
在256色以下的位图中存储的像素值是系统调色板的索引,其颜色依赖于系统调色板。
由于DDB高度依赖输出设备,所以DDB只能存在于内存中,它要么在视频内存中,要么在系统内存中。
11.3.1 DDB的创建
MFC的CBitmap类封装了DDB。该类提供了几个函数用来创建DDB:
BOOL LoadBitmap( LPCTSTR lpszResourceName );
BOOL LoadBitmap( UINT nIDResource );
该函数从资源中载入一幅位图,若载入成功则返回TRUE。资源位图实际上是一个DIB,该函数在载入时把它转换成了DDB。
BOOL CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits );
该函数用来创建一幅空白的DDB。参数nWidth和nHeight以像素为单位说明了位图的宽度和高度。nPlanes是DDB的色平面数,nBitcount是每个色平面的颜色位数。一般来说,nPlanes为1,而nBitcount代表DDB中每个像素值所占的位数,但在创建16色DDB时,nPlanes为4,而nBitcount为1。参数lpBits指向存储像素阵列的数组,该数组应该逐行存储位图的每个像素值。注意,数组中每行像素的数目必需是偶数个字节,如果是奇数,则应该用0补足。若创建成功函数返回TRUE。
BOOL CreateCompatibleBitmap( CDC* pDC, int nWidth, int nHeight );
该函数创建一个与指定设备上下文兼容的DDB。参数pDC指向一个设备上下文,nWidth和nHeight是DDB的尺寸。若创建成功函数返回TRUE。
可以调用CBitmap的成员函数GetBitmap来查询DDB的各种属性(如尺寸):
int GetBitmap( BITMAP* pBitMap );
该函数用来获得与DDB有关的信息,参数pBitMap指向一个BITMAP结构。BITMAP结构的定义为:
typedef struct tagBITMAP {
LONG bmType; //必需为0
LONG bmWidth; //位图的宽度(以像素为单位)
LONG bmHeight; //位图的高度(以像素为单位)
LONG bmWidthBytes; //每一扫描行所需的字节数,应是偶数
WORD bmPlanes; //色平面数
WORD bmBitsPixel; //色平面的颜色位数
LPVOID bmBits; //指向存储像素阵列的数组
} BITMAP;
11.3.2 DDB的用途
DDB的主要用途是保存位图。要保存的位图可以来自资源位图,也可以是一个绘图的结果。
前面说过,在256色以下的显示模式中,DDB中的像素值是系统调色板的索引。一般在系统调色板中除了保留的20种静态颜色外,其它表项都有可能被应用程序改变。如果DDB中有一些像素值是指向20种静态颜色以外的颜色,那么该位图的颜色将是不稳定的。因此,DDB不能用来长期存储色彩丰富的位图。如果位图使用的大部分颜色都是20种保留色,则该位图可以用CBitmap对象保存在内存中。例如,用CDC::LoadBitmap载入的资源位图一般都是颜色较简单的位图,对于那些颜色比较丰富的位图,只有使用下面将要介绍的DIB才能长期保存。
在窗口中显示DDB的方法有些特别,其过程分以下几步:
构建一个CDC对象,然后调用CDC::CreateCompatibleDC创建一个兼容的内存设备上下文。
调用CDC::SelectObject将DDB选入内存设备上下文中。
调用CDC::BitBlt或CDC::StretchBlt将DDB从内存设备上下文中输出到窗口的设备上下文中。
调用CDC::SelectObject把原来的DDB选入到内存设备上下文中并使新DDB脱离出来。
下面这段代码在视图中显示了一个DDB:
void CMyView::OnDraw( CDC* pDC)
{
. . .
CDC MemDC;
CBitmap *oldBmp;
BITMAP bmpInfo;
int bmWidth,bmHeight;
MemDC.CreateCompatibleDC(pDC);
oldBmp=MemDC.SelectObject(&m_Bitmap); //m_Bitmap是一个CBitmap对象
m_Bitmap.GetBitmap(&bmpInfo); //获取位图的尺寸
bmWidth=bmpInfo.bmWidth;
bmHeight=bmpInfo.bmHeight;
pDC->BitBlt(0,0,bmWidth,bmHeight,&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(oldBmp); //使位图m_Bitmap脱离设备上下文
. . .
}
函数CDC::BitBlt的声明为:
BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );
该函数把源设备上下文中的位图复制到本身的设备上下文中,两个设备上下文可以是内存设备上下文,也可以是同一个设备上下文。参数x和y是目的矩形的逻辑坐标,参数nWidth和nHeight说明了目的矩形及源位图的宽和高。pSrcDC指向源设备上下文,xSrc和ySrc说明了源矩形相对于源位图左上角的偏移。参数dwRop指定了光栅操作(ROP)代码,一些常用的ROP代码如表11.2所示。
表11.2 常用的ROP代码
|
ROP码 |
含义 |
|
BLACKNESS |
输出黑色 |
|
DSTINVERT |
反转目的位图 |
|
MERGECOPY |
用与操作把图案(Pattern)与源位图融合起来 |
|
MERGEPAINT |
用或操作把反转的源位图与目的位图融合起来 |
|
NOTSRCCOPY |
把源位图反转然后拷贝到目的地 |
|
NOTSRCERASE |
用或操作融合源和目的位图,然后再反转 |
|
PATCOPY |
把图案拷贝到目的位图中 |
|
PATINVERT |
用异或操作把图案与目的位图相融合 |
|
PATPAINT |
用或操作融合图案和反转的源位图,然后用或操作把结果与目的位图融合 |
|
SRCAND |
用与操作融合源位图和目的位图 |
|
SRCCOPY |
把源位图拷贝到目的位图 |
|
SRCERASE |
先反转目的位图,再用与操作将其与源位图融合 |
|
SRCINVERT |
用异或操作融合源位图和目的位图 |
|
SRCPAINT |
用或操作融合源位图和目的位图 |
|
WHITENESS |
输出白色 |
函数CDC::StretchBlt的声明为:
BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop );
该函数把位图从源矩形拷贝到目的矩形中,如果源和目的矩形尺寸不同,那么将缩放位图的功能以适应目的矩形的大小。函数的大部分参数与BitBlt的相同,但多了两个参数nSrcWidth和nSrcHeight用来指定源矩形的宽和高。
DDB的一个重要用途是用作设备上下文的显示表面。每一个设备上下文都包含有一个DDB,该位图实际上是在显示设备的缓冲区中(如视频内存),我们可以把它看做设备上下文的显示表面,设备上下文用GDI函数绘图实际上就是修改它所包含的DDB(显示表面)的过程。
普通的设备上下文都是在屏幕上绘图的,而使用内存设备上下文则可以在系统内存中绘制图形。内存设备上下文是一种特殊的设备上下文,它将系统内存用作显示表面。程序可以使用内存设备上下文预先在系统内存中绘制复杂的图形,然后再快速地将其复制到实际的设备上下文的显示表面上,而绘制图形的结果仍保存在内存设备上下文的DDB中。
| 提示:有人可能会想到用BitBlt函数把绘图结果从显示设备拷贝到内存设备上下文中,这种方法可以工作,但有时会出错。当源矩形被别的窗口遮住时,BitBlt会把别的窗口中的像素拷贝下来。 |
内存设备上下文缺省的DDB是一个1×1的单色位图,如此小的显示表面显然是没有用的,因此程序一般要为内存设备对象选择一个合适大小的彩色DDB。
下面这段代码创建了一个内存设备上下文,并在其包含的DDB中画了一个灰色实心矩形,然后再把DDB输出到屏幕上。
void CMyView::OnDraw(CDC* pDC)
{
. . .
CDC MemDC;
CBitmap bm,*oldBmp;
MemDC.CreateCompatibleDC(pDC); //创建一个兼容的内存设备上下文
bm.CreateCompatibleBitmap(pDC,100,50); //创建一个兼容的DDB
oldBmp=MemDC.SelectObject(&bm);
MemDC.SelectStockObject(BLACK_PEN);
MemDC.SelectStockObject(GRAY_BRUSH);
MemDC.Rectangle(0,0,50,50); //在DDB中画一个矩形
pDC->BitBlt(0,0,100,50,&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(oldBmp); //使位图bm对象脱离设备上下文
. . .
}
在上面的代码中,绘图的结果保存在位图bm中,一旦调用MemDC.SelectObject(oldBmp)使位图bm脱离设备上下文,该位图就可以被其它对象使用。
下面是别人的一段代码,我无法理解CreateCompatibleBitmap函数的意义。兼容位图到里是做什么的?不明白!
CPaintDC dc(this); // 用于绘制的设备上下文
CRect rcClient;
GetClientRect(&rcClient);
//构造内存DC,用于画图
CDC m_MemDC;
m_MemDC.CreateCompatibleDC(&dc);
CBitmap btScreen;
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
m_MemDC.SelectObject(&btScreen);
btScreen.DeleteObject();
//这里画图
...
dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &m_MemDC, 0, 0, SRCCOPY);
m_MemDC.DeleteDC();
/////////////////////////////////////////////
一)
在上面代码中,如果我将
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
换成
btScreen.LoadBitmap(IDB_BITMAP1);
能达到同样的效果吗?
二)
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
m_MemDC.SelectObject(&btScreen);
CreateCompatibleBitmap创建一幅兼容位图后将该容易位图选入DC中,这个兼容位图到里是个什么图片?我发现,将该语句屏蔽后,程序运行后显示有些地方是黑的。不知道为什么。
三)
我想知道,CreateCompatibleBitmap到里创建了一幅什么位图啊?这个函数里面根本就没有填入任何位图信息嘛,难道它创建的是一幅空位图吗?它有什么意思啊?平常都是用LoadBitmap来创建位图的,真不知道什么时候该用CreateCompatibleBitmap函数,对这个函数一点都不理解,希望有高手能详细指点一下,重分答谢!
网友回复:记不清楚了,大概是每个新建的内存兼容DC里选中的位图都是1*1的灰度图,不创建一个兼容位图选进去的话,现实意义上说这个DC不可用(往上面bitblt)
网友回复:兼容位图是位图的各种信息与设备相兼容,主要是颜色位数要相同。
新创建的位图所有像素值都是0,通常是黑色。
兼容位图主要用于与设备相互复制图象,最常见的就是“双缓冲”绘图方式。
网友回复:CreateCompatibleBitmap用法
创建一幅与设备有关位图,它与指定的设备场景兼容
内存设备场景即与彩色位图兼容,也与单色位图兼容。这个函数的作用是创建一幅与当前选入hdc中的场景兼容。对一个内存场景来说,默认的位图是单色的。倘若内存设备场景有一个DIBSection选入其中,这个函数就会返回DIBSection的一个句柄。如hdc是一幅设备位图,那么结果生成的位图就肯定兼容于设备(也就是说,彩色设备生成的肯定是彩色位图)
如果nWidth和nHeight为零,返回的位图就是一个1×1的单色位图
一旦位图不再需要,一定用DeleteObject函数释放它占用的内存及资源
网友回复:一:可以,但是要注意位图的大小。
二:内存DC默认的位图是1x1单色位图,必须选入屏幕兼容的位图(也可以是其它格式)才能绘制、显示对应格式的颜色;
三:CreateCompatibleBitmap创建的位图是空的,一般初始化为黑色(和操作系统有关),关键是复制了参数中dc的位图格式。
依赖于设备的位图(DDB) ,CreateCompatibleBitmap用法的更多相关文章
- Device-Dependent Bitmaps (DDB) 设备相关位图
设备相关的位图(DDB)使用单一结构BITMAP结构描述.该结构的成员指定矩形区域的宽度和高度,以像素为单位;将条目从设备调色板映射到像素的数组的宽度;以及器件的颜色格式,在每个像素的颜色平面和位数方 ...
- 第15章 设备无关位图_15.3 DIB和DDB的结合
第15章 设备相关位图_15.3 DIB和DDB的结合 15.3.1 从DIB创建DDB (1)hBitmap =CreateDIBitmap(…)——注意这名称会误导,实际上创建的是DDB 参数 说 ...
- windows设备相关位图与设备无关位图
windows支持两种位图格式,DDB(device-dependent bitmap),DIB(device-independent bitmap).设备相关位图用于windows显示系统中,其图像 ...
- device-independent bitmap (DIB) 设备无关位图
设备无关位图即独立于设备的位图(DIB)与"Device-Dependent Bitmaps (DDB) 设备相关位图"相比,它不再依赖于具体的设备,从而更适合在不同的计算机之间传 ...
- 屏幕抓取程序 (位图DDB的例子)
屏幕抓取程序的意思是将整个屏幕图显示在应用程序的用户区中,等价于截图.对桌面窗口的操作:首先得知道桌面窗口的宽和高,获取宽和高需要利用窗口的设备句柄,而获取设备句柄需要知道窗口句柄,这一系列的连串关系 ...
- 第15章 设备无关位图_15.2 显示和打印DIB
15.2.1 探究DIB (1)DIB文件的结构 整个文件 紧凑DIB(整个文件除文件头) 文件头(File Header) 信息头(Information Header) 信息头(Informati ...
- 第15章 设备无关位图_15.1 DIB文件格式
15.1 DIB文件格式(一种文件格式,扩展名为BMP) 15.1.1 OS/2风格的DIB 文件格式 字段 说明 文件头 (BITMAPFILEHEADER) 1.共14个字节 2.缩写建议用bmf ...
- 位图和SVG用法比较
位图,亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的.这些点可以进行不同的排列和染色以构成图样.当放大位图时,可以看见赖以构成整个图像的无数单个方块.扩大位图尺寸的效果是增大单个像素 ...
- [2011-3-9 12:59 ]As3.0中的位图(Bitmap/BitmapData)用法
1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xefefef); //画 ...
随机推荐
- java String分类trim,substring,replaceAll,indexOf使用功能
1.trim性能 特征去掉字符串首尾空格,防止不必要的空格导致错误. public class TrimTest { public static void main(String[] args) { ...
- Android应用开发基础篇(13)-----GestureDetector(手势识别)
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/05/2381025.html 一.概述 GestureDetector是一个用于识别手势的类,这 ...
- tomcat管理员manager app无法进入解决方法
浏览器输入http://localhost:8080/进入tomcat页面后,点击manager app输入用户名(admin)密码(admin)后页面跳转出现如下错误:备注:tomcat7.0.39 ...
- select标签操作大全
http://blog.csdn.net/hhhh2012/article/details/8610336
- [LeetCode]题解(python):122-Best Time to Buy and Sell Stock II
题目来源: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ 题意分析: 和上题类似,给定array,代表第i天物品i ...
- NET Core,Ubuntu运行
NET Core,如何开发跨平台的应用并部署至Ubuntu运行 之前写了一篇博文宣布Rabbit Rpc跨平台了“拥抱.NET Core,跨平台的轻量级RPC:Rabbit.Rpc”,在过程中尝试了如 ...
- spss
编辑 SPSS(Statistical Product and Service Solutions),“统计产品与服务解决方案”软件.最初软件全称为“社会科学统计软件包” (SolutionsStat ...
- A Brief Introduction to Multiset[STL]
基础 multiset是<set>库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,而且序列中可以存 ...
- Poj 2232 Moo Volume(排序)
题目链接:http://poj.org/problem?id=2231 思路分析:先排序,再推导计算公式. 代码如下: #include <iostream> #include <a ...
- 2014-CVTE网测部分软件技术测试题及答案
1.叉树的先序遍历序列和后序遍历序列正好相反,则该二叉树满足的条件是(D) A.空或只有一个结点 B.高度等于其结点数 C.该二叉树是完全二叉树 D.所有结点无右孩子 应该是二叉树的每个结点都只有一个 ...