graphdib.cpp

来自「读写位图文件的」· C++ 代码 · 共 275 行

CPP
275
字号
// GraphDIB.cpp: implementation of the CGraphDIB class.
// 作者:董希华
// 日期:2004年11月05日
// 联系方式: sddongxh@hotmail.com
// 说明:本例程曾参考多人的代码,在此致谢!
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "myDib.h"
#include "GraphDIB.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define PALVERSION   0x300
IMPLEMENT_SERIAL(CGraphDIB,CObject,1)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGraphDIB::CGraphDIB()
{
	m_hBmp     = NULL;
	m_pBmpInfo = NULL;
	m_pPixels  = NULL;
}

CGraphDIB::~CGraphDIB()
{
	
	//m_pPixels在GDI对象m_hBmp被销毁时同时释放
	if(m_hBmp!=NULL)
	{
		DeleteObject(m_hBmp);
		m_hBmp = NULL;
		m_pPixels = NULL;
	}
	if(m_pBmpInfo!=NULL)
	{
		delete []m_pBmpInfo;
	}


}

bool CGraphDIB::LoadBmp(CFile &file)
{

    DWORD dwStart = file.GetPosition();

	BITMAPFILEHEADER bfhHeader;
	file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));

	if(bfhHeader.bfType!=((WORD)('M'<<8)|'B'))                  //判断是否是bmp文件
	{
		AfxMessageBox("文件不是bmp文件");
		return false;
	}

	if(bfhHeader.bfSize!=file.GetLength())
	{
		AfxMessageBox("文件已经损坏!");
		return false;
	}
	
	int nBmpInfoLen = bfhHeader.bfOffBits - sizeof(BITMAPFILEHEADER);//判断位图信息头的长度

	m_pBmpInfo = (LPBITMAPINFO)new BYTE[nBmpInfoLen];                //创建信息头

	file.Read((void*)m_pBmpInfo,nBmpInfoLen);          	//读入位图信息


	UINT nBitLen = bfhHeader.bfSize - bfhHeader.bfOffBits;           //位图象素数据的长度


	m_hBmp = ::CreateDIBSection(NULL,m_pBmpInfo,DIB_RGB_COLORS,(void**)&m_pPixels,NULL,0);
	if(m_hBmp==NULL)
	{	
		delete []m_pBmpInfo;
		m_pBmpInfo = NULL;
		return false;
	}
	
//	file.Seek(dwStart + bfhHeader.bfOffBits,CFile::begin);
	if(file.ReadHuge(m_pPixels,nBitLen)!=nBitLen)
	{
		AfxMessageBox("读文件时发生错误!");
		file.Close();
		delete []m_pBmpInfo;
		m_pBmpInfo = NULL;
		DeleteObject(m_hBmp);
		m_hBmp = NULL;
		return false;
	}

	m_rectBound = CRect(0,0,Width(),Height());

    int nSize = file.GetPosition();

	return true;

}

bool CGraphDIB::LoadBmp(const char *lpszFileName)
{
	//如果已经创建了对象,安全清除之
	if(m_hBmp!=NULL)
	{
		DeleteObject(m_hBmp);
		m_hBmp = NULL;
		m_pPixels = NULL;
	}
	if(m_pBmpInfo!=NULL)
	{
		delete []m_pBmpInfo;
	}
	//
	CFile file;
	if(!file.Open(lpszFileName,CFile::modeRead|CFile::shareDenyWrite))
	{
		AfxMessageBox("未能打开bmp文件!");
		return false;
	}

	bool res = LoadBmp(file);
	file.Close();
    return res;

}


int CGraphDIB::Width() const
{
	if(m_pBmpInfo!=NULL)
		return m_pBmpInfo->bmiHeader.biWidth;
	else
		return 0;

}

int CGraphDIB::Height() const
{
	if(m_pBmpInfo!=NULL)
		return m_pBmpInfo->bmiHeader.biHeight;
	else
		return 0;
}


