⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmpviewerdoc.cpp

📁 本代码实现对BMP格式文件的读取
💻 CPP
字号:
// BMPViewerDoc.cpp : implementation of the CBMPViewerDoc class
//

#include "stdafx.h"
#include "BMPViewer.h"

#include "BMPViewerDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CBMPViewerDoc

IMPLEMENT_DYNCREATE(CBMPViewerDoc, CDocument)

BEGIN_MESSAGE_MAP(CBMPViewerDoc, CDocument)
	//{{AFX_MSG_MAP(CBMPViewerDoc)
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
	ON_COMMAND(ID_Zoomin, OnZoomin)
	ON_COMMAND(ID_Zoomout, OnZoomout)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBMPViewerDoc construction/destruction

CBMPViewerDoc::CBMPViewerDoc()
{
	// TODO: add one-time construction code here
	
}

CBMPViewerDoc::~CBMPViewerDoc()
{
	if (flag==1) {
		//释放内存资源
		HeapFree(GetProcessHeap(),0,pbi);
		HeapFree(GetProcessHeap(),0,lpBuf);
	}
}

BOOL CBMPViewerDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CBMPViewerDoc serialization

void CBMPViewerDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

/////////////////////////////////////////////////////////////////////////////
// CBMPViewerDoc diagnostics

#ifdef _DEBUG
void CBMPViewerDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CBMPViewerDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CBMPViewerDoc commands

BOOL CBMPViewerDoc::PrepareShowdata()
{
	BYTE** image;
	BYTE** originimage;
	int i,j;
	int linewidth;

	if(lpshowbuf!=NULL)
		HeapFree(GetProcessHeap(),0,lpshowbuf);
	if(zoomfactor>=1)
	{//放大
		pbi->bmiHeader.biHeight=bi.biHeight*zoomfactor;
		pbi->bmiHeader.biWidth=bi.biWidth*zoomfactor;
	
		//每行四字节补齐,计算每行字节数:
		linewidth=(pbi->bmiHeader.biWidth*pbi->bmiHeader.biBitCount+31)/32*4;
		
		//计算显示图像所需内存大小
		pbi->bmiHeader.biSizeImage=linewidth*pbi->bmiHeader.biHeight;
		
		//申请内存
		lpshowbuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,pbi->bmiHeader.biSizeImage);
		
		//生成对lpshowbuf的二维数组索引:
		image=new BYTE*[pbi->bmiHeader.biHeight];
		for(i=0;i<pbi->bmiHeader.biHeight;i++)
			image[i]=lpshowbuf+i*linewidth;
		
		originimage=new BYTE*[bi.biHeight];
		for(i=0;i<bi.biHeight;i++)
			originimage[i]=lpBuf+i*bi.biSizeImage/bi.biHeight;

		//赋值
		if(bi.biBitCount<24)
		{
			for(i=0;i<pbi->bmiHeader.biHeight;i++)
			 for(j=0;j<linewidth;j++)
			  image[i][j]=originimage[i/zoomfactor][j/zoomfactor];
		}
		else if(bi.biBitCount==24)
		{//24位真彩色
			for(i=0;i<pbi->bmiHeader.biHeight;i++)
			 for(j=0;j<pbi->bmiHeader.biWidth;j++)
			 {
				image[i][j*3]=originimage[i/zoomfactor][(j/zoomfactor)*3];
				image[i][j*3+1]=originimage[i/zoomfactor][(j/zoomfactor)*3+1];
				image[i][j*3+2]=originimage[i/zoomfactor][(j/zoomfactor)*3+2];
			 }
		}
		else
		{//32位色
			for(i=0;i<pbi->bmiHeader.biHeight;i++)
			 for(j=0;j<pbi->bmiHeader.biWidth;j++)
			 {
				image[i][j*4]=originimage[i/zoomfactor][(j/zoomfactor)*4];
				image[i][j*4+1]=originimage[i/zoomfactor][(j/zoomfactor)*4+1];
				image[i][j*4+2]=originimage[i/zoomfactor][(j/zoomfactor)*4+2];
 				image[i][j*4+3]=originimage[i/zoomfactor][(j/zoomfactor)*4+3];
			 }
		}
	}
	else
	{//缩小
		pbi->bmiHeader.biHeight=bi.biHeight/(-zoomfactor);
		pbi->bmiHeader.biWidth=bi.biWidth/(-zoomfactor);
	
		//每行四字节补齐,计算每行字节数:
		linewidth=(pbi->bmiHeader.biWidth*pbi->bmiHeader.biBitCount+31)/32*4;
		
		//计算显示图像所需内存大小
		pbi->bmiHeader.biSizeImage=linewidth*pbi->bmiHeader.biHeight;
		
		//申请内存
		lpshowbuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,pbi->bmiHeader.biSizeImage);
		
		//生成对lpshowbuf的二维数组索引:
		image=new BYTE*[pbi->bmiHeader.biHeight];
		for(i=0;i<pbi->bmiHeader.biHeight;i++)
			image[i]=lpshowbuf+i*linewidth;
		
		originimage=new BYTE*[bi.biHeight];
		for(i=0;i<bi.biHeight;i++)
			originimage[i]=lpBuf+i*bi.biSizeImage/bi.biHeight;

		//赋值
		if(bi.biBitCount<24)
		{
			for(i=0;i<pbi->bmiHeader.biHeight;i++)
			 for(j=0;j<linewidth;j++)
			  image[i][j]=originimage[i*(-zoomfactor)][j*(-zoomfactor)];
		}
		else if(bi.biBitCount==24)
		{//24位真彩色
			for(i=0;i<pbi->bmiHeader.biHeight;i++)
			 for(j=0;j<pbi->bmiHeader.biWidth;j++)
			 {
				image[i][j*3]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*3];
				image[i][j*3+1]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*3+1];
				image[i][j*3+2]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*3+2];
			 }
		}
		else
		{//32位色
			for(i=0;i<pbi->bmiHeader.biHeight;i++)
			 for(j=0;j<pbi->bmiHeader.biWidth;j++)
			 {
				image[i][j*4]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4];
				image[i][j*4+1]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4+1];
				image[i][j*4+2]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4+2];
				image[i][j*4+3]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4+3];
			 }
		}
	}

	return TRUE;
}

