本程序运用到了OpenCv库,采用2.47版本。、
本程序中也充分运用到了MFC框架下的两个坐标系:屏幕坐标系和客户区坐标系。
本程序利用MFC画图技术+OpenCv技术实现功能:
1、通过文件对话框,利用OpenCv将图片加载并刷新到MFC Picture控件上。
根据OpenCv载入图片数据得到MFC BitMapInfo 位图信息。
LPBITMAPINFO CDrawAndOpenCVDlg::CtreateMapInfo(IplImage* workImg)
{
BITMAPINFOHEADER BIH={40,1,1,1,8,0,0,0,0,0,0};
LPBITMAPINFO lpBmi;
int wid, hei, bits, colors,i;
RGBQUAD ColorTab[256];
wid =workImg->width;
//正负不对将导致图片颠倒
hei =(workImg->origin == 0) ? -workImg->height:workImg->height;
bits=workImg->depth*workImg->nChannels;
if (bits>8) colors=0;
else colors = 1<int nsize = sizeof(BITMAPINFO);
lpBmi=(LPBITMAPINFO) malloc(40+4*colors);
BIH.biWidth =wid; BIH.biHeight =hei;
BIH.biBitCount=(BYTE) bits;
memcpy(&lpBmi->bmiHeader, &BIH, 40); // 复制位图信息头
if (bits==8) { // 256 色位图
for (i=0;i<256;i++) { // 设置灰阶调色板
ColorTab[i].rgbRed=ColorTab[i].rgbGreen=ColorTab[i].rgbBlue=(BYTE) i;
}
memcpy(lpBmi->bmiColors, ColorTab, 1024);
}
return(lpBmi);
}
利用OpenCv载入图片并将其显示到Picture控件上,其中img为IplImage*,已经载入。
BOOL CDrawAndOpenCVDlg::displayImage()
{
CDC* pDC = mPictureStatic.GetDC();
CRect rect;
mPictureStatic.GetClientRect(rect);
HDC hDC = pDC->GetSafeHdc();
LPBITMAPINFO bitmap = CtreateMapInfo(img);
::SetStretchBltMode (hDC, STRETCH_DELETESCANS);
::StretchDIBits(hDC , rect.left , rect.top , rect.Width() , rect.Height(),
0 , 0 , img->width , img->height, img->imageData ,
bitmap,DIB_RGB_COLORS,SRCCOPY);
ReleaseDC(pDC);
pDC = NULL;
delete bitmap;
bitmap = NULL;
return TRUE;
}
2、实现对Picture控件进行动态画图,本实时加载到图片数据上进行显示。
动态绘图主要处理三个鼠标消息响应:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
在OnMouseMove中主要处理:
CPoint p1 = mPoint1;
CPoint p2 = mPoint2;
CDC *pDC = mPictureStatic.GetDC();
pDC->SetROP2(R2_XORPEN); //这是关键,先去反色
pDC->SelectObject(mMFCPen);
CBrush *newBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
pDC->SelectObject(newBrush);
switch(drawType) {
case 1: //画线
{
pDC->MoveTo(p1);
pDC->LineTo(p2); //将上次画的线反色再画
p2 = mPoint2 = point;
pDC->MoveTo(p1);
pDC->LineTo(p2); //画本次线
ReleaseDC(pDC);
break;
}
case 2:
{
CRect rect(p1, p2);
pDC->Rectangle(rect);
p2 = mPoint2 = point;
if(p1.x > p2.x){
long x = p1.x;
p1.x = p2.x;
p2.x = x;
}
if(p1.y > p2.y){
long y = p1.y;
p1.y = p2.y;
p2.y = y;
}
rect.SetRect(p1, p2);
pDC->Rectangle(rect);
break;
}
}
newBrush->DeleteObject();
ReleaseDC(pDC);
OpenCv绘图主要有两个函数:
void CDrawAndOpenCVDlg::drawLineToImage()
{
CRect rect;
mPictureStatic.GetClientRect(rect);
CvPoint cvPo1, cvPo2;
cvPo1.x = mPoint1.x * img->width / rect.Width();
cvPo1.y = mPoint1.y * img->height / rect.Height();
cvPo2.x = mPoint2.x * img->width / rect.Width();
cvPo2.y = mPoint2.y * img->height / rect.Height();
int tempWidth = lineWidth * img->width / rect.Width();
cvLine(img, cvPo1, cvPo2, mCvScaler, tempWidth);
displayImage();
}
void CDrawAndOpenCVDlg::drawRectToImage()
{
if(mPoint1.x > mPoint2.x){
long x = mPoint1.x;
mPoint1.x = mPoint2.x;
mPoint2.x = x;
}
if(mPoint1.y > mPoint2.y){
long y = mPoint1.y;
mPoint1.y = mPoint2.y;
mPoint2.y = y;
}
CRect rectPicStatic;
CvPoint cvPo1, cvPo2;
mPictureStatic.GetClientRect(rectPicStatic);
cvPo1.x = mPoint1.x * img->width / rectPicStatic.Width();
cvPo1.y = mPoint1.y * img->height / rectPicStatic.Height();
cvPo2.x = mPoint2.x * img->width / rectPicStatic.Width();
cvPo2.y = mPoint2.y * img->height / rectPicStatic.Height();
int tempWidth = lineWidth * img->width / rectPicStatic.Width();
cvRectangle(img, cvPo1, cvPo2, mCvScaler, tempWidth);
displayImage();
}
3、可实现对画图颜色和线宽的选择,画图方式有矩形和线。颜色选择主要在void OnLButtonDown(UINT nFlags, CPoint point);中处理:
ClientToScreen(&point); //将对话框客户区坐标point转换为屏幕坐标
CRect rect;
mColourStatic.GetWindowRect(rect); //得到屏幕坐标系下的mColourStatic矩形坐标
if(rect.PtInRect(point)){
CColorDialog m_setClrDlg;
// CC_RGBINIT可以让上次选择的颜色作为初始颜色显示出来
m_setClrDlg.m_cc.Flags |= CC_FULLOPEN|CC_RGBINIT;
m_setClrDlg.m_cc.rgbResult = mMFCColor; //记录上次选择的颜色
if(IDOK ==m_setClrDlg.DoModal())
mMFCColor = m_setClrDlg.m_cc.rgbResult; // 保存用户选择的颜色
fillColourStatic();
mMFCPen.DeleteObject();
mCvScaler.val[0] = GetBValue(mMFCColor);
mCvScaler.val[1] = GetGValue(mMFCColor);
mCvScaler.val[2] = GetRValue(mMFCColor);
lineWidth = mLineWidthBox.GetCurLineWidth();
mMFCPen.CreatePen(PS_SOLID, lineWidth,
RGB(GetRValue(mMFCColor), GetGValue(mMFCColor), GetBValue(mMFCColor)));
}
4、可将最终画的图片进行本地保存,在画图过程还可以进行还原,全部删除前面所画图形。
下载地址:http://download.csdn.net/detail/qq_20828983/9609281
程序效果: