电脑常识【雷老师的图像处理】读入一幅RGB图象,编写程序显示图象中任一象素点的R
1.读入一幅RGB图象,编写程序显示图象中任一象素点的RGB值。
2.利用C++语言编写代码实现。
3.实现彩色图像的显示与RGB值的显示。
实验步骤:
-
搭建VS2019环境
-
安装MFC工具包
-
创建一个工程
-
完成界面布局
-
添加按键响应函数
程序清单1 添加按键按下的响应函数
void CMFCApplication1Dlg::OnBnClickedButtonOpenbmp()
{
// TODO: 在此添加控件通知处理程序代码
//
//打开文件
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 (EntName.Compare(_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();
//显示图像
//guangjie2333的设计
CWnd* pWnd = GetDlgItem(IDC_STATIC_PICTURE); //获得pictrue控件窗口的句柄
CRect rect;
pWnd->GetClientRect(&rect); //获得pictrue控件所在的矩形区域
CDC* pDC = pWnd->GetDC(); //获得pictrue控件的DC
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0, bmpInfo.biWidth, bmpInfo.biHeight, pBmpData, pBmpInfo, DIB_RGB_COLORS, SRCCOPY);
//打印信息
TRACE(" rect.Width() = %d , rect.Height() = %d, bmpInfo.biWidth = %d , bmpInfo.biHeight = %d",rect.Width(), rect.Height(), bmpInfo.biWidth, bmpInfo.biHeight);
X_Scale = bmpInfo.biWidth / rect.Width();
Y_Scale = bmpInfo.biHeight / rect.Height();
}
}
}
- 添加鼠标移动响应函数
程序清单2 添加鼠标移动的响应函数
void CMFCApplication1Dlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//guangjie2333的设计
CDialogEx::OnMouseMove(nFlags, point);
//确保鼠标在图像内移动
if (point.x >= 10 && point.x<=358 && point.y >= 58 && point.y <= 373)
{
TRACE("捕捉到了鼠标移动,当前位置 X = %d Y = %d", point.x, point.y);
SetDlgItemInt(IDC_EDIT_X, point.x); //写入坐标值x
SetDlgItemInt(IDC_EDIT_Y, point.y); //写入坐标值y
CWnd* pWnd = GetDlgItem(IDC_STATIC_PICTURE); //获得pictrue控件窗口的句柄
CDC* pDC = pWnd->GetDC(); //获得pictrue控件的DC
HDC hDC = pDC->GetSafeHdc(); ;
COLORREF rgb = ::GetPixel(hDC, point.x, point.y); //后两个参数是屏幕绝对坐标,如果用相对坐标则获取错误的灰度值
int r = GetRValue(rgb); //获得灰度分量
int g = GetGValue(rgb);
int b = GetBValue(rgb);
SetDlgItemInt(IDC_EDIT_R, r); //写入灰度分量R
SetDlgItemInt(IDC_EDIT_G, g); //写入灰度分量G
SetDlgItemInt(IDC_EDIT_B, b); //写入灰度分量B
}
else
{
SetDlgItemInt(IDC_EDIT_X, 0); //写入坐标值x
SetDlgItemInt(IDC_EDIT_Y, 0); //写入坐标值y
SetDlgItemInt(IDC_EDIT_R, 0); //写入灰度分量R
SetDlgItemInt(IDC_EDIT_G, 0); //写入灰度分量G
SetDlgItemInt(IDC_EDIT_B, 0); //写入灰度分量B
}
}
-
读取bmp图片
-
将鼠标放在图片区域内自动显示坐标和RGB
图1
实验结果:
当把鼠标放在火箭的白色火焰区域
图2
当把鼠标放在左上角蓝天区域
图3
实验分析:
从图2 的结果看出,将鼠标放在图片的白色区域R G B 显示均为255 ,结果正确。
从图3 的结果看出,将鼠标放在图片的蓝色区域R G B 显示均为133 143 181 ,结果中的蓝色分量大于红色分量和绿色分量,结果认为正确。
综上所述,实验取得成功。
感想与心得:
- 通过这次实验熟悉了C++的语法
- 通过这次实验,仅仅花了一个晚上的时间就速成了MFC,对界面设计和人机交互有了更深的理解。
- 通过这次实验,提高了我解决问题的能力,通过上网搜索相关的内容,将他们创造性的为我所用。
- 我与别人的不同点在于我将鼠标放在图片的任何一个位置,无需其他操作,就能显示位置信息和RGB信息。
- 我的界面设计比别人更美观和简洁。
- 实验结束后会把我解决问题的过程上传至csdn供更多人参考。