Windows调色板是256色显卡时期的产物,现在显卡最少也是16bit的了。因此调色板基本上是用不到了的。spa
但是如下几种状况仍是需要去使用和了解调色板:.net
1.在新显卡上保证256色兼容模式的正常执行code
2.在256色显卡或低于256色显卡老机器上执行程序或在一些工业控制场合(为了节约成本可能採用256色显卡或低于256色显卡)执行程序对象
3.操做DIB的指定像素点数据blog
相同採用如下一张图ip
如上图,咱们可以调色板分为例如如下几种:内存
1.DIB文件里的调色板get
2.内存中建立的逻辑调色板对象源码
3.显卡中硬件调色板it
调色板顾名思义就是相似画家的调色板同样,以256色显卡来讲,现在有256个小格子,每个格子中有一种颜色,每次画图你可以用这256种颜色来画图,假设你对当前的256种颜色不惬意,可以更换当中的调色板颜色,但是每画一幅图仅仅能用确认的256中颜色来。相应到电脑的调色板来讲,显卡支持显示的颜色仅仅有256种,存储在显卡硬件调色板中,你可以设置要採用的256种颜色。而后你要显示的所有颜色都会近似用256中颜色中的一种来显示,这就是所谓的调色板查表以取得近期似颜色。
可以看到。一幅图在电脑上显示的效果是什么样和当前显卡硬件调色板中的颜色是密不可分的,因此对于採用硬件调色板的的位图,保存它的最好作法就是保存位图数据的同一时候保存位图调色板。
为了改变硬件调色板中的颜色咱们需要先建立逻辑调色板对象,而后再将逻辑调色板映射到硬件调色板上。
对于带有调色板的DIB来讲。显示DIB的通常过程例如如下:
1.读入DIB分别为File Header、Info Header、Mask、Color Table、Bits各个区
2.利用DIB的调色板数据(Color Table区)建立逻辑调色板对象(CreatePalette)。通常在WM_CREATE中
3.在WM_PAINT显示DIB以前,将基于DIB建立的逻辑调色板对象选进当前设备描写叙述表(SelectPalette)并映射到硬件调色板上(RealizePalette)。
4.假设仅仅是想保证指定窗体为活动窗体时显示的颜色,那么作完这三歩便可了。假设想保证指定窗体不是活动窗体时的颜色,那么还要处理WM_QUERYPALETTE和WM_PALETTECHANGED消息。
这两个消息是为了帮助Windows组织系统调色板用的。这里不详述。直接依照固定模式使用,详细可以查看MSDN。
演示程序为一个典型的Windows 带调色板DIB的显示过程。如下为部分代码,完整源码最后会给出下载连接。
依据DIB Color Table建立逻辑调色板
//建立数据显示调色板 HPALETTE PackedDibCreatePalette(BITMAPINFO *pPackedDib, HWND hwnd) { HPALETTE hPalete; HDC hdc; int i, iNumColors; LOGPALETTE *plp = NULL; RGBQUAD *prgb = NULL; if (0 == PackedDibGetColorTableSize(pPackedDib) && PackedDibGetBitCount(pPackedDib) > 8)//没有调色板区且位深大于8,则没有必要建立调色板 { return NULL; } else if (0 == PackedDibGetColorTableSize(pPackedDib))//没有调色板区且位深小于等于8,则建立通用调色板 { hdc = GetDC(hwnd); hPalete = CreateHalftonePalette(hdc); ReleaseDC(hwnd, hdc); return hPalete; } else//使用位图自带的调色板区 { iNumColors = PackedDibGetNumColors(pPackedDib); plp = malloc(sizeof(LOGPALETTE) + (iNumColors-1)*sizeof(PALETTEENTRY)); if (NULL == plp) { return NULL; } plp->palVersion = 0x0300; plp->palNumEntries = iNumColors; for (i = 0; i < iNumColors; i++) { prgb = PackedDibGetColorTableEntry(pPackedDib, i); plp->palPalEntry[i].peRed = prgb->rgbRed; plp->palPalEntry[i].peGreen = prgb->rgbGreen; plp->palPalEntry[i].peBlue = prgb->rgbBlue; plp->palPalEntry[i].peFlags = 0; } hPalete = CreatePalette(plp); if (INVALID_HANDLE_VALUE == hPalete) { return NULL; } return hPalete; } }
WM_PAINT中显示DIB及WM_QUERYPALETTE和WM_PALETTECHANGED消息的处理
case WM_PAINT: hdc = BeginPaint (hwnd, &ps); if (hPalette) { SelectPalette(hdc, hPalette, FALSE); RealizePalette(hdc); } if (pPackedDib) { SetDIBitsToDevice( hdc, 0, 0, PackedDibGetWidth(pPackedDib), PackedDibGetHeight(pPackedDib), 0, 0, 0, PackedDibGetHeight(pPackedDib), PackedDibGetBitsPtr(pPackedDib), pPackedDib, DIB_RGB_COLORS); } EndPaint (hwnd, &ps); return (0); case WM_QUERYNEWPALETTE: if(!hPalette) { return FALSE; } hdc = GetDC(hwnd); SelectPalette(hdc, hPalette, FALSE); RealizePalette(hdc); InvalidateRect(hwnd, NULL, FALSE); ReleaseDC(hwnd, hdc); return TRUE; case WM_PALETTECHANGED: if(!hPalette || (HWND)wParam==hwnd) { break; } hdc = GetDC(hwnd); SelectPalette(hdc, hPalette, FALSE); RealizePalette(hdc); UpdateColors(hdc); ReleaseDC(hwnd, hdc); break;
至此为止,关于DIB显示的全部知识点全部讲完。在给出的代码中实现了一个完整的DIB操做库,主要用于打开、显示和保存DIB。不一样于实验DIB显示功能,一个完整性好的DIB操做库必须兼容各类版本号DIB格式、不标准DIB位图。
1.DIB版本号的兼容主要包含对OS/2格式位图的兼容(BITMAPCOREHEADER定义带来的各类差别。RGBTRIPLE带来的差别)。
2.不标准DIB位图主要指有的DIB位图不填充ClrUsed、SizeImage项,有的小于8bit的DIB位图没有调色板需要使用通用调色板,有的16bit位图不提供掩码等等。
总之,一个实现完整的DIB库需要考虑种种繁枝末节,假设是在商业程序中使用的话。最好使用已经开源的各类实现。该博文提供的DIB库在Pelzold的实现上改动而来,但仍然有不足,好比对压缩的DIB没有考虑等,仅供技术研究用。
完整源码下载连接
原创。转载请注明来自http://blog.csdn.net/wenzhou1219