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

📄 conversionview.cpp

📁 图象像素的表示
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// ConversionView.cpp : implementation of the CConversionView class
//

#include "stdafx.h"
#include "Conversion.h"

#include "ConversionDoc.h"
#include "ConversionView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CConversionView

IMPLEMENT_DYNCREATE(CConversionView, CView)

BEGIN_MESSAGE_MAP(CConversionView, CView)
	//{{AFX_MSG_MAP(CConversionView)
	ON_WM_CREATE()
	ON_COMMAND(ID_btnOpenBmp, OnbtnOpenBmp)
	ON_COMMAND(ID_btn_Mosaic, OnbtnMosaic)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_DESTROY()
	ON_COMMAND(ID_btnBlur, OnbtnBlur)
	ON_UPDATE_COMMAND_UI(ID_btnBlur, OnUpdatebtnBlur)
	ON_COMMAND(ID_btnContour, OnbtnContour)
	ON_UPDATE_COMMAND_UI(ID_btnContour, OnUpdatebtnContour)
	ON_COMMAND(ID_btnContrast, OnbtnContrast)
	ON_UPDATE_COMMAND_UI(ID_btnContrast, OnUpdatebtnContrast)
	ON_COMMAND(ID_btnGray, OnbtnGray)
	ON_UPDATE_COMMAND_UI(ID_btnGray, OnUpdatebtnGray)
	ON_COMMAND(ID_btnLuminosity, OnbtnLuminosity)
	ON_UPDATE_COMMAND_UI(ID_btnLuminosity, OnUpdatebtnLuminosity)
	ON_UPDATE_COMMAND_UI(ID_btnMosaic, OnUpdatebtnMosaic)
	ON_COMMAND(ID_btnUndo, OnbtnUndo)
	ON_UPDATE_COMMAND_UI(ID_btnUndo, OnUpdatebtnUndo)
	ON_COMMAND(ID_btnWave, OnbtnWave)
	ON_UPDATE_COMMAND_UI(ID_btnWave, OnUpdatebtnWave)
	ON_COMMAND(ID_btnWhtBlk, OnbtnWhtBlk)
	ON_UPDATE_COMMAND_UI(ID_btnWhtBlk, OnUpdatebtnWhtBlk)
	ON_COMMAND(ID_btnRedo, OnbtnRedo)
	ON_UPDATE_COMMAND_UI(ID_btnRedo, OnUpdatebtnRedo)
	ON_COMMAND(ID_btnMosaic, OnbtnMosaic)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CConversionView construction/destruction

CConversionView::CConversionView()
{
	m_pDC=NULL;
	pFrameBuff=NULL;
	pBuff=NULL;
}

CConversionView::~CConversionView()
{
}

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

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CConversionView drawing

