CreateDIBSection 与 CreateDIBIT map 的区别——详细探讨 [已结帖,结帖人:wonaixiaogang] .
[华 软 网]
编程论坛 楼主 很多人说,IDB和DDB之间的相互转换比较慢,所以我们使用CreateDIBSection()来创建一个DIB区块。这样作图速度快。
CreateDIBSection()返回的是一个HBITMAP,CreateDIBitmap()返回的也是HBIT MAP。
两者的区别是,CreateDIBSection创建的是一个DIBSECTION结构,而CreateDIBitmap创建的是BIT MAP结构。
----------------------------------------------------
DIB区块(DIBSECTION)是什么?看看它的结构:
typedef struct tagDIBSECTION {
BIT MAP dsBm;
BIT MAPINFOHEADER dsBmih;
DWORD dsBIT fields[3];
HANDLE dshSection;
DWORD dsOffset;
} DIBSECTION, *PDIBSECTION;
可以看到,它包含了一个 位图结构BITMAP,一个DIB信息头BITMAPINFOHEADER,一个掩码表dsBIT fields[3].
还有一个内存映射文件句柄和偏移量。我们不去理睬最后两个字段。
因此,使用GDI函数对CreateDIBSection()返回的HBIT MAP作图是没有什么问题的。
-------------------------------------------------------------------------
我不明白的是,既然我们可以使用CreateDIBIT map()来从DIB得到DDB,干嘛微软还要多此一举弄一个CreateDIBSection()(除开内存映射文件功能)?
这连个函数的作图效率有差别么?如果有,是什么原因。在我看来,DIB和DDB的区别无非就是信息头不同。一个是BITMAPINFOHEADER,一个是BIT MAP,还有,一个带有颜色表,而另一个没有颜色表。而DIB和DDB的位图数据是完全一样的。
求牛人指教。 .
[华 软 网]
编程论坛 1 个网友回答: CreateDIBitmap The DDB that is created will be whatever bIT depth your reference DC is.
CreateDIBSection To create a bitmap that is of different bIT depth .
[华 软 网]
编程论坛 2 个网友回答: 你首先要搞明白DIB和DDB的区别,对于DDB到DIB的转换,只要加上一个位图信息头就是了;但是从DIB到DDB的转换,要根据当前DC的位图格式 (多少位色彩),可能要扩展也可能要减少色彩位数,如果你考虑这个因素,可以认为是由速度的损失。因此GDI下DDB作图肯定是最快的,直接拷贝位图数据 到显存即可。 .
[华 软 网]
编程论坛 3 个网友回答: 该回复于2009-05-11 10:13:11被版主删除 .
[华 软 网]
编程论坛 4 个网友回答: 其实一句话,使用CreateDIBSection()容易控制,因为你构造的BITMAPINFO是多少bit就按多少bIT 来操作它的位数据.
而CreateDIBitmap(), create出来的是DDB,是和屏幕色深相同的,在这台机它可能是16Bit的,而在那台机器它可能是24bit或者是32bIT ,明显不利于代码操控/维护..
CreateDIBSection()使用时传入一个LPB IT MAPINFO和一个空的CONST VOID **的指针,一旦create了,就可以直接对那个位数据指针(CONST VOID **)操纵,而不需要理会它是怎样转换为DDB的.
不过要说的是,DIB肯定比DDB慢,因为它还要转成DDB显示.
=====================================================
hBitmap = CreateDIBSection( hDC, ( CONST BIT MAPINFO * )lPB minfo, DIB_RGB_COLORS,
( VOID ** )&PB IT s, NULL, 0 );
// 一旦create了,就可以直接操控PB IT s这个指针,例如:
memset( PB IT s, 0x0, ImageSize ); // 全部变黑或者象下面的
*( PB IT s + xxxx ) = 255; // 对某个像素赋值.
========================================================
比较方便,所以很多人都会用这个方法,而且保存为文件时也是相当容易的,有BITMAPINFO和位数据指针,填个BIT MAPFILEHEADER就可以全部写入为一个BMP了. .
[华 软 网]
编程论坛 5 个网友回答: 4楼,按你说法,我这样理解你看对不对:
当第四个参数是 DIB_RGB_COLORS时,CreateDIBSection()创建的DIB不使用HDC的色深,是和HDC不兼容的。那么我们直接使用CreateDIBSection()返回的HBIT MAP 作图的时候,就有可能失败或者错误。
而当第四个参数是 DIB_PAL_COLORS 时,位图色深与HDC兼容,这时,我们用lPB minfo指定的色深就无效了。此时就不能把DIB直接保存到文件中了。
如果我理解错误,请你解释一下,但DC和lPB minfo的色深不一样时,CreateDIBSection()是如何工作的。谢谢 .
[华 软 网]
编程论坛 6 个网友回答: 永远指定为DIB_RGB_COLORS,无论任何情况都不会作图失败的.
因为任何对该HBIT MAP( DDB )的改动,都会反映在它的数据块内(那个const void ** 指针).
例如你用这个CreateDIBSection()函数建了个HBIT AMP,就可以直接选入内存DC画图,然后就直接可以保存,因为所有改动都记录在数据指针内 :
HDC hDC = GetDC( NULL );
HBITMAP hBitmap = CreateDIBSection( hDC, ( CONST BIT MAPINFO * )lPB minfo, DIB_RGB_COLORS,
( CONST VOID ** )&PB IT s, NULL, 0 );
HDC hMemDC = CreateCompatibleDC( hDC );
HBITMAP hOldBmp = ( HBITMAP )SelectObject( hMemDC, hBIT map );
DrawCodeHere().....
DrawAgain().....
// releASE
SelectObject( hMemDC, hOldBmp );
DeleteDC( hMemDC );
ReleASE DC( NULL, hDC );
// 然后就可以保存或者其它..
BIT MAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42;
.........
.....
..
==========================================================================
那是绝对和设备无关的, 绝对不会因为和设备不同而失败, 所以几乎都用它来构造什么CDib之类的.
当然,如果处理的是8bIT 或以下的bmp的话,还要有设置调色板( PALETTE )和彩色表( colors table )的代码 .
[华 软 网]
编程论坛 7 个网友回答: 晕菜了。
DDB 究竟是什么样的结构?除了一个BIT MAP信息头之外,是不是就只有数据区了?
数据区是什么格式的?是4字节一像素的RGB格式,还是每个像素指向DC的颜色表的索引值?
如果DDB的数据是32位1像素的RGB格式的,而DC是8位的256色的颜色盘。把DDB选入DC时,会进行数据区域的转换么?
如果不转换,用DC来作图岂不是会造成颜色错误? .
[华 软 网]
编程论坛 8 个网友回答:
DDB很简单,你的系统是什么色深的,它就是什么色深.
你的系统设置是24Bit true color,DDB就是24Bit true color,如果设置的是16 or 32bit,那么DDB就是16 or 32BIT .
根本就不会存在有32位DDB而DC是8位的.
DC就好比你的屏幕,而DDB就象是屏幕上显示的图,屏幕上能显示的图是多少位(色深),DDB就是多少位的.
DDB是设备相关的. .
[华 软 网]
编程论坛 9 个网友回答:
你这样说,那我们使用DC还有什么用?
屏幕和打印机的DC是不一样的,创建兼容位图就是说创建和DC兼容的位图,是要传入DC参数的。
DC绝对是有8位的,DDB也绝对是有32位的,就看你传入的DC是什么位。
为什么GDI的很多函数都要用到HDC传进参数?就是因为DC可能不一样。
在网上看了一下,CreateDIBSection()的第3个参数使用DIB_RGB_COLORS时,
CreateDIBSection()创建的DIB是直接由4字节一像素的RGB值构成,不使用HDC的色深,是和HDC不兼容的。
.
[华 软 网]
编程论坛 10 个网友回答: 当然,我可能说错了,也有可能,CreateDIBSection()的第3个参数使用DIB_RGB_COLORS时,
CreateDIBSection()创建的DIB是直接和屏幕的DC兼容,也就是使用系统的色深,
不过就算这样,依然是不使用传入的HDC的色深,是可能和HDC不兼容的。 .
[华 软 网]
编程论坛 11 个网友回答: 晕..DC当然有8位,那是因为是设备是8位..
同样,DDB当然也有32位的.
很简单,use CreateCompaibleBitmap() Create个BIT map出来,然后GetObject(),就知道设备是多少位的,因为Create出来的DDB是设备相关的.
同一台机器,DC绝对一样的.
"CreateDIBSection()创建的DIB是直接由4字节一像素的RGB值构成,不使用HDC的色深,是和HDC不兼容的。"
当然不是啦,create 8位的BMP的话,取它的DIB数据指针处理,每个像素还是一个字节的,24位就3个字节.
除非你是在32位色深系统下用GetObject()来取它HIBMTAP那个BIT MAP结构里的DDB数据指针,那才会是4个字节的RGBX数据.
建议lz去看看周长发的 < <精通Visual C++ .NET 图象处理编程 >>.或者去google search DDB & DIB和DC的概念 .
[华 软 网]
编程论坛 12 个网友回答:
你总是说一些片面的句子。
同一台机器,我自己创建的DC和屏幕DC就可能不一样。
你是说:CreateDIBSection()创建的DIB数据返回的指针 和GetObject()来取它HIBMTAP那个BIT MAP结构里的DDB数据指针指向的不是同一个位置?
我去试验了下,证明这两个指针指向的是同一个位置。
.
[华 软 网]
编程论坛 13 个网友回答: 实验代码:
void *ppV;
void *ppV2;
BITMAP B;
HBITMAP hBitmap = CreateDIBSection(NULL,(BIT MAPINFO *)PB uf,DIB_RGB_COLORS,&ppV,NULL,NULL);
GetObject( hBitmap, sizeof(BITMAP),&B);
ppV2 = B.bmBIT s ;
if(ppV==ppV2)
{
TRACE("相同/n");
}
else
{
TRACE("不同/n");
}
.
[华 软 网]
编程论坛 14 个网友回答: 现在我貌似有点点明白了:
CreateDIBSection()的第一个参数HDC和第二个参数BIT MAPINFO的色深必须一样,使用DIB_PAL_COLORS时,函数才会成功。这是因为:
使用DIB_PAL_COLORS时,只是把HDC的颜色表拷贝到DIB的DIBSECTION里的颜色表。而使用DIB_RGB_COLOR时,
DIB的颜色表保持默认的颜色表。
也不知道我说对了没有。我靠,这函数网上的资料和MSDN都没说清楚。而使用它的人也都似懂非懂,将就使用。 .
[华 软 网]
编程论坛 15 个网友回答: 那正好说明CreateDIBSection()创建出来的DIB由里到外都是设备无关...虽然偶还以为它那个HBITMAP的BIT MAP结构已经转换为DDB.
但那又怎样呢?并不如你所说:它的像素是由四个字节RGBX组成的.
依然是8位就1个字节(color table索引),16位就两个字节,是绝对设备无关的.
在上面怎么作图,都不会因为系统色深不同而改变,依然是8bit还是8bit,24bit还是24bIT .
说说你的DC..既然你都是说你创建的DC了,和屏幕的不一样又怎样..
估计你说的是CreateDC(),偶也不知道你Create出什么DC来.
不过,最终显示到屏幕上的DDB的色深肯定和显示设备设置的色深一样.
.
[华 软 网]
编程论坛 16 个网友回答: 传统所说的DC,就是屏幕的设备上下文.
偶之说以说它是一样的,那是因为通常都是用GetDC()来获取DC来显示,获得的色深在一台机器上肯定是相同的..