各位,CreateDibSection说是返回一个Dib的位图,我们知道dib是与设备无关的,里面包含了调色板等信息。为什么我在网上查的代码都是不用解析这个dib的调色板,再赋给对应的dc,而是直接使用当前的设备调色板。就像下面的代码一样:
void CPalettedDIBView::OnDraw(CDC* pDC)
{
CPalettedDIBDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);struct SIBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColor[3]; //exactly three colors in the palette
};SIBITMAPINFO bi = {0};
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = 256;
bi.bmiHeader.biHeight = 256; // positive number == bottom-up DIB
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 8;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biClrUsed = 3; // only three colors are in the palette
// define the three colors in the palette (R, G and B)bi.bmiColor[ 0 ].rgbRed = 255;
bi.bmiColor[ 0 ].rgbGreen = 0;
bi.bmiColor[ 0 ].rgbBlue = 0;
bi.bmiColor[ 0 ].rgbReserved = 0;bi.bmiColor[ 1 ].rgbRed = 0;
bi.bmiColor[ 1 ].rgbGreen = 255;
bi.bmiColor[ 1 ].rgbBlue = 0;
bi.bmiColor[ 1 ].rgbReserved = 0;
bi.bmiColor[ 2 ].rgbRed = 0;
bi.bmiColor[ 2 ].rgbGreen = 0;
bi.bmiColor[ 2 ].rgbBlue = 255;
bi.bmiColor[ 2 ].rgbReserved = 0;
BYTE* pBits;HANDLE hBM = ::CreateDIBSection( (HDC)(*pDC), (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0 );// Set color-index values of the pixels
// This is a bottom-up DIB, so the colors will be in horizontal bands, 64 rows high,
// in the order (bottom-up) of R, G, Bfor ( int iRow=0; iRow<256; ++iRow )
{
for ( int iCol=0; iCol<256; ++iCol )
{
switch ( (iRow/64)%4 )
{
case 0: *pBits = 0; break;
case 1: *pBits = 1; break;
case 2: *pBits = 2; break;
case 3: *pBits = 0; break;
}pBits++;
}
}// blt the DDB bitmap to the display device contextCBitmap bm;
bm.Attach( hBM );CDC memDC;
memDC.CreateCompatibleDC( pDC );
CBitmap* pOldBM = memDC.SelectObject( &bm );pDC->BitBlt( 0, 0, 256, 256, &memDC, 0, 0, SRCCOPY );
memDC.SelectObject( pOldBM );}大家可以看到红色部分,我们在上面定义的调色板,然后调用CreateDIBSection返回一个HBitmap,我觉得在memDC中应该把返回的这个HBitmap中的调色板解析出来,再select到memDC中。这样其实就把它当成了一个DDB来操作了,而不是DIB. 但是这个函数返回的是DIB,而不是DDB。哪位大虾能解释一下。

解决方案 »

  1.   

    HDC能处理DDB和DIBSECTION,但是不能处理DIB,不要把DIB和DIBSECTION混为一谈。之所以不用关心调色板,是因为memDC能正确处理这个位图的细节,它来负责位块传输时调色板、颜色位深的转换。
      

  2.   

    HDC能处理DIBSection,是不是这样理解:HDC能从自动的把这个DibSection中调色板信息给解析出来并赋值给自己,不需要程序员手动的解析,是这样理解吗?要不然上面创建调色板就没有意义了。
      

  3.   

    含义就是DIBSection使用的调色板就是设备内存HDC内的逻辑调色板,所以HDC不需要解析。
      

  4.   

    如果是这样,根本没必要创建palette,然后再赋给SIBITMAPINFO.bmiColor啊,因为都都是使用设备内存调色板,那为什么好多示例都要创建调色板赋给SIBITMAPINFO.bmiColor呢,有点不解
      

  5.   

    你的图像格式是非压缩形式的
    biCompression = BI_RGB
    所以不需要调色板。在你的这个例子里并不需要对SIBITMAPINFO.bmiColor赋值
      

  6.   

    看错了,以为你的biBitCount是大于6;你的biBitCount是8,那么需要2^biBitCount大小的调色板,即256*sizeof(RGBQUAD)
      

  7.   

    btw 你对SIBITMAPINFO.bmiColor赋值之后,然后调用CreateDIBSection函数,使用SIBITMAPINFO.bmiColor设置HDC内存设备的逻辑调色板。
      

  8.   


    在高发色数系统上,那确实是没必要的,因为转成DDB显示后,都不需要调色板了(因为系统发色数大于256).
    至于很多示例都依然创建/实现调色板那是考虑上下兼容的问题,考虑一下那些依然工作在256色及以下的老系统吧,不创建/实现调色板将不能正确显示颜色呢.试试把系统设置为256色就知道了..
    实际上现在很多的流行代码估计放到256色(或以下)系统都会死得很难看的,因为根本没有考虑这个问题.btw:bmiColor可不是调色板哦,那是bmp的色彩表,不要和系统的palette混为一谈..
      

  9.   

    这是啥意思,使用使用SIBITMAPINFO.bmiColor设置HDC内存设备的逻辑调色板? 是调用CreateDIBSection函数的时候已经自动把SIBITMAPINFO.bmiColor设置到HDC内存设备中去了吗?但是你上面又说:DIBSection使用的调色板就是设备内存HDC内的逻辑调色板,所以HDC不需要解析。我搞糊涂了。能详细的解释一下吗?
      

  10.   


    首先,函数返回的DIB section,怎么转成DDB了,有点不明白。
    其次:按照你的解释,如果在高发色数系统上,内存HDC提供的色数会满足DIB section的使用。如果在低于256色以下,需要创建色彩表,那么创建了色彩表后,调用CreateDIBSection函数,会自动把色彩表值赋值给内存HDC吗,还是需要手工解析后再赋给内存HDC.
      

  11.   

    你要是明白了DIBSection的作用就什么都清楚了,DIBSection是什么玩意?我想可能是想像操作DDB图像一样去操作DIB图像吧。DIBSection结合了DDB API的变量,又能使用DIB图像。显然要想像使用DDB数据一样去使用DIB图像,那么就不用去考虑调色板的因素。
    我的理解是在创建DIBSection对象时,使用DIB的调色板去初始化设备DC的调色板。然后直接使用设备DC的调色板去处理DIBSection数据。
      

  12.   


    如果SIBITMAPINFO.bmiColor没有相关的调色板数据,就直接使用内存设备DC中的调色板,是这样理解吗?
      

  13.   

    假如程序肯定不会在8位显示模式下执行,那么您也不需要使用调色盘管理器。调色盘的作用就是显示器能显示的颜色数不能满足你的需要才有用。
    很明显你的目前XP的系统一般是在32位的模式下运行,足够来显示你位图中的所有颜色,那么选择8位位图的调色盘到DC中完全是无效的,你可以使用GetDeviceCaps (hdc, RASTERCAPS)来查询一下系统需不需要使用调色盘,假如需要的话你才有必要把位图中的调色盘选入DC。