//每一行的字節(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; //存儲調(diào)色板的局部內(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; //對于真彩色圖,沒用到調(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; //申請內(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)色板分配局部內(nèi)存,大小為邏輯調(diào)色板結(jié)構(gòu)長度加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); //釋放局部內(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; //成功返回 |
|