在VC5中顯示256色位圖
發(fā)表時間:2024-02-21 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]李欣 周學(xué)泳 ---- 在Windows的編程中,彩色圖像的顯示和處理一直是一個重要的課題,即使是在顯卡普遍支持真彩的今天,討論256色位圖的顯示也是有意義的。通過對這一課題的討論,可以了解如何在VC5中實現(xiàn)裝入圖像,創(chuàng)建和使用調(diào)色板,以及最后將圖像畫出來。 ---- 總的來說,要顯示一幅256色...
李欣 周學(xué)泳
---- 在Windows的編程中,彩色圖像的顯示和處理一直是一個重要的課題,即使是在顯卡普遍支持真彩的今天,討論256色位圖的顯示也是有意義的。通過對這一課題的討論,可以了解如何在VC5中實現(xiàn)裝入圖像,創(chuàng)建和使用調(diào)色板,以及最后將圖像畫出來。
---- 總的來說,要顯示一幅256色的位圖,首先應(yīng)得到該圖的有關(guān)信息,通過位圖的顏色表創(chuàng)建一個邏輯調(diào)色板,然后將這個調(diào)色板選入設(shè)備環(huán)境,實現(xiàn)這個調(diào)色板,最后將位圖用BitBlt函數(shù)拷貝到設(shè)備環(huán)境就可以了。
---- 具體實現(xiàn)步驟如下:
---- 1、裝載位圖并創(chuàng)建調(diào)色板。
---- 首先裝入一幅位圖,該位圖既可以以資源的形式與程序綁在一起,也可以以文件的形式從外部裝入。然后將該位圖與一個Cbitmap對象聯(lián)系(Attach)起來。在這兒我們應(yīng)使用API函數(shù)LoadImage(),而不是CBitmap類的成員函數(shù)CBitmap::LoadBitmap(),因為我們需要得到該位圖的DIBSECTION結(jié)構(gòu),從這個結(jié)構(gòu)中我們可以得到該位圖的色彩信息,從而建立一個與這些色彩相匹配的邏輯調(diào)色板。使用CBitmap::LoadBitmap()將會失去我們所需的位圖的色彩信息。
---- 得到位圖后,下一步工作就是取得該位圖的色彩信息。通過CBitmap:GetObject()函數(shù),我們可以訪問DIBSECTION結(jié)構(gòu),從中得到位圖的色彩數(shù)。一般來說,這些信息存在于BITMAPINFOHEAD結(jié)構(gòu)中,不過,作為DIBSECTION結(jié)構(gòu)的一部分,BITMAPINFOHEAD有時并未說明圖像用了多少種顏色;碰到這種情況,我們可以看看圖像的每一象素用了幾位(Bit)來描述顏色,如果是8位的話,因為8位二進(jìn)制數(shù)可以表示256種不同的值,所以該圖像是256色的;同理,16Bit表明是64K色。得到了位圖所用的顏色數(shù),就可以創(chuàng)建邏輯調(diào)色板了。色彩超過256色的位圖是沒有顏色表(Color Table)的,這時我們只用簡單地創(chuàng)建一個和設(shè)備環(huán)境兼容的半色調(diào)調(diào)色板(Halftone Palette)就行了,在半色調(diào)調(diào)色板中包含著所有不同顏色的樣本。這顯然不是最佳解決方案,但卻是最簡單的。
---- 而對于顏色數(shù)小于或等于256的位圖,我們就要從頭建立一個新的調(diào)色板。先分配足夠的內(nèi)存空間來裝入圖像的顏色表,顏色表可以利用API函數(shù)GetDIBColorTable獲得;然后再分配足夠的內(nèi)存給新建的邏輯調(diào)色板,將剛才得到的顏色表信息相應(yīng)拷入新建調(diào)色板中的palPalEntry域,并將PalVersion域設(shè)為0X300。創(chuàng)建了調(diào)色板后,應(yīng)將窗口刷新重畫。在具體的實現(xiàn)上,我們定義了一個函數(shù)GetBitmapandPalette()來實現(xiàn)位圖資源的裝入和邏輯調(diào)色板的創(chuàng)建,其功能實現(xiàn)框圖如下(略)
---- 函數(shù)具體實現(xiàn)如下:
BOOL GetBitmapandPalette(LPCTSTR lpszresource,
CBitmap &bitmap, CPalette &pal,long *w,long *h)
{
LPCTSTR lpszresourcename = (LPCTSTR)lpszresource;
HBITMAP hbmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),
lpszresourcename,IMAGE_BITMAP,0,0,
LR_LOADFROMFILE); //裝入位圖
if( hbmp == NULL )
return FALSE;
bitmap.Attach( hbmp );
// 將該位圖與一個CBitmap對象聯(lián)系起來
DIBSECTION ds;
BITMAPINFOHEADER &bminfo = ds.dsBmih;
bitmap.GetObject( sizeof(ds), &ds );
// 得到位圖顏色數(shù)
int ncolors = bminfo.biClrUsed ?
bminfo.biClrUsed : 1 << bminfo.biBitCount; *w="bminfo.biWidth;" //得到位圖寬度值 *h="bminfo.biHeight;" //得到位圖高度值 CClientDC dc(NULL); // 創(chuàng)建邏輯調(diào)色板 if( ncolors> 256 )
pal.CreateHalftonePalette( &dc );
else
{
// 顏色數(shù) <= 256 RGBQUAD *prgb="new" RGBQUAD[ncolors]; CDC memdc; memdc.CreateCompatibleDC(&dc); memdc.SelectObject( &bitmap ); ::GetDIBColorTable( memdc, 0, ncolors, prgb ); UINT nsize="sizeof(LOGPALETTE)" + (sizeof(PALETTEENTRY) * ncolors); LOGPALETTE *plp="(LOGPALETTE" *) new byte[nsize]; plp->palVersion = 0x300;
plp- >palNumEntries = ncolors;
for( int i=0; ipalPalEntry[i].peRed = prgb[i].rgbRed;
plp- >palPalEntry[i].peGreen = prgb[i].rgbGreen;
plp- >palPalEntry[i].peBlue = prgb[i].rgbBlue;
plp- >palPalEntry[i].peFlags = 0;
}
pal.CreatePalette( plp );
delete[] plp;
delete[] prgb;
}
return TRUE;
}
2.顯示位圖
在WM_PAINT消息的響應(yīng)函數(shù)OnPaint()中實現(xiàn)。
void OnPaint()
{
CPaintDC dc(this); // device context for painting
// create a memory dc compatible with the paint dc
CDC memdc;
memdc.CreateCompatibleDC( &dc );
CBitmap bitmap;
CPalette palette;
long nWidth;
long nHeight;
//調(diào)用該函數(shù)
GetBitmapandPalette("e:\\project\\
showimage\\bitmap1.bmp",bitmap,palette ,
&nWidth,&nHeight);
memdc.SelectObject( &bitmap );
// select and realize the palette
if( dc.GetDeviceCaps(RASTERCAPS) &
RC_PALETTE && palette.m_hObject != NULL )
{
dc.SelectPalette( &palette, FALSE );
dc.RealizePalette();
}
//顯示位圖
dc.BitBlt(0, 0, nWidth,nHeight, &memdc, 0, 0,SRCCOPY);
}
---- 以上程序只是簡單的從一個固定路徑(e:\\project\\showimage\\bitmap1.bmp)裝入位圖,讀者可以將其功能擴(kuò)充,如通過對話框選取等等,在此不多贅述。
---- 最后還要補(bǔ)充的一點是,如果要顯示的位圖是作為位圖資源與程序聯(lián)系在一起的,對以上程序稍作修改即可顯示出來,修改方法如下:
首先將GetBitmapandPalette()函數(shù)改為:
BOOL GetBitmapandPalette(UINT nidresource,
CBitmap &bitmap, CPalette &pal,long *w,long *h)
其中nidresource是該位圖的ID。
然后將GetBitmapandPalette()中的第一句改為:
LPCTSTR lpszresourcename = (LPCTSTR)nidresource;
并將LoadImage函數(shù)改為:
HBITMAP hbmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),
nidresourcename,IMAGE_BITMAP,0,0,
LR_CREATEDIBSECTION);
最后,在OnPaint函數(shù)中調(diào)用GetBitmapandPalette()時,
將位圖的ID
通過nidresource傳入即可