void CConversionView::OnDraw(CDC* pDC)
{
	CConversionDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	//显示位图
	//
	if(pFrameBuff)
	{
		DrawBitmap(pFrameBuff,0,0,m_pDC);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CConversionView diagnostics

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

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

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

/////////////////////////////////////////////////////////////////////////////
// CConversionView message handlers

//////////////////////////////////////////////
//位图文件读取函数:打开、构造与缓冲含有手写字
//符的位图文件。
//
void CConversionView::ReadBitmap()
{
	#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B') //"BM"

	CFile f;
	CFileException e;
	BITMAPFILEHEADER bmfHead;
	BITMAPINFOHEADER bmHead;
	DWORD rdBytes,svBytes,nPixel;
	UINT nEntries;
	UINT nScan,tmp;
	BYTE *pTemp=NULL,*pRGBQUARD=NULL;
	int i,j;
	DWORD index;
	BYTE iRGB,OneByte;
	LONG lOffset;
	CString pFileName;
	
	//通过文件对话框获取有效的文件名
	//
	pFileName=CString("");
	CFileDialog fDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, "bitmap Files (*.bmp)||",NULL );
	if((fDlg.DoModal())!=IDOK)
	{
		return;
	}

	pFileName=fDlg.GetPathName ();
	if(!pFileName)
	{
		return;
	}
	
	//打开位图文件
	//	
	if(!f.Open(pFileName, CFile::modeRead, &e ))//
	{
		MessageBox("Error occuring!","File operating .",MB_OK);
		exit(0);
	}
	
	//读取位图文件并构造显示数据:关于解压算法可参见位图文件
	//的有关存储格式介绍。
	//
	f.Read (&bmfHead,sizeof(BITMAPFILEHEADER));
	
	if(bmfHead.bfType!=DIB_HEADER_MARKER)
	{
		MessageBox("File is not BMP!",NULL,MB_OK);
		return;
	}
	f.Seek(14,CFile::begin);
	f.Read (&bmHead,sizeof(BITMAPINFOHEADER));
	if(bmHead.biCompression)
	{
		MessageBox("cannot open this compressed file!",NULL,MB_OK);
		return;
	}

	//从堆中分配逐象素缓冲所需要容量的内存
	//
	tmp=bmHead.biWidth*bmHead.biBitCount;
	nScan=tmp%32?(tmp/32*4+(tmp%32+32)/32*4):tmp/8;
	rdBytes=nScan*bmHead.biHeight ;	
	svBytes=bmHead.biWidth*bmHead.biHeight;
	pTemp=new BYTE[rdBytes];
	if(pBuff)
		delete pBuff;
	pBuff=new _MYBITMAP[svBytes];
	if(!pBuff||!pTemp)
	{
		MessageBox("Cannot allocate memory","Memory allocate",MB_OK);
		exit(0);
	}

	//读取数据
	//
	lOffset=bmfHead.bfOffBits;
	f.Seek (lOffset,CFile::begin);
	f.Read (pTemp,rdBytes);

	if(bmHead.biBitCount<24)
	{
		nEntries=Pow2(bmHead.biBitCount); 
		pRGBQUARD=new BYTE[nEntries*4];
		f.Seek (54l,CFile::begin);
		f.Read (pRGBQUARD,nEntries*4);
	}
	f.Close();

	//进行数据构造
	//
	switch(bmHead.biBitCount)
	{
	case 1:nPixel=0;
		for(i=bmHead.biHeight-1;i>=0;i--)
			for(index=i*nScan,j=0;j<bmHead.biWidth;j++)
				{
					OneByte=pTemp[index+j/8];
					iRGB=(OneByte&Pow2(7-j%8))?1:0;
					pBuff[nPixel++].clrRGBA =RGB(pRGBQUARD[iRGB*4+2],pRGBQUARD[iRGB*4+1],pRGBQUARD[iRGB*4]);
				}
			break;
		case 4:nPixel=0;
			for(i=bmHead.biHeight-1;i>=0;i--)
				for(index=i*nScan,j=0;j<bmHead.biWidth;j++)
				{
					OneByte=pTemp[index+j*4/8];
					iRGB=j%2?OneByte&0x0f:OneByte>>4;
					pBuff[nPixel++].clrRGBA =RGB(pRGBQUARD[iRGB*4+2],pRGBQUARD[iRGB*4+1],pRGBQUARD[iRGB*4]);
				}
			break;
		case 8:nPixel=0;
			for(i=bmHead.biHeight-1;i>=0;i--)
				for(index=i*nScan,j=0;j<bmHead.biWidth;j++)
				{
					OneByte=pTemp[index+j];
					iRGB=OneByte;
					pBuff[nPixel++].clrRGBA =RGB(pRGBQUARD[iRGB*4+2],pRGBQUARD[iRGB*4+1],pRGBQUARD[iRGB*4]);
				}
				break;
		case 24:nPixel=0;
			for(i=bmHead.biHeight-1;i>=0;i--)
				for(index=i*nScan,j=0;j<bmHead.biWidth;j++)
				{
					pBuff[nPixel++].clrRGBA =RGB(pTemp[index+2],pTemp[index+1],pTemp[index]);
					index+=3;
				}
				break;
		default:
			MessageBox("File not supported.",NULL,MB_OK);
			delete pBuff;
			pBuff=NULL;
			return;
	}

	//保存变量状态及释放临时资源
	//
	biWidth=bmHead.biWidth;
	biHeight=bmHead.biHeight;
	if(pTemp)
		delete pTemp;
	if(pRGBQUARD)
		delete pRGBQUARD;

}

//////////////////////////////////////////////////////////////////////////////
//位图显示函数:在屏幕上某个位置逐象素显示位图。
//
void CConversionView::DrawBitmap(MYBITMAP *pBmp, int x0, int y0, CClientDC *dc)
{
	int x,y;
	UINT i,j;
	DWORD index;
	RECT rect;
	UINT wUpper,hUpper;

	if(!pBmp)
	{
		MessageBox("请先打开位图文件!","位图显示",MB_OK);
		return;
	}

	GetClientRect(&rect);
	wUpper=rect.right>biWidth?biWidth:rect.right ;
	hUpper=rect.bottom >biHeight?biHeight:rect.bottom ;

	//逐象素显示位图
	//
	y=y0;
	dc->SetROP2 (R2_COPYPEN);
	if(pBmp)
		for(i=0;i<hUpper;i++,y++)
			for(x=x0,j=0;j<wUpper;j++,x++)
			{
				index=i*biWidth+j;
				dc->SetPixel (x,y,pBmp[index].clrRGBA);
			}
}

//////////////////////////////////
//幂函数:计算2的x次幂
//
DWORD CConversionView::Pow2(UINT x)
{
	DWORD dwProduct;
	UINT i;

	for(dwProduct=1,i=1;i<=x;i++)
		dwProduct*=2;
	return dwProduct;
}

////////////////////////////////////
//初始化函数:初始化状态变量。
//
void CConversionView::Init()
{
	m_pDC = new CClientDC(this);
	
	//没有指定进行图像变换的区域
	//
	selRect.right =-1;
	bSelect=FALSE;
	opStatus=sInitialized;
	UnRedo=sUndetermined;
}

int CConversionView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// 初始化调用
	//
	Init();

	return 0;
}