void CGraphDIB::Serialize(CArchive &ar)
{
	if(ar.IsStoring())
	{	
		CFile *pFile = ar.GetFile();
		ar.Flush();
		WriteToFile(*pFile);
		
    }
	else
	{
		CFile *pFile = ar.GetFile();
		ar.Flush();
		bool res = LoadBmp(*pFile);
	
	}
}


int CGraphDIB::GetBmpInfoSize()  const //获取位图信息头的大小
{
	if(m_pBmpInfo==NULL)
		return 0;

	int nbitCount = m_pBmpInfo->bmiHeader.biBitCount;
	int nPalEntries = 0;
	if(nbitCount<=8)
		nPalEntries = 1<<nbitCount;
	
	return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nPalEntries;
	
}
bool CGraphDIB::WriteToFile(CFile &file)
{
	if(m_hBmp==NULL)
		return false;

	BITMAPFILEHEADER bfhHeader;
    bfhHeader.bfType = 0x4d42;  // 'BM'
    bfhHeader.bfSize = sizeof(BITMAPFILEHEADER) + GetBmpInfoSize() + GetBmpDataSize();
    bfhHeader.bfReserved1 = 0;
	bfhHeader.bfReserved2 = 0;
	bfhHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + GetBmpInfoSize();

	file.Write((void*)&bfhHeader,sizeof(BITMAPFILEHEADER));
	file.Write((void*)m_pBmpInfo,GetBmpInfoSize());

	file.WriteHuge((void*)m_pPixels,GetBmpDataSize());

	return true;

}

int CGraphDIB::GetBmpDataSize() const
{

	if(m_hBmp != NULL)
	{
		BITMAP bmp;
	    ::GetObject(m_hBmp,sizeof(BITMAP),&bmp);
	    return bmp.bmWidthBytes*bmp.bmHeight;
	}
	else
		return 0;

}

CGraphDIB::CGraphDIB(const CGraphDIB &s)
{
	if(s.m_hBmp==NULL)
	{
		m_hBmp     = NULL;
		m_pBmpInfo = NULL;
		m_pPixels  = NULL;
		return;
	}

	int nBmpInfoLen = s.GetBmpInfoSize();
	m_pBmpInfo  = (LPBITMAPINFO)new BYTE[nBmpInfoLen];                //创建信息头
	memcpy(m_pBmpInfo,s.m_pBmpInfo,nBmpInfoLen);                    
	m_hBmp = CreateDIBSection(NULL,m_pBmpInfo,DIB_RGB_COLORS,(void**)&m_pPixels,NULL,0);
	memcpy(m_pPixels,s.m_pPixels,s.GetBmpDataSize());
	
	m_rectBound = s.m_rectBound;

}



int CGraphDIB::GetPalEntries()
{
	if(m_pBmpInfo==NULL)
		return 0;

	
	int dwClrUsed = m_pBmpInfo->bmiHeader.biClrUsed;
	if (dwClrUsed != 0)
		return (WORD)dwClrUsed;

	int nbitCount = m_pBmpInfo->bmiHeader.biBitCount;
	int nPalEntries = 0;
	if(nbitCount<=8)
		nPalEntries = 1<<nbitCount;
	return nPalEntries;
}

void CGraphDIB::Draw(CDC *pDC)
{
	if(m_hBmp == NULL)
		return;

	CDC dcMem;
	dcMem.CreateCompatibleDC(pDC);
	HBITMAP hbmp = (HBITMAP)dcMem.SelectObject(m_hBmp);

	int nHeight = Height();
	int nWidth  = Width();

	CRect rect = m_rectBound;

	pDC->StretchBlt(m_rectBound.left,m_rectBound.top,m_rectBound.Width(),m_rectBound.Height(),&dcMem,0,0,nWidth,nHeight,SRCCOPY);
  	dcMem.SelectObject(hbmp);

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?