题目是老师布置的一道作业题,要求用C或C++完成,但不能用VTK/Opencv等软件包,经过很多摸索之后实现了该功能,后续可能还有其他功能要实现,所以先写一篇博客记录下,一方面是方便自己以后使用,另一方面是给其他人做个参考,少走一些弯路。说不定以后学弟学妹们就看到了这篇博客(猜猜我是哪个学校的?)
一、作业要求
要求读取一幅位图图像,即BMP位图,并显示该图像在对话框内。鼠标点击该图像时,显示所点击的像素坐标值和RGB灰度分量。
编译环境:vs
二、实现步骤
(一)创建对话框MFC
选择基于对话框的MFC,其他后面的都是默认选项,所以可以直接点击完成即可。
点击完成之后出现如下对话框
把中间的对话框放大,把确定和取消两个botton修改为打开图片和保存图片,并增加一个图像控件框和五个编辑框,如下图所示
MFC创建就结束了
(二)添加程序
双击打开图片按钮添加程序,如下图所示
添加代码如下:
//打开文件 CString filter = (CString)"图像文件(*.bmp)|*.bmp;*.BMP||";//指明可供选择的文件类型和相应的扩展名CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter, NULL); //打开文件//按下确定按钮 dlg.DoModal() 函数显示对话框if (dlg.DoModal() == IDOK){//打开对话框获取图像信息CString BmpName = dlg.GetPathName();//获取文件路径名 CString EntName = dlg.GetFileExt();//获取文件扩展名EntName.MakeLower(); //将文件扩展名转换为一个小写字符if (pare(_T("bmp")) == 0) //如果是bmp图片则打开显示{//定义变量存储图片信息BITMAPINFO *pBmpInfo; //记录图像信息头内容BYTE *pBmpData; //图像数据BITMAPFILEHEADER bmpHeader; //文件头BITMAPINFOHEADER bmpInfo; //信息头CFile bmpFile; //记录打开文件//以只读的方式打开文件 读取bmp图片各部分 bmp文件头 信息 数据if (!bmpFile.Open(BmpName, CFile::modeRead | CFile::typeBinary))return;if (bmpFile.Read(&bmpHeader, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))return;if (bmpFile.Read(&bmpInfo, sizeof(BITMAPINFOHEADER)) != sizeof(BITMAPINFOHEADER))return;pBmpInfo = (BITMAPINFO *)new char[sizeof(BITMAPINFOHEADER)];//为图像数据申请空间memcpy(pBmpInfo, &bmpInfo, sizeof(BITMAPINFOHEADER)); //存储图像信息头内容DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits;//图像数据大小,单位为字节pBmpData = (BYTE*)new char[dataBytes];bmpFile.Read(pBmpData, dataBytes); //存储图像数据bmpFile.Close();//显示图像CStatic *pwnd = (CStatic*)GetDlgItem(IDC_STATIC); //里面的参数是图片控件的ID//pwnd->SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);pwnd->ModifyStyle(0xf, SS_BITMAP);pwnd->SetBitmap((HBITMAP)::LoadImage(GetModuleHandle(NULL), BmpName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));//打开图片}}
此时已经可以打开图片了,效果如下:
接下来天加显示坐标值和灰度值的代码:
在类向导里添加消息函数WM_LBUTTONDOWN
添加代码:
代码如下:
void CWJ_zuoye1Dlg::OnLButtonDown(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值CRect rect;CWnd *pWnd = GetDlgItem(IDC_STATIC);pWnd->GetWindowRect(&rect);ScreenToClient(&rect);//先获取鼠标相对于屏幕的坐标GetCursorPos(&point);int temp_x = point.x;int temp_y = point.y;//然后得到static控件的rect坐标CRect pRect;pWnd->GetClientRect(&pRect);//最后把当前鼠标的坐标转化为相对于rect的坐标pWnd->ScreenToClient(&point);int x = point.x;int y = point.y;SetDlgItemInt(IDC_EDIT1, x);//写入坐标值SetDlgItemInt(IDC_EDIT2, y);//写入HDC hDC = ::GetDC(NULL);COLORREF rgb = ::GetPixel(hDC, temp_x, temp_y);int r = GetRValue(rgb);int g = GetGValue(rgb);int b = GetBValue(rgb);SetDlgItemInt(IDC_EDIT3, r);//写入SetDlgItemInt(IDC_EDIT4, g);//写入SetDlgItemInt(IDC_EDIT5, b);//写入CDialogEx::OnLButtonDown(nFlags, point);}
编辑运行:
大概就是这么个情况,时间有限,下一篇我将讲一下上面的代码含义以及相关引用 ,对代码含义有要求的同学可以看我的下篇博客