刚做了一下打开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位图的显示