//每一行的字節(jié)數(shù)必須是4的整倍數(shù),調(diào)用宏完成這一換算
//WIDTHBYTES(bi.biWidth*bi.biBitCount)就能進(jìn)行調(diào)整
#define WIDTHBYTES(i) ((i+31)/32*4)
HGLOBAL hImgData;
HPALETTE hPalette;
HBITMAP hBitmap;
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
BOOL LoadBmpFile(HWND hWnd,char *BmpFileName)
{
HANDLE hfile; //文件句柄
LPBITMAPINFOHEADER lpImgData; //指向BITMAPINFOHEADER結(jié)構(gòu)的指針
LOGPALETTE *pPal; //指向邏輯調(diào)色板結(jié)構(gòu)的指針
LPRGBQUAD lpRGB; //指向RGBQUAD結(jié)構(gòu)的指針
HPALETTE hPrevPalette; //用來保存設(shè)備中原來的調(diào)色板
HDC hDc; //設(shè)備句柄
HLOCAL hPal; //存儲(chǔ)調(diào)色板的局部?jī)?nèi)存句柄
DWORD LineBytes; //每一行的字節(jié)數(shù)
DWORD ImgSize; //實(shí)際的圖象數(shù)據(jù)占用的字節(jié)數(shù)
DWORD NumColors; //實(shí)際用到的顏色數(shù),即調(diào)色板數(shù)組中的顏色個(gè)數(shù)
DWORD i;
hfile=CreateFile(BmpFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if(hfile==NULL)
{
MessageBox(hWnd, "File open failed! ", "Error ",MB_OK|MB_ICONEXCLAMATION);
return FALSE; //打開文件錯(cuò)誤返回
}
//ReadFile讀取后按實(shí)際讀的位置調(diào)整文件指針
if(!ReadFile(hfile,&bf,sizeof(BITMAPFILEHEADER),NULL,NULL))
return FALSE; //讀BITMAPFILEHEADER失敗
if(!ReadFile(hfile,&bi,sizeof(BITMAPINFOHEADER),NULL,NULL))
return FALSE; //讀BITMAPINFOHEADER失敗
//計(jì)算實(shí)際數(shù)據(jù)的大小,4倍調(diào)整
LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount); //每一行的字節(jié)數(shù)
ImgSize=(DWORD)LineBytes*bi.biHeight; //實(shí)際的圖象數(shù)據(jù)占用的字節(jié)數(shù)
//進(jìn)行顏色數(shù)的處理
if(bi.biClrUsed!=0) //如果bi.biClrUsed不為零,即為實(shí)際用到的顏色數(shù)
NumColors=(DWORD)bi.biClrUsed;
else //否則,用到的顏色數(shù)為2的biBitCount次冪
switch(bi.biBitCount)
{
case 1:
NumColors=2;
break;
case 4:
NumColors=16;
break;
case 8:
NumColors=256;
break;
case 24:
NumColors=0; //對(duì)于真彩色圖,沒用到調(diào)色板
break;
default: //不處理其它的顏色數(shù),認(rèn)為出錯(cuò)。
MessageBox(hWnd, "Invalid color numbers! ", "Error ",MB_OK|MB_ICONEXCLAMATION);
CloseFile(hfile);
return FALSE; //關(guān)閉文件,返回FALSE
}
//計(jì)算出的偏移量與實(shí)際偏移量不符,一定是顏色數(shù)出錯(cuò)
if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+
sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
{
MessageBox(hWnd, "Invalid color numbers! ", "Error ",MB_OK|MB_ICONEXCLAMATION);
CloseHandle(hfile);
return FALSE; //關(guān)閉文件,返回FALSE
}
//計(jì)算整個(gè)BMP文件的大小
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
NumColors*sizeof(RGBQUAD)+ImgSize;
//申請(qǐng)內(nèi)存空間,忽略了BITMAPFILEHEADER的大小
if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+
NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
{
MessageBox(hWnd, "Error alloc memory! ", "Error ",MB_OK|MB_ICONEXCLAMATION);
CloseHandle(hfile);
return FALSE; //關(guān)閉文件,返回FALSE
}
//GlobalLock將一個(gè)內(nèi)存區(qū)域轉(zhuǎn)為一個(gè)指針
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
//文件指針重新定位到BITMAPINFOHEADER開始處
SetFilePointer(hfile,sizeof(BITMAPFILEHEADER),NULL,FILE_BEGIN);
//將文件內(nèi)容讀入lpImgData
ReadFile(hfile,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER)+
(long)NumColors*sizeof(RGBQUAD)+ImgSize);
CloseHandle(hfile); //關(guān)閉文件
//如果需要調(diào)色板數(shù)據(jù),NumColors不為零
if(NumColors!=0)
{
//為邏輯調(diào)色板分配局部?jī)?nèi)存,大小為邏輯調(diào)色板結(jié)構(gòu)長(zhǎng)度加NumColors個(gè)PALETTENTRY
hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+NumColors* sizeof(PALETTEENTRY));
//指針pPal指向該內(nèi)存區(qū)
pPal =(LOGPALETTE *)LocalLock(hPal);
//填寫邏輯調(diào)色板結(jié)構(gòu)的頭
pPal-> palNumEntries = NumColors;
pPal-> palVersion = 0X300;
//lpRGB指向的是調(diào)色板開始的位置
lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPINFOHEADER));
//填寫每一項(xiàng)
for(i = 0; i < NumColors; i++)
{
pPal-> palPalEntry[i].peRed=lpRGB-> rgbRed;
pPal-> palPalEntry[i].peGreen=lpRGB-> rgbGreen;
pPal-> palPalEntry[i].peBlue=lpRGB-> rgbBlue;
pPal-> palPalEntry[i].peFlags=(BYTE)0;
lpRGB++; //指針移到下一項(xiàng)
}
//產(chǎn)生邏輯調(diào)色板,hPalette是一個(gè)全局變量
hPalette=CreatePalette(pPal);
//釋放局部?jī)?nèi)存
LocalUnlock(hPal);
LocalFree(hPal);
}
//獲得設(shè)備上下文句柄
HDC hDc=GetDC(hWnd);
if(hPalette) //如果剛才產(chǎn)生了邏輯調(diào)色板
{
//將新的邏輯調(diào)色板選入DC,將舊的邏輯調(diào)色板句柄保存在hPrevPalette
hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
RealizePalette(hDc);
}
//產(chǎn)生位圖句柄
hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,
(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);
//將原來的調(diào)色板(如果有的話)選入設(shè)備上下文句柄
if(hPalette && hPrevPalette)
{
SelectPalette(hDc,hPrevPalette,FALSE);
RealizePalette(hDc);
}
ReleaseDC(hWnd,hDc); //釋放設(shè)備上下文
GlobalUnlock(hImgData); //解鎖內(nèi)存區(qū)
return TRUE; //成功返回