www.pudn.com > BitmapExample.rar > Dib.cpp


// Dib.cpp: implementation of the CDib class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "BitmapExample.h" 
#include "Dib.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
int dibwidth; 
int dibheight; 
 
CDib::CDib() 
{ 
    m_pDib = NULL; 
 
} 
 
CDib::~CDib() 
{ 
    // 如果位图已经被加载,释放内存 
    if (m_pDib != NULL) 
    delete []m_pDib; 
} 
 
BOOL CDib::Load(const char *pszFilename) 
{ 
	CFile cf; 
	// 打开位图文件 
	if (!cf.Open(pszFilename, CFile::modeRead)) 
		return (FALSE); 
	// 获得位图文件大小,并减去BITMAPFILEHEADER的长度 
	DWORD dwDibSize; 
	dwDibSize = cf.GetLength() - sizeof(BITMAPFILEHEADER); 
	// 为DIB位图分配内存 
	unsigned char *pDib; 
	pDib = new unsigned char[dwDibSize]; 
	if (pDib == NULL) 
		return (FALSE); 
	 
	BITMAPFILEHEADER BFH; 
	 
	// 读取位图文件数据 
	try 
	{ 
		// 文件格式是否正确有效 
		if ( cf.Read(&BFH, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER) || 
			BFH.bfType !='MB'|| cf.Read(pDib, dwDibSize) != dwDibSize) 
		{ 
			delete []pDib; 
			return (FALSE); 
		} 
	} 
	catch (CFileException *e) 
	{ 
		e->Delete(); 
		delete []pDib; 
		return (FALSE); 
	} 
	// delete先前加载的位图 
	if (m_pDib != NULL)  
		delete m_pDib; 
	 
	// 将临时Dib数据指针和Dib大小变量赋给类成员变量 
	m_pDib = pDib; 
	m_dwDibSize = dwDibSize; 
	// 为相应类成员变量赋BITMAPINFOHEADER和调色板指针 
	m_pBIH = (BITMAPINFOHEADER*)m_pDib; 
	m_pPalette = (RGBQUAD*) &m_pDib[sizeof(BITMAPINFOHEADER)]; 
	 
	// 计算调色板中实际颜色数量 
	m_nPaletteEntries = 1 << m_pBIH->biBitCount; 
	if (m_pBIH->biBitCount > 8) 
		m_nPaletteEntries = 0; 
	else if (m_pBIH->biClrUsed != 0) 
		m_nPaletteEntries = m_pBIH->biClrUsed; 
	 
	// 为相应类成员变量赋image data指针 
	m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER) + m_nPaletteEntries * sizeof (RGBQUAD)]; 
	// delete先前的调色板 
	if (m_Palette.GetSafeHandle() != NULL) 
		m_Palette.DeleteObject(); 
	 
	// 如果位图中存在调色板,创建LOGPALETTE 及CPalette 
	if (m_nPaletteEntries != 0) 
	{ 
		LOGPALETTE *pLogPal = (LOGPALETTE*)new char[sizeof(LOGPALETTE) + m_nPaletteEntries *sizeof(PALETTEENTRY)]; 
		if (pLogPal != NULL) 
		{ 
			pLogPal->palVersion = 0x300; 
			pLogPal->palNumEntries = m_nPaletteEntries; 
			 
			for (int i = 0; i < m_nPaletteEntries; i++) 
			{ 
				pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed; 
				pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen; 
				pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgbBlue; 
			} 
			//创建CPalette并释放LOGPALETTE的内存 
			m_Palette.CreatePalette(pLogPal); 
			delete []pLogPal; 
		} 
	} 
	 
	return (TRUE); 
} 
 
     //函数功能:保存位图入BMP文件 
BOOL CDib::Save(const char *pszFilename) 
{ 
	if (m_pDib == NULL) 
		return (FALSE); 
	 
	CFile cf; 
	if (!cf.Open(pszFilename, CFile::modeCreate | CFile::modeWrite)) 
		return (FALSE); 
	try 
	{ 
		BITMAPFILEHEADER BFH; 
		memset(&BFH, 0, sizeof(BITMAPFILEHEADER)); 
		BFH.bfType='MB'; 
		BFH.bfSize = sizeof(BITMAPFILEHEADER) + m_dwDibSize; 
		BFH.bfOffBits = sizeof(BITMAPFILEHEADER) +  
			sizeof(BITMAPINFOHEADER) + m_nPaletteEntries *sizeof(RGBQUAD); 
		cf.Write(&BFH, sizeof(BITMAPFILEHEADER)); 
		cf.Write(m_pDib, m_dwDibSize); 
	} 
	catch (CFileException *e) 
	{ 
		e->Delete(); 
		return (FALSE); 
	} 
	return (TRUE); 
}  
 
BOOL CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode) 
{ 
	if (m_pDib == NULL) 
		return (FALSE); 
	// 获取位图宽度和高度赋值 
	if (nWidth == - 1) 
		nWidth = m_pBIH->biWidth; 
	if (nHeight == - 1) 
		nHeight = m_pBIH->biHeight; 
	 
	dibwidth=nWidth; 
	dibheight=nHeight; 
 
	 
	// 绘制位图 
	StretchDIBits(pDC->m_hDC, nX, nY, nWidth, nHeight, 0, 0,  
			  m_pBIH->biWidth, m_pBIH->biHeight, m_pDibBits, 
			  (BITMAPINFO*)m_pBIH, BI_RGB, mode); 
/*StretchDIBits(pDC->m_hDC, nX, nY, m_pBIH->biWidth,m_pBIH->biHeight, 0, 0,  
			  m_pBIH->biWidth, m_pBIH->biHeight, m_pDibBits, 
			  (BITMAPINFO*)m_pBIH, BI_RGB, mode);*/ 
 
 
	return (TRUE); 
} 
 
//函数功能:设置调色板 
BOOL CDib::SetPalette(CDC *pDC) 
{ 
	if (m_pDib == NULL) 
		return (FALSE); 
	// 检查当前是否有一个调色板句柄,对于大于256色的位图,为NULL 
	if (m_Palette.GetSafeHandle() == NULL) 
		return (TRUE); 
 
// 选择调色板,接着实施之,最后恢复老的调色板 
	CPalette *pOldPalette; 
	pOldPalette = pDC->SelectPalette(&m_Palette, FALSE); 
	pDC->RealizePalette(); 
	pDC->SelectPalette(pOldPalette, FALSE); 
	 
	return (TRUE); 
}