讀取並顯示一幅位圖的方法:
1、讀取文件頭,文件頭格式如下:
typedef struct tagBITMAPFILEHEADER {
WORD bfType;//位圖標識,必須示‘BM’
DWORD bfSize;//標識位圖文件的大小,單位是字節
WORD bfReserved1;//未使用
WORD bfReserved2;//未使用
DWORD bfOffBits;//從頭文件到位圖數據的偏移量,主要是指頭文件和調色板的長度,如果是256色的位圖,則這個值爲1078,文件頭14+位圖頭40+調色板256×4
} BITMAPFILEHEADER;
這是MFC中定義的位圖頭文件。
2、讀入位圖頭和位圖數據
位圖頭的格式如下:
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;//標識該結構的大小,應該是40;
LONG biWidth;//位圖的寬度
LONG biHeight;//位圖的高
WORD biPlanes;//必須爲1
WORD biBitCount;//標識位圖的顏色數目,標識2的biBitCount次方色的位圖,256色位圖這裏爲8
DWORD biCompression;//是否壓縮;
DWORD biSizeImage;//位圖的大小,一遍是寬×高,寬必須是4的整數倍。如果是RGB位圖,這裏爲0;
LONG biXPelsPerMeter;//目標設備的水平分辨率
LONG biYPelsPerMeter;//目標設備的垂直分辨率
DWORD biClrUsed;//實際使用到的顏色數,爲0表示都使用;
DWORD biClrImportant;//重要的顏色數,爲0標識都重要;
} BITMAPINFOHEADER;
位圖頭之後的就是調色板,結構如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
調色板之後的就是位圖數據了。
3、顯示位圖文件:
(1)創建調色板指針,對new一個調色板的對象,如下:
CPalette× pPalette = new CPalette;
(2)創建邏輯調色板:
PLOGPALETTE lpLogPalette = (PLOGPALETTE)new char[PaletteSize] ;
(3)填充邏輯調色板:
lpLogPalette->palVersion = PALVERSION; //版本
lpLogPalette->palNumEntries = (WORD)ColorNum; //顏色數
LPBITMAPINFO pPaletteEntry = (LPBITMAPINFO)hBitmap; //hBitmap是指向位圖頭的指針;
for(int i = 0;i<ColorNum;i++)
{
lpLogPalette->palPalEntry[i].peRed = pPaletteEntry->bmiColors[i].rgbRed;
lpLogPalette->palPalEntry[i].peGreen = pPaletteEntry->bmiColors[i].rgbGreen;
lpLogPalette->palPalEntry[i].peBlue = pPaletteEntry->bmiColors[i].rgbBlue;
lpLogPalette->palPalEntry[i].peFlags = 0;
}
(4)創建調色板:
pCPalette->CreatePalette(lpLogPalette);
(5)選擇當前創建的調色板:
CPalette* pOldPalette = pDC->SelectPalette(pCPalette,TRUE);
(6)使用SetDIBitsToDevice函數將位圖顯示出來;
源代碼如下:
1、創建一個單文檔工程:CMyPaintBitmap
2、在頭文件中加入如下定義:
typedef char* HDIB;//此定義在類外
HDIB hDIB;
BITMAPFILEHEADER BitMapHeader;
BITMAPINFOHEADER bitMapInfoHeader;
3、添加打開菜單的命令響應函數,函數代碼如下:
void CCMyPaintBitmapView::OnFileOpen()
{
// TODO: 在此添加命令處理程序代碼
CCMyPaintBitmapDoc* pDoc = GetDocument();
CFileDialog file(true);
if(IDOK != file.DoModal())
{
return;
}
CString m_strFilePath = file.GetPathName();
CStdioFile DibFile;
HDIB& hDIB = pDoc->hDIB;
if(hDIB != NULL)
{
delete []hDIB;
hDIB = NULL;
}
ULONGLONG nFileSize;
ULONGLONG BitMapSize;
BITMAPFILEHEADER& BitMapHeader = pDoc->BitMapHeader;
if(DibFile.Open(m_strFilePath,CStdioFile::modeRead))
{
//讀文件頭
DibFile.Read(&BitMapHeader,sizeof(BITMAPFILEHEADER));
if(BitMapHeader.bfType != 19778)
{
return;
}
nFileSize = DibFile.GetLength();
BitMapSize = nFileSize - sizeof(BITMAPFILEHEADER);
hDIB = new char[BitMapSize];
//讀位圖文件
DibFile.Read(hDIB,BitMapSize);
}
BITMAPINFOHEADER& BitMapInfoHeader = pDoc->bitMapInfoHeader;
//獲得位圖頭文件
memcpy(&BitMapInfoHeader,hDIB,sizeof(BITMAPINFOHEADER));
//ULONGLONG biWidth = pDoc->GetMapWidth();
使窗口無效
Invalidate(true);
}
4、爲CCMyPaintBitmapDoc類增加無暇成員函數
ULONGLONG GetMapWidth(void)
{
ULONGLONG width = bitMapInfoHeader.biWidth;
return ((width + 2)/4) * 4;
}
5、在OnDraw函數中增加如下代碼:
void CCMyPaintBitmapView::OnDraw(CDC* pDC)
{
CCMyPaintBitmapDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處爲本機數據添加繪製代碼
HDIB& hDIB = pDoc->hDIB;
if(hDIB != NULL)
{
CPalette* pOldPalette;
CPalette* pPalette = new CPalette;
unsigned int PaletteSize = sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY);
PLOGPALETTE lpLogPalette = (PLOGPALETTE)new char[PaletteSize];
lpLogPalette->palVersion = 0x300;
lpLogPalette->palNumEntries = 256;
HDIB lpPalette = hDIB + 40;
PALETTEENTRY* pPaletteEntry = (PALETTEENTRY*)lpPalette;
for(int i = 0;i<256;i++)
{
lpLogPalette->palPalEntry[i].peBlue = pPaletteEntry->peBlue;
lpLogPalette->palPalEntry[i].peGreen = pPaletteEntry->peGreen;
lpLogPalette->palPalEntry[i].peRed = pPaletteEntry->peRed;
lpLogPalette->palPalEntry[i].peFlags = 0;
pPaletteEntry++;
}
pPalette->CreatePalette(lpLogPalette);
pOldPalette = pDC->SelectPalette(pPalette,true);
::SetDIBitsToDevice(pDC->m_hDC,0,0,pDoc->GetMapWidth(),pDoc->bitMapInfoHeader.biHeight,0,0,0,pDoc->bitMapInfoHeader.biHeight,LPVOID(hDIB + 1064),(BITMAPINFO*)hDIB,DIB_RGB_COLORS);
pDC->SelectPalette(pOldPalette,true);
delete pPalette;
}
}
6、在CCMyPaintBitmapDoc的構造函數中增加如下語句:
hDIB = NULL
編譯運行,點擊打開按鈕,選擇256色位圖文件,即可顯示到界面上