📄 conversionview.cpp
字号:
// 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 + -