VC编程打开BMP图片

刚做了一下打开BMP位图的编程,记录一下过程

1:创建CDib类

CDib类的声明

#ifndef _CDIB_H_
#define _CDIB_H_

class CDib : public CObject
{
public:
 RGBQUAD* m_pRGB;
 BYTE* m_pData;
 UINT m_numberOfColors;
 BOOL m_valid;
 BITMAPFILEHEADER bitmapFileHeader;
 BITMAPINFOHEADER* m_pBitmapInfoHeader;
 BITMAPINFO* m_pBitmapInfo;
 BYTE* pDib;
 DWORD size;
public:
 CDib();
 ~CDib();
 char m_fileName[256];
 char* GetFileName();
 BOOL IsValid();
 DWORD GetSize();
 UINT GetWidth();
 UINT GetHeight();
 UINT GetNumberOfColors();
 RGBQUAD* GetRGB();
 BYTE* GetData();
 BITMAPINFO* GetInfo();
 WORD PaleteSize(LPBYTE lpDIB);
 WORD DIBNumColors(LPBYTE lpDIB);
 void SaveFile(const CString filename);
public:
 void LoadFile(const char* dibFileName);
};

#endif

 

CDib类函数的实现:

CDib::CDib()
{
 size = 0;
 m_valid = 0;
}

CDib::~CDib()
{
 GlobalFreePtr(m_pBitmapInfo);
}

void CDib::LoadFile(const char* dibFileName)
{
 strcpy(m_fileName, dibFileName);
 CFile dibFile(m_fileName, CFile::modeRead);
 dibFile.Read((void*)&bitmapFileHeader, sizeof(BITMAPFILEHEADER));
 if (bitmapFileHeader.bfType = 0x4d42)
 {
  DWORD fileLenghth = dibFile.GetLength();
  size = fileLenghth - sizeof(BITMAPFILEHEADER);
  pDib = (BYTE*)GlobalAllocPtr(GMEM_MOVEABLE, size);
  dibFile.Read((void*)pDib, size);
  dibFile.Close();
  m_pBitmapInfo = (BITMAPINFO*) pDib;
  m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pDib;
  m_pRGB = (RGBQUAD*)(pDib + m_pBitmapInfoHeader->biSize);
  int m_numberOfColors = GetNumberOfColors();
  if (m_pBitmapInfoHeader->biClrUsed = 0)
   m_pBitmapInfoHeader->biClrUsed = m_numberOfColors;
  DWORD colorTableSize = m_numberOfColors * sizeof(RGBQUAD);
  m_pData = pDib + m_pBitmapInfoHeader->biSize + colorTableSize;
  if (m_pRGB = (RGBQUAD*)m_pData)
   m_pRGB = NULL;
  m_pBitmapInfoHeader->biSizeImage = GetSize();
  m_valid = TRUE;
 }
 else
 {
  m_valid = FALSE;
  AfxMessageBox("This isn't bitmap file!");
 }
}

BOOL CDib::IsValid()
{
 return m_valid;
}

char* CDib::GetFileName()
{
 return m_fileName;
}

UINT CDib::GetWidth()
{
 return (UINT) m_pBitmapInfoHeader->biWidth;
}

UINT CDib::GetHeight()
{
 return (UINT) m_pBitmapInfoHeader->biHeight;
}
DWORD CDib::GetSize()
{
 if (m_pBitmapInfoHeader->biSizeImage != 0)
  return m_pBitmapInfoHeader->biSizeImage;
 else
 {
  DWORD height = (DWORD)GetHeight();
  DWORD width = (DWORD)GetWidth();
  return height* width;
 }
}

UINT CDib::GetNumberOfColors()
{
 int numberOfColors;
 if ((m_pBitmapInfoHeader->biClrUsed == 0) && (m_pBitmapInfoHeader->biBitCount < 9))
 {
  switch (m_pBitmapInfoHeader->biBitCount)
  {
  case 1: numberOfColors = 2; break;
  case 4: numberOfColors = 16; break;
  case 8: numberOfColors = 256;
  }
 }
 else
  m_numberOfColors = (int)m_pBitmapInfoHeader->biClrUsed;
 return numberOfColors;
}

BYTE * CDib::GetData()
{
 return m_pData;
}

RGBQUAD * CDib::GetRGB()
{
 return m_pRGB;
}

BITMAPINFO * CDib::GetInfo()
{
 return m_pBitmapInfo;
}

