windows下的DDB和DIB
1、
DDB依赖于具体设备:
DDB的颜色模式必需与输出设备相一致。例如,如果当前的显示设备是256色模式,那么DDB必然也是256色的。
在256色以下的位图中存储的像素值是系统调色板的索引,其颜色依赖于系统调色板。
由于DDB高度依赖输出设备,所以DDB只能存在于内存中,它要么在视频内存中,要么在系统内存中
DIB的与设备无关性主要体现在以下两个方面:
DIB的颜色模式与设备无关。例如,一个256色的DIB即可以在真彩色显示模式下使用,也可以在16色模式下使用。
256色以下(包括256色)的DIB拥有自己的颜色表,像素的颜色独立于系统调色板。
由于DIB不依赖于具体设备,因此可以用来永久性地保存图象。DIB一般是以*.BMP文件的形式保存在磁盘中的,有时也会保存在*.DIB文件中。运行在不同输出设备下的应用程序可以通过DIB来交换图象
DDB依赖于具体设备,它只能存在于内存中(视频内存或系统内存),其颜色模式必须与特定的输出设备相一致,使用系统调色板。一般只能载入色彩较简单的DDB位图,对于颜色较丰富的位图,需使用DIB才能长期保存。
DIB不依赖于具体设备,可以用来永久性地保存图象。DIB一般是以*.BMP文件的形式保存在磁盘中的,有时也会保存在*.DIB文件中。 DIB位图的特点是将颜色信息储存在位图文件自身的颜色表中,应用程序要根据此颜色表为DIB创建逻辑调色板。因此,在输出一幅DIB位图之前,程序应该将其逻辑调色板选入到相关的设备上下文并实现到系统调色板中。
2、我们在加载图片的时候为什么需要创建兼容的设备上下文呢? 其实即使不创建兼容DC我们也可以操作 位图,但是我们这样操作时时刻刻和 真是的设备联系在了一起,
每次对位图的操作都要访问 设备上下文,速度很慢 。我们利用兼容DC也就是 内存中虚拟的设备,完成一切工作之后 然后直接将图片拷贝到上显示,这也就是所谓的双缓冲技术。
3、
如何在窗体显示 DDB?
无非就是 创建和显示设备兼容的DC---->然后将图片选择到兼容DC中 --->最后利用 BitBlt或者 StrechBlt将图片从 兼容DC复制到 显示设备上下文。。
4、
对于DDB的操作 MFC没有给我们封装成一个类,并不是说不重要,DIB在视频开发中有重要的作用 。。
就比如说我们在利用VFW 进行视频捕获的时候,我们捕获到了一帧的图像数据 ,我们要想把这个缓冲区的数据转换成图像 就要涉及到DIB操作 。
StrechDIBts 和 SetDibToDevice都可以直接显示 DIB位图 。 VFW的 DrawDibDraw也可以显示DIB 他可以将一个图像数据绘制到DC上。
GetDIBts DDB转换为DIB
SetDIBts DIB转换为DDB
CreateDIBitmap 用指定的DIB创建DDB并且初始化位图图像
CreateDIBSection 创建一个直接可以写入的DIB 也就是说
5、位图的大小是如何计算的呢 ? 位图的宽度像素 x 位图高度的像素 X (颜色位数/8) =ImageSize
6、我们在使用DIB的时候 一定要了解DIB位图的结构 。 比如我们想截取 屏幕图像并保存起来就需要用到知道DIB 的知识 。
DIB位图 的后缀是 bmp或者dib 。
他的文件结构自上而下是 :
1、 BITMAPFILEHEADER 位图文件信头 保存的是 DIB文件的信息 。
2、 BITMAPINFOHEADER 位图信息头 存储的是位图 的大小 等信息
3、 RGBQUAD 颜色表用于说明位图的颜色 。颜色表中RGBQUAD结构数据的个数由
BITMAPINFOHEADER结构体的biBitCount来确定:当biBitCount=1,4,8时,分别有2,16,256个表项;当biBitCount=24时,没有颜色表项。
4、 位图数据 。
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数由BITMAPINFOHEADER中的biBitCount有关:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;
知道了这样的结构我们就可以,将位图数据保存成 DIB文件 。
下面是一段测试代码:
dcc = GetDesktopWindow()->GetWindowDC();
CBitmap hbitmap;//参数可选
dcMem = CreateCompatibleDC(*dcc); //兼容DC
BITMAPINFO RGB16BitsBITMAPINFO;
ZeroMemory(&RGB16BitsBITMAPINFO, sizeof(BITMAPINFO));
RGB16BitsBITMAPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
RGB16BitsBITMAPINFO.bmiHeader.biWidth = 480;
RGB16BitsBITMAPINFO.bmiHeader.biHeight = 800;
RGB16BitsBITMAPINFO.bmiHeader.biPlanes = 1;
RGB16BitsBITMAPINFO.bmiHeader.biBitCount = 16;
BYTE *lpBitmapBits = NULL;
HBITMAP directBmp = CreateDIBSection(dcMem, (BITMAPINFO*)&RGB16BitsBITMAPINFO,
DIB_RGB_COLORS, (void **)&lpBitmapBits, NULL, 0);
HGDIOBJ previousObject = SelectObject(dcMem, directBmp);
BitBlt(dcMem, 0, 0, 480, 800, *dcc, 0, 0, SRCCOPY);
BITMAPFILEHEADER bmBITMAPFILEHEADER;
ZeroMemory(&bmBITMAPFILEHEADER, sizeof(BITMAPFILEHEADER));
bmBITMAPFILEHEADER.bfType = 0x4d42; //bmp
bmBITMAPFILEHEADER.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((480*800)*2); ///2=(16 / 8)
FILE *mStream = NULL;
if((mStream = fopen("deskmap.bmp", "wb")))
{
fwrite(&bmBITMAPFILEHEADER, sizeof(BITMAPFILEHEADER), 1, mStream);
fwrite(&(RGB16BitsBITMAPINFO.bmiHeader), sizeof(BITMAPINFOHEADER), 1, mStream);
fwrite(lpBitmapBits, 2*480*800, 1, mStream);
fclose(mStream);
}
DeleteObject(dcMem);
DeleteObject(dcc);
DeleteObject(directBmp);
DeleteObject(previousObject);
}
我们有时候可能不明白 我们在将DIB数据显示出来的时候为什么 急需要兼容DC和 兼容位图。 这个是这样的 ,兼容DC就相当与我们的显示设备,而兼容位图我们只有将数据写入到兼容位图中才可以被显示出来 。 我们不可能直接将DIB数据显示到DC上面 ,在VFW中 DrawDIbDraw就是将数据写入到兼容位图 。
兼容位图 和我们现实硬盘上的位图文件其实是一样的 。只不过一个再磁盘上显示 ,而另一个是在内存设备中保存而已 ,在需要的时候可以显示到任意显示设备上,