標籤:win32 dib 位元影像 調色盤
Windows調色盤是256色顯卡時期的產物,現在顯卡最少也是16bit的了,所以調色盤基本上是用不到了的。
但是下面幾種情況還是需要去使用和瞭解調色盤:
1.在新顯卡上保證256色相容模式的正常運行
2.在256色顯卡或低於256色顯卡老機器上運行程式或在一些工業控制場合(為了節約成本可能採用256色顯卡或低於256色顯卡)運行程式
3.操作DIB的指定像素點資料
1.調色盤是什麼
同樣採用下面一張圖
如,我們可以調色盤分為如下幾種:
1.DIB檔案中的調色盤
2.記憶體中建立的邏輯調色盤對象
3.顯卡中硬體調色盤
調色盤顧名思義就是類似畫家的調色盤一樣,以256色顯卡來說,現在有256個小格子,每個格子中有一種顏色,每次繪圖你可以用這256種顏色來繪圖,如果你對當前的256種顏色不滿意,可以更換其中的調色盤顏色,但是每畫一幅圖只能用確認的256中顏色來。對應到電腦的調色盤來說,顯卡支援顯示的顏色只有256種,儲存在顯卡硬體調色盤中,你可以設定要採用的256種顏色,然後你要顯示的所有顏色都會近似用256中顏色中的一種來顯示,這就是所謂的調色盤查表以取得最近似顏色。
可以看到,一幅圖在電腦上顯示的效果是什麼樣和當前顯卡硬體調色盤中的顏色是密不可分的,所以對於採用硬體調色盤的的位元影像,儲存它的最好做法就是儲存位元影像資料的同時儲存位元影像調色盤。
為了改變硬體調色盤中的顏色我們需要先建立邏輯調色盤對象,然後再將邏輯調色盤映射到硬體調色盤上。
2.調色盤的使用
對於帶有調色盤的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。
3.代碼示範
示範程式為一個典型的Windows 帶調色盤DIB的顯示過程。下面為部分代碼,完整原始碼最後會給出下載連結。
根據DIB Color Table建立邏輯調色盤
//建立資料顯示調色盤HPALETTE PackedDibCreatePalette(BITMAPINFO *pPackedDib, HWND hwnd){HPALETTEhPalete;HDChdc;inti, 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;
4.DIB操作庫
至此為止,關於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