讀取並顯示一幅位圖的方法

讀取並顯示一幅位圖的方法:
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色位圖文件,即可顯示到界面上


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章