/////////////////////////////////////////
//位图打开按钮消息函数:读取位图、复制缓冲等。
//
void CConversionView::OnbtnOpenBmp() 
{
	ReadBitmap();

	if(pFrameBuff)
		delete pFrameBuff;
	pFrameBuff=NULL;
	if(pBuff)
	{
		pFrameBuff=new _MYBITMAP[biWidth*biHeight];
		if(!pFrameBuff)
		{
			MessageBox("不能分配足够的内存!","内存分配",MB_OK);
			exit(0);
		}
		CopyBitmap(pBuff,pFrameBuff);
	}
	
	selRect.right =-1;
	bSelect=FALSE;
	opStatus=sInitialized;
	UnRedo=sUndetermined;
}

///////////////////////////////////////////////////////
//马赛克按钮消息函数:将前次处理结果复制“后台”缓冲区,
//从而不能再对前次操作进行反复,然后对选定区域进行马赛克
//效果处理,并设置相应状态。
//
void CConversionView::OnbtnMosaic() 
{
	CopyBitmap(pFrameBuff,pBuff);
	Mosaic(selRect,8);
	opStatus=sMosaic;
	UnRedo=sUndo;
}

///////////////////////////////////////////////////////
//马赛克按钮更新消息函数:当打开了有效位图文件之后,系统
//自动使按钮处于有效状态,否则处于无效状态。
//
void CConversionView::OnUpdatebtnMosaic(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable (pBuff!=NULL);
	
}

///////////////////////////////////////////////////////////////
//鼠标左键按下消息函数:开始通过画矩形指定处理区域的过程。
//
void CConversionView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	RECT rect;
	
	SetCapture();
	GetClientRect(&rect);
	ClientToScreen(&rect);
	ClipCursor(&rect);

	bSelect=TRUE;
	selRect.left=point.x;
	selRect.top =point.y;
	selRect.right =-1;

	CView::OnLButtonDown(nFlags, point);
}

///////////////////////////////////////////////////////////////
//鼠标左键释放消息函数:结束通过画矩形指定处理区域的过程,并调
//整矩形结构各成员的值,以保证其值与字段变量的含义一致。
//
void CConversionView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	int left,top,bottom,right;

	//调整矩形结构各成员的值,以保证其值与字段变量的含义一致
	//
	if(bSelect)
	{
		if(selRect.left >selRect.right )
		{
			left=selRect.right ;
			right=selRect.left ;
		}
		else
		{
			left=selRect.left ;
			right=selRect.right ;
		}

		if(selRect.top >selRect.bottom )
		{
			top=selRect.bottom ;
			bottom=selRect.top ;

⌨️ 快捷键说明

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