Windows DIB文件操做具體解釋-5.DIB和調色板

Windows調色板是256色顯卡時期的產物,現在顯卡最少也是16bit的了。因此調色板基本上是用不到了的。spa

但是如下幾種狀況仍是需要去使用和了解調色板:.net

1.在新顯卡上保證256色兼容模式的正常執行code

2.在256色顯卡或低於256色顯卡老機器上執行程序或在一些工業控制場合(爲了節約成本可能採用256色顯卡或低於256色顯卡)執行程序對象

3.操做DIB的指定像素點數據blog


1.調色板是什麼

相同採用如下一張圖ip



如上圖,咱們可以調色板分爲例如如下幾種:內存

1.DIB文件裏的調色板get

2.內存中建立的邏輯調色板對象源碼

3.顯卡中硬件調色板it


調色板顧名思義就是相似畫家的調色板同樣,以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)
{
	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;

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

相關文章
相關標籤/搜索