WORD CDib::PaleteSize(LPBYTE lpDIB)
{
 return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
}

WORD CDib::DIBNumColors(LPBYTE lpDIB)
{
 WORD wBitCount;
 wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
 switch (wBitCount)
 {
 case 1: return 2;
 case 4: return 16;
 case 8: return 256;
 default: return 0;
 }
}

void CDib::SaveFile(const CString filename)
{
 strcpy(m_fileName, filename);
 CFile dibFile(m_fileName, CFile::modeCreate | CFile::modeWrite);
 dibFile.Write((void*)&bitmapFileHeader, sizeof(BITMAPFILEHEADER));
 dibFile.Write((void*)pDib, size);
 dibFile.Close();
}

 

2:利用MFC ClassWizard为CShowDIBView添加ON_FILE_OPEN的消息响应,并添加以下代码:

void CShowDIBView::OnFileOpen()
{
 CFileDialog dlg(TRUE,
     _T("BMP"),
     _T("*.BMP"),
     OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
     _T("位图文件(*.BMP) | *.BMP|"));
 dlg.DoModal ();
    filename.Format("%s", dlg.GetPathName());   
 m_Dib.LoadFile(filename);
 
 state1 = 1;
 flag = 1;
 CPalette *pal;
 pal = &hPalette;
 ::DeleteObject(pal);
 Invalidate(); 
}

 

3:在OnDraw中添加以下代码

void CShowDIBView::OnDraw(CDC* pDC)
{
 CShowDIBDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 // TODO: add draw code for native data here
 if(state1 == 1)
 {
  int m_scale = 1;
  BYTE *pBitmapData = m_Dib.GetData();
  LPBITMAPINFO pBitmapInfo = m_Dib.GetInfo();
  int bitmapHeight = m_Dib.GetHeight();
  int bitmapWidth = m_Dib.GetWidth();
  int scaledWidth = (int)(bitmapWidth * m_scale);
  int scaledHeight = (int)(bitmapHeight * m_scale);
  if (m_Dib.GetRGB())
  {
   CPalette *hPalette1 = CreateBitmapPalette(&m_Dib);
   flag=0;
   CPalette *hOldPalette = pDC->SelectPalette(hPalette1, TRUE);
   pDC->RealizePalette();
   ::StretchDIBits(pDC->GetSafeHdc(),
       0,
       0,
       scaledWidth,
       scaledHeight,
       0,
       0,
       bitmapWidth,
       bitmapHeight,
       pBitmapData,
       pBitmapInfo,
       DIB_RGB_COLORS,
       SRCCOPY);
   pDC->SelectPalette(hOldPalette,TRUE);
   ::DeleteObject(hPalette1);
  }
  else
  {
   ::StretchDIBits(pDC->GetSafeHdc(),
       0,
       0,
       scaledWidth,
       scaledHeight,
       0,
       0,
       bitmapWidth,
       bitmapHeight,
       pBitmapData,
       pBitmapInfo,
       DIB_RGB_COLORS,
       SRCCOPY);
  }
 }
}

 

4:编写调色版程序如下:

CPalette *CShowDIBView::CreateBitmapPalette(CDib *pBitmap)
{
 if (flag)
 {
  UINT numberOfColors = pBitmap->GetNumberOfColors();
  LPLOGPALETTE palette = (LPLOGPALETTE)new char[2 * sizeof(WORD) + numberOfColors * sizeof(PALETTEENTRY)];
  palette->palVersion = 0x300;
  palette->palNumEntries = numberOfColors;

  LPRGBQUAD pRGBTable = pBitmap->GetRGB();

  for(UINT x = 0; x < numberOfColors; x++)
  {
   palette->palPalEntry[x].peRed = pRGBTable[x].rgbRed;
   palette->palPalEntry[x].peGreen = pRGBTable[x].rgbGreen;
   palette->palPalEntry[x].peBlue = pRGBTable[x].rgbBlue;
   palette->palPalEntry[x].peFlags = 0;
  }

  hPalette.CreatePalette((LPLOGPALETTE)palette);
  delete []palette;
 }
 return &hPalette;
}

 

5:在CShowDIBView的构造函数中添加以下代码:

 state1 = 0;
 flag = 0;

 

最后编译运行,最终实现4,8,24位的bmp位图的显示

你可能感兴趣的:(VC编程打开BMP图片)