www.gusucode.com > VC++位图拉伸与背景叠加应用示例-源码程序 > VC++位图拉伸与背景叠加应用示例-源码程序/code/Dib.cpp

    #include "stdafx.h"
#include "windows.h"
#include "windowsx.h"
#include "Dib.h"
// Download by http://www.NewXing.com
CDib::CDib()
{
	Initialize();
}

CDib::CDib(const char* fileName)
{
	Initialize();
	LoadFromFile(fileName);		//读入位图并做初始化
}
//初始化
void CDib::Initialize()
{
	m_pBmInfo		= 0;
	m_pBmInfoHeader = 0;
	m_pRGBTable		= 0;
	m_pDibBits		= 0;
	m_bNeedPalette	= FALSE;
	m_hPalette		= NULL;
}

CDib::~CDib()
{
	Empty();
}
//清空函数
void CDib::Empty()
{
	if(m_pBmInfo)
		GlobalFreePtr(m_pBmInfo);		//释放位图占用的内存
	if(m_bNeedPalette && m_hPalette)	//释放调色板
		DeleteObject(m_hPalette);
}
//从文件读入位图
BOOL CDib::LoadFromFile (LPCTSTR fileName)
{
	CFile file;
	//打开位图文件
	if(file.Open(fileName, CFile::modeRead|CFile::shareDenyWrite)!=TRUE)
	{
		CString errorStr;
		errorStr.Format(_T("打开%s错误"), (LPCTSTR)fileName);
		AfxMessageBox(errorStr);
		file.Close();
		return FALSE;
	}
	//读入位图文件头
	BITMAPFILEHEADER bmFileHeader;
	file.Read((void*)&bmFileHeader, sizeof(bmFileHeader));
	//检查是否是位图标识符,如果不是,显示错误信息,并返回
	if (bmFileHeader.bfType != 0x4d42)
	{
		CString errorStr;
		errorStr.Format("%s 不是位图文件!!!", (LPCTSTR)fileName);
		AfxMessageBox(errorStr);
		file.Close();
		return FALSE;
	}
	//计算位图数据的大小,等于文件长度-文件头长度
	DWORD fileLength = file.GetLength();
	DWORD dibSize = fileLength - sizeof(bmFileHeader);
	//为位图数据分配内存
	BYTE* pDib = (BYTE*)GlobalAllocPtr(GMEM_MOVEABLE, dibSize);
	//把位图数据读入内存并关闭文件
	file.Read((void*)pDib, dibSize);
	file.Close();
	//初始化位图信息头指针和位图信息指针
	m_pBmInfo = (LPBITMAPINFO) pDib;
	m_pBmInfoHeader = (LPBITMAPINFOHEADER) pDib;
	//如果BITMAPINFOHEADER的biSizeImage不正确,改正
	if (m_pBmInfoHeader->biSizeImage == 0)
		m_pBmInfoHeader->biSizeImage 
			= m_pBmInfoHeader->biWidth * m_pBmInfoHeader->biHeight;
	//如果biClrUsed为0,且不是真彩色图,返回2的biBitCount次方,否则直接返回已有值
	if(m_pBmInfoHeader->biClrUsed == 0)
		m_pBmInfoHeader->biClrUsed = DWORD(1 << m_pBmInfoHeader->biBitCount);
	//判断是否需要调色板
	if(m_pBmInfoHeader->biClrUsed <= 256)
	{
		m_bNeedPalette = TRUE;
		//计算颜色查找表的偏移量,并给其指针赋值
		m_pRGBTable = (RGBQUAD*)(pDib + m_pBmInfoHeader->biSize);
		m_hPalette = CreateDibPalette();
	}
	//计算位图点数组的偏移量,并给其指针赋值
	DWORD clrTableSize = m_bNeedPalette ? UsedColors() * sizeof(RGBQUAD) : 0;
	m_pDibBits = pDib + m_pBmInfoHeader->biSize + clrTableSize;
	return TRUE;
}
//返回位图的大小(高度*宽度)
DWORD CDib::ImageSize()
{
	return m_pBmInfoHeader->biSizeImage;
}
//返回位图的宽度
int CDib::Width()
{
	return m_pBmInfoHeader->biWidth;
}
//返回位图的高度
int CDib::Height()
{
	return m_pBmInfoHeader->biHeight;
}
//返回位图使用的颜色数
UINT CDib::UsedColors()
{
	return (int) m_pBmInfoHeader->biClrUsed;
}
//返回位图的信息头指针
LPBITMAPINFOHEADER CDib::GetInfoHeaderPtr()
{
	return m_pBmInfoHeader;
}
//返回位图的信息块指针
LPBITMAPINFO CDib::GetInfoPtr()
{
	return m_pBmInfo;
}
//返回位图的颜色查找表指针
LPRGBQUAD CDib::GetRGBTablePtr()
{
	return m_pRGBTable;
}
//返回位图的点数组
BYTE* CDib::GetBmBitsPtr()
{
	return m_pDibBits;
}
//返回是否需要调色板
BOOL CDib::NeedPalette()
{
	return m_bNeedPalette;
}
//返回调色板句柄
HPALETTE CDib::GetDibPalette()
{
	return m_hPalette;
}
//计算图像数据字节数
DWORD CDib::ImageDataSize()
{
	return (Width()*Height()*m_pBmInfoHeader->biBitCount)/8;
}
//创建调色板,返回其句柄
HPALETTE CDib::CreateDibPalette()
{
	//获得颜色数
	UINT numColors = UsedColors();
	//定义逻辑调色板
	struct
	{
		WORD Version;
		WORD NumberOfEntries;
		PALETTEENTRY aEntries[256];
	}	logicalPalette = { 0x300, 256 };
	//把RGBTable中的数据转入调色板中
	for(UINT i=0; i<numColors; ++i)
	{
		logicalPalette.aEntries[i].peRed	= m_pRGBTable[i].rgbRed;
		logicalPalette.aEntries[i].peGreen	= m_pRGBTable[i].rgbGreen;
		logicalPalette.aEntries[i].peBlue	= m_pRGBTable[i].rgbBlue;
		logicalPalette.aEntries[i].peFlags	= 0;
	}
	//生成调色板句柄
	HPALETTE hPalette = ::CreatePalette((LPLOGPALETTE)&logicalPalette);
	return hPalette;
}
//显示显示由CDib封装的位图,bStretch为是否拉伸
ShowDib(CDC * pDC,CDib * pDib,CRect& rect,BOOL bStretch)
{
	BYTE* pBmBits			= pDib->GetBmBitsPtr();
	LPBITMAPINFO pBmInfo	= pDib->GetInfoPtr();
	UINT bmWidth			= pDib->Width();
	UINT bmHeight			= pDib->Height();
	//根据是否拉伸,决定显示的矩形
	CRect drawRect;
	if(bStretch==TRUE)
		drawRect = rect;
	else
	{
		drawRect.left = rect.left;
		drawRect.top = rect.top;
		drawRect.right = rect.left+bmWidth;
		drawRect.bottom = rect.top+bmHeight;
	}
	//如果需要调色板,生成调色板
	HPALETTE hPalette = NULL;
	HPALETTE hOldPalette = NULL;
	if(pDib->NeedPalette())
	{
		hPalette = pDib->GetDibPalette();
		hOldPalette = SelectPalette(pDC->m_hDC,hPalette, FALSE);
		RealizePalette(pDC->m_hDC);
	}
	//使用StretchDIBits显示
	::StretchDIBits(pDC->m_hDC,
		drawRect.left,drawRect.top,drawRect.Width(),drawRect.Height(),
		0, 0, bmWidth, bmHeight,
		pBmBits, pBmInfo, DIB_RGB_COLORS, SRCCOPY);
	//释放调色板
	if(pDib->NeedPalette())
	{
		::SelectPalette(pDC->m_hDC,hOldPalette,FALSE);
		::DeleteObject(hPalette);
	}
	return 0;
}