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

📄 bmpview.cpp

📁 一个用MFC打开位图的程序
💻 CPP
字号:
// BMPView.cpp : implementation of the CBMPView class
//

#include "stdafx.h"
#include "BMP.h"

#include "BMPDoc.h"
#include "BMPView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CBMPView

IMPLEMENT_DYNCREATE(CBMPView, CView)

BEGIN_MESSAGE_MAP(CBMPView, CView)
	//{{AFX_MSG_MAP(CBMPView)
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBMPView construction/destruction

CBMPView::CBMPView()
{
	// TODO: add construction code here

}

CBMPView::~CBMPView()
{
}

BOOL CBMPView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CBMPView drawing

void CBMPView::OnDraw(CDC* pDC)
{
	CBMPDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	if(filename=="")
	{
		return;
	}

	FILE *fp=fopen(filename,"r");

	BITMAPFILEHEADER fileheader;
	BITMAPINFO info;
	
	fread(&fileheader,sizeof(fileheader),1,fp);

	if(fileheader.bfType!=0x4D42)
	{
		pDC->TextOut(100,200,"无位图文件 请选择位图文件");
		fclose(fp);
		return ;
	}

	fread(&info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
	long width=info.bmiHeader.biWidth;
	long height=info.bmiHeader.biHeight;
	UCHAR *buffer=new UCHAR[info.bmiHeader.biSizeImage];
	fseek(fp,fileheader.bfOffBits,0);
	fread(buffer,info.bmiHeader.biSizeImage,1,fp);

	// 单色图的解析
	if(info.bmiHeader.biBitCount==1)
	{
		int n=0;
		int color[500][500];

		if(height>0)
		{
			//height>0 表示图片颠倒
			for(int i=0; i<height; i++)
				for(int j=0; j<width; j=j+8)
				{
					int k=7;
					while(k>=0)
					{
						color[i][k+j]=buffer[n]%2;
						buffer[n]=buffer[n]/2;
						k--;
					}
					n++;
				}

			for(i=0; i<height; i++)
				for(int j=0; j<width; j++)
				{
					if(color[i][j] == 0)
						pDC->SetPixel(j,height-i,RGB(0,0,0));
					if(color[i][j] == 1)
						pDC->SetPixel(j,height-i,RGB(255,255,255));
				}
		}
		else
		{
			for(int i=0; i<0-height; i++)
				for(int j=0; j<width; j=j+8)
				{
					int k=7;
					while(k>=0)
					{
						color[i][k+j]=buffer[n]%2;
						buffer[n]=buffer[n]/2;
						k--;
					}
					n++;
				}

			for(i=0; i<0-height; i++)
				for(int j=0; j<width; j++)
				{
					if(color[i][j] == 0)
						pDC->SetPixel(j,i,RGB(0,0,0));
					if(color[i][j] == 1)
						pDC->SetPixel(j,i,RGB(255,255,255));
				}
		}
	}

	// 16色图的解析
	if(info.bmiHeader.biBitCount==4)
	{
		int pitch;
		if(width%8==0)
			pitch=width;
		else
			pitch=width+8-width%8;

		RGBQUAD quad[16];
		fseek(fp,fileheader.bfOffBits-sizeof(RGBQUAD)*16,0);
		fread(quad,sizeof(RGBQUAD)*16,1,fp);

		if(height>0)
		{
			//height>0 表示图片颠倒
			for(int i=0; i<height; i++)
				for(int j=0; j<width; j++)
				{
					int index;
					if(j%2==0)
						index = buffer[(i*pitch+j)/2]/16;
				
					if(j%2==1)
						index = buffer[(i*pitch+j)/2]%16;

					UCHAR r=quad[index].rgbRed;
					UCHAR g=quad[index].rgbGreen;
					UCHAR b=quad[index].rgbBlue;
					pDC->SetPixel(j,height-i,RGB(r,g,b));
				}
		}
		else
		{
			for(int i=0; i<0-height; i++)
				for(int j=0; j<width; j++)
				{
					int index;
					if(j%2==0)
						index = buffer[(i*pitch+j)/2]/16;
				
					if(j%2==1)
						index = buffer[(i*pitch+j)/2]%16;

					UCHAR r=quad[index].rgbRed;
					UCHAR g=quad[index].rgbGreen;
					UCHAR b=quad[index].rgbBlue;
					pDC->SetPixel(j,i,RGB(r,g,b));
				}
		}
	}

	// 32色图的解析
	if(info.bmiHeader.biBitCount==8)
	{
		int pitch;
		if(width%4==0)
		{
			pitch=width;
		}
		else
		{
			pitch=width+4-width%4;
		}

		RGBQUAD quad[256];
		fseek(fp,fileheader.bfOffBits-sizeof(RGBQUAD)*256,0);
		fread(quad,sizeof(RGBQUAD)*256,1,fp);

		if(height>0)
		{
			//height>0 表示图片颠倒
			for(int i=0;i<height;i++){
				for(int j=0;j<width;j++){
					int index=buffer[i*pitch+j];
					UCHAR r=quad[index].rgbRed;
					UCHAR g=quad[index].rgbGreen;
					UCHAR b=quad[index].rgbBlue;
					pDC->SetPixel(j,height-i,RGB(r,g,b));
				}
			}
		}
		else
		{
			for(int i=0;i<0-height;i++)
			{
				for(int j=0;j<width;j++)
				{
					int index=buffer[i*pitch+j];
					UCHAR r=quad[index].rgbRed;
					UCHAR g=quad[index].rgbGreen;
					UCHAR b=quad[index].rgbBlue;
					pDC->SetPixel(j,i,RGB(r,g,b));
				}
			}
		}
	}

	// 256色图解析
	if(info.bmiHeader.biBitCount==16)
	{
		int pitch=width+width%2;

		if(height>0)
		{
			//height>0 表示图片颠倒
			if(info.bmiHeader.biCompression==BI_RGB)
			{
				//该模式只有555
				for(int i=0;i<height;i++)
				{
					for(int j=0;j<width;j++)
					{
						// 555 格式
						UCHAR b=buffer[(i*pitch+j)*2]&0x1F;
						UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);
						UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;
						pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));
					}
				}
			}

			if(info.bmiHeader.biCompression==BI_BITFIELDS)
			{
				//该模式在bitmapinfoheader之后存在RGB掩码 每个掩码1 DWORD
				fseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);
				DWORD  rMask;
				fread(&rMask,sizeof(DWORD ),1,fp);
				if(rMask==0x7C00)
				{
					// 5 5 5 格式
					MessageBeep(0);
					for(int i=0;i<height;i++)
					{
						for(int j=0;j<width;j++)
						{
							UCHAR b=buffer[(i*pitch+j)*2]&0x1F;
							UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);
							UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;
							pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));
						}
					}
				}

				if(rMask==0xF800)
				{
					//5 6 5 格式
					for(int i=0;i<height;i++)
					{
						for(int j=0;j<width;j++)
						{
							UCHAR b=buffer[(i*pitch+j)*2]&0x1F;
							UCHAR g=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch+j)*2]>>5);
							UCHAR r=buffer[(i*pitch+j)*2+1]>>3;
							pDC->SetPixel(j,height-i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1F));
						}
					}
				}
			}

		}
		else
		{
			if(info.bmiHeader.biCompression==BI_RGB)
			{
				//该模式只有555
				for(int i=0;i<0-height;i++){
					for(int j=0;j<width;j++){			
						//5 5 5 格式
						UCHAR b=buffer[(i*pitch+j)*2]&0x1F;
						UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);
						UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;
						pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));
					}
				}
			}

			if(info.bmiHeader.biCompression==BI_BITFIELDS)
			{
				//该模式在bitmapinfoheader之后存在RGB掩码 每个掩码1 DWORD
				fseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);
				DWORD  rMask;
				fread(&rMask,sizeof(DWORD ),1,fp);
				if(rMask==0x7C00)
				{
					// 5 5 5 格式
					MessageBeep(0);
					for(int i=0;i<0-height;i++)
					{
						for(int j=0;j<width;j++)
						{
							UCHAR b=buffer[(i*pitch+j)*2]&0x1F;
							UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);
							UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;
							pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));
						}
					}
				}

				if(rMask==0xF800)
				{
					//565 格式
					for(int i=0;i<0-height;i++)
					{
						for(int j=0;j<width;j++)
						{
							UCHAR b=buffer[(i*pitch+j)*2]&0x1F;
							UCHAR g=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch+j)*2]>>5);
							UCHAR r=buffer[(i*pitch+j)*2+1]>>3;
							pDC->SetPixel(j,i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1F));
						}
					}
				}
			}
		}
	}
	
	// 24位图解析
	if(info.bmiHeader.biBitCount==24)
	{
		int pitch=width%4;
		// bgr
		if(height>0){
			//height>0 表示图片颠倒
			for(int i=0;i<height;i++)
			{
				int realPitch=i*pitch;
				for(int j=0;j<width;j++)
				{
					UCHAR b=buffer[(i*width+j)*3+realPitch];
					UCHAR g=buffer[(i*width+j)*3+1+realPitch];
					UCHAR r=buffer[(i*width+j)*3+2+realPitch];
					pDC->SetPixel(j,height-i,RGB(r,g,b));
				}
			}
		}
		else
		{
			for(int i=0;i<0-height;i++)
			{
				int realPitch=i*pitch;
				for(int j=0;j<width;j++)
				{
					UCHAR b=buffer[(i*width+j)*3+realPitch];
					UCHAR g=buffer[(i*width+j)*3+1+realPitch];
					UCHAR r=buffer[(i*width+j)*3+2+realPitch];
					pDC->SetPixel(j,i,RGB(r,g,b));
				}
			}
		}
	}

	// 32位图进行解析
	if(info.bmiHeader.biBitCount==32)
	{
		// bgra
		if(height>0)
		{
			//height>0 表示图片颠倒
			for(int i=0;i<0-height;i++)
			{
				for(int j=0;j<width;j++)
				{
					UCHAR b=buffer[(i*width+j)*4];
					UCHAR g=buffer[(i*width+j)*4+1];
					UCHAR r=buffer[(i*width+j)*4+2];
					pDC->SetPixel(j,height-i,RGB(r,g,b));
				}
			}
		}
		else
		{
			for(int i=0;i<height;i++)
			{
				for(int j=0;j<width;j++)
				{
					UCHAR b=buffer[(i*width+j)*4];
					UCHAR g=buffer[(i*width+j)*4+1];
					UCHAR r=buffer[(i*width+j)*4+2];
					pDC->SetPixel(j,i,RGB(r,g,b));
				}
			}
		}
	}
	

	delete buffer;
	fclose(fp); 
}

/////////////////////////////////////////////////////////////////////////////
// CBMPView printing

BOOL CBMPView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CBMPView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CBMPView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CBMPView diagnostics

#ifdef _DEBUG
void CBMPView::AssertValid() const
{
	CView::AssertValid();
}

void CBMPView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CBMPDoc* CBMPView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CBMPDoc)));
	return (CBMPDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CBMPView message handlers

void CBMPView::OnFileOpen()
{
	// TODO: Add your command handler code here
	CString filter;
	filter = "BMP文件(*.bmp)|*.bmp||";
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, filter);
	if(dlg.DoModal() == IDOK)
	{
		filename = dlg.GetPathName();
		CBMPView::OnInitialUpdate();
	}
}

⌨️ 快捷键说明

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