void CBMPViewerDoc::OnFileOpen() 
{
	// TODO: Add your command handler code here
	LPCTSTR lpszFilter="BMP Files(*.bmp)|*.bmp|任何文件|*.*||";
	CFileDialog dlg(TRUE,lpszFilter,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,lpszFilter,NULL);
	CString filename;
	CFile file;
	BITMAPFILEHEADER bf;

	//打开文件对话框
	if(dlg.DoModal()==IDOK)
	{
		filename=dlg.GetPathName();
	    if(file.Open(filename,CFile::modeRead|CFile::shareDenyNone,NULL)==0)
		{	
			//读取文件失败
			AfxMessageBox("无法打开文件!",MB_OK,0);
			return;
		}
		//读取文件头
		file.Read(&bf,sizeof(bf));
		//判断是否是BMP文件
		if(bf.bfType!=0x4d42)//'BM'
		{
			AfxMessageBox("非BMP文件!",MB_OK,0);
			return;
		}
		//判断文件是否损坏
		if(file.GetLength()!=bf.bfSize)
		{
			AfxMessageBox("文件已损坏,请检查!",MB_OK,0);
			return;
		}

		//读文件信息头
		file.Read(&bi,sizeof(bi));
					
		//计算调色板数目
		numQuad=0;
		if(bi.biBitCount<24)
		{
			numQuad=1<<bi.biBitCount;
		}
		
		//为图像信息pbi申请空间
		pbi=(BITMAPINFO*)HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+numQuad*sizeof(RGBQUAD));
		memcpy(pbi,&bi,sizeof(bi));
		quad=(RGBQUAD*)((BYTE*)pbi+sizeof(BITMAPINFOHEADER));
		
		//读取调色板
		if(numQuad!=0)
		{
			file.Read(quad,sizeof(RGBQUAD)*numQuad);
		}
		
		//为图像数据申请空间
		bi.biSizeImage=bf.bfSize-bf.bfOffBits;
		lpBuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,bi.biSizeImage);
		//读取图像数据
		file.Read(lpBuf,bi.biSizeImage);
		
		//图像读取完毕,关闭文件,设置标志
		file.Close();
		flag=1;
		zoomfactor=1;
		lpshowbuf=NULL;
		PrepareShowdata();
		UpdateAllViews(NULL,0,NULL);
	}
}


void CBMPViewerDoc::OnZoomin() 
{
	// TODO: Add your command handler code here
	// 缩小倍数不超过2
	if(zoomfactor>1||zoomfactor<-1)
		zoomfactor--;
	else if(zoomfactor=1)
		zoomfactor=-2;
	PrepareShowdata();
	UpdateAllViews(NULL,0,NULL);
}

void CBMPViewerDoc::OnZoomout() 
{
	// TODO: Add your command handler code here
	// 放大倍数超过2次还原
	if(zoomfactor>=1||zoomfactor<-2)
		zoomfactor++;
	else if(zoomfactor=-2)
		zoomfactor=1;
	PrepareShowdata();
	UpdateAllViews(NULL,0,NULL);
}

⌨️ 快捷键说明

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