当前位置: 首页 > 工具软件 > Dib Utils​ > 使用案例 >

DDB&DIB

邵兴怀
2023-12-01

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就是将数据写入到兼容位图 。 

兼容位图 和我们现实硬盘上的位图文件其实是一样的 。只不过一个再磁盘上显示 ,而另一个是在内存设备中保存而已 ,在需要的时候可以显示到任意显示设备上。

首先是DIB,DIB之所以设备无关,是因为他本身带有图像的描述信息。
比如储存的是多少bit色的图片,如果不是真彩则带有一个颜色表(调色板)。
这样程序在显示DIB的时候,可以根据这些信息把数据转换成符合当前显示模式的数据,再显示到屏幕上(传输到内存或者显存中)。
所以一个DIB图像在GDI中不能用一个简单的数组表示,需要有一个专门的结构来记录头部信息,以及颜色表。常见的Bmp图像就是在一个DIB图像的基础上,再加Bmp图像的文件头组成。
DIB的图像数据有点不方便地方在于,每行图像数据必须是DWORD的整数倍,也就是4字节的整数倍,不足补充0,而且是从下到上从左到右组成。

在MFC中,没有处理DIB的东西,我理解是指没有像CBitmap一样封装好的类。用于绘图的API还是有的,不过必须是包括DIB图像头部结构以及符合DIB的数据排布的图像数据,否则就不能显示。

DDB就是根据当前显示模式创建的图像,其实当我们把图像从BMP文件读入之后,系统内部储存的就是DDB了。比如CBitmap就是DDB,或者DDraw的surface所读入的数据也是DDB。
不同颜色格式的DDB是不能直接转换的……比如32bit的CBitmap就不能往24bit的CBitmap上面绘图,BitBlt方法会失败。
CBitmap调用CreateBitmap方法建立对象的话,必须指定合适的参数,如果和当前显示模式不同,就不能绘制在当前的屏幕上。所以一般不采用这种方式,调用CBitmap的另外一个Create方法建立兼容当前显示模式的CBitmap。

然后是关于DC的,也就是设备上下文。这个概念感觉很奇怪,虽然抽象出来一个DC有一定好处,但是具体用的时候会很麻烦,每次都要建立一个DC才能开始绘图或者写字等操作。这个DC是抽象于图像或者窗体之外的,所以感觉会很奇怪。本来是把图像绘制到窗体上,而他们之间也是可以绘制的,非要先建立两个关联到他们的DC,然后在DC之间操作-.-并且如果DC之间存在某种差异,就会操作失败。

 类似资料:

相关阅读

相关文章

相关问答