39. {
40. fread(&red,sizeof(char),1,fpo);
41. IntRed=int(red);
42. sumRedHD=sumRedHD+IntRed;
43. if( IntRed>=0 && IntRed<256 ) Red[IntRed]++; //像素0-255之间
44.
45. fread(&green,sizeof(char),1,fpo);
46. IntGreen=int(green);
47. sumGreenHD=sumGreenHD+IntGreen;
48. if( IntGreen>=0 && IntGreen<256 ) Green[IntGreen]++;
49.
50. fread(&blue,sizeof(char),1,fpo);
51. IntBlue=int(blue);
52. sumBlueHD=sumBlueHD+IntBlue;
53. if( IntBlue>=0 && IntBlue<256 ) Blue[IntBlue]++;
54. }
55. fclose(fpo);
56.
57. //像素:
int型转换为CString型
58. dlg.m_redXS.Format("%d",m_nImage);
59. dlg.m_greenXS.Format("%d",m_nImage);
60. dlg.m_blueXS.Format("%d",m_nImage);
61.
62. //平均灰度值:
计算24位bmp图片的灰度值,我是记录RGB中的所有平均值
63. float pinRedHD,pinGreenHD,pinBlueHD;
64. pinRedHD=sumRedHD*3/m_nImage;
65. pinGreenHD=sumGreenHD*3/m_nImage; //平均灰度=总灰度/总像素
66. pinBlueHD=sumBlueHD*3/m_nImage;
67.
68. dlg.m_redPJHD.Format("%.2f",pinRedHD);
69. dlg.m_greenPJHD.Format("%.2f",pinGreenHD);
70. dlg.m_bluePJHD.Format("%.2f",pinBlueHD);
71.
72. /****************************************************************/
73. /* 中值灰度:
算法重点(黄凯大神提供)
74. /* 中值灰度:
所有像素中的中位数,应该所有像素排序找到中间的灰度值
75. /* 算法:
num[256]记录各灰度出现次数,sum+=num[i],找到sum=总像素/2
76. /****************************************************************/
77. int sumRedZZHD=0,sumGreenZZHD=0,sumBlueZZHD=0;
78. int redZZHD,greenZZHD,blueZZHD;
79. for(i=0;i<256;i++)
80. {
81. sumRedZZHD=sumRedZZHD+Red[i];
82. if(sumRedZZHD>=m_nImage/6) //m_nImage被分成3份RGB并且sum=总像素/2
83. {
84. redZZHD=i;
85. break;
86. }
87. }
88. for(i=0;i<256;i++)
89. {
90. sumGreenZZHD=sumGreenZZHD+Green[i];
91. if(sumGreenZZHD>=m_nImage/6) //m_nImage被分成3份RGB并且sum=总像素/2
92. {
93. greenZZHD=i;
94. break;
95. }
96. }
97. for(i=0;i<256;i++)
98. {
99. sumBlueZZHD=sumBlueZZHD+Blue[i];
100. if(sumBlueZZHD>=m_nImage/6) //m_nImage被分成3份RGB并且sum=总像素/2
101. {
102. blueZZHD=i;
103. break;
104. }
105. }
106.
107. dlg.m_redZZHD.Format("%d",redZZHD);
108. dlg.m_greenZZHD.Format("%d",greenZZHD);
109. dlg.m_blueZZHD.Format("%d",blueZZHD);
110.
111. /******************************************************************/
112. /*标准差:
标准差=方差的算术平方根
113. /* 方差s^2=[(x1-x)^2+(x2-x)^2+......(xn-x)^2]/n
114. /* 算法:
不用开m_nImage数组进行计算 用num[256]中数进行
115. /* 方差=(平均灰度-i)*(平均灰度-i)*Red[i] 有Red[i]个灰度值为i的数
116. /******************************************************************/
117. float redBZC,greenBZC,blueBZC; //标准差
118. double redFC=0,greenFC=0,blueFC=0; //方差
119. for(i=0;i<256;i++)
120. {
121. redFC=redFC+(pinRedHD-i)*(pinRedHD-i)*Red[i]; //有Red[i]个像素i
122. greenFC=greenFC+(pinGreenHD-i)*(pinGreenHD-i)*Green[i];
123. blueFC=blueFC+(pinBlueHD-i)*(pinBlueHD-i)*Blue[i];
124. }
125.
126. redBZC=sqrt(redFC*3/m_nImage);
127. greenBZC=sqrt(greenFC*3/m_nImage);
128. blueBZC=sqrt(blueFC*3/m_nImage);
129.
130. dlg.m_redBZC.Format("%.2lf",redBZC);
131. dlg.m_greenBZC.Format("%.2lf",greenBZC);
132. dlg.m_blueBZC.Format("%.2lf",blueBZC);
133.
134. //重点必须添加该语句才能弹出对话框
135. if(dlg.DoModal()==IDOK)
136. {
137.
138. }
139.}
第五步:
此时运行结果如下图所示,打开图片可以显示参数。
2.建立对话框与View联系并绘制直方图
重点(极其重要*)
(1)如何在MFC中(View中)实现对子对话框的画图或直方图响应?
解决方法:
在子对话框中.cpp文件中实现画图响应,不要再View.cpp中实现,否则图像会以menu背景为坐标,而在ImageZFTDlg.cpp中建立OnPaint函数实现画图,它默认会以子对话框为标准。
(2)如何把View.cpp中的图片像素直方图信息传递给子对话框ImageZFTDlg.cpp呢?
解决方法:
如果自定义ImageStruct.h中建立全局变量,每个.cpp中引用该头文件调用总是报错(未知),所以我在View.h中建立一个全局变量intRed[256];再在子文件.cpp中函数里调用该全局变量即可externintRed[256],这是非常重要的一个C语言知识。
(3)画图函数OnPaint()参考源代码中详细注释。
如何绘制坐标轴、文字、图像,其实自己绘制而没调用第三方库还是挺有意思的。
第一步:
建立画直方图函数OnPaint
打开类向导(Ctrl+W),类名选择CImageZFTDlg,IDs选择CImageZFTDlg,在Message函数中建立WM_PAINT映射,默认函数名为OnPaint建立函数voidCImageZFTDlg:
:
OnPaint()
第二步:
绘制直方图大致思想如下
(1)重点:
获取要绘制直方图的位置和图像资源的对应号ID(IDC_STATIC_KJ框架),我当时认为绘制直方图只能绘制到”图像“控件IDC中,不能是对话框IDD。
CWnd*pWnd=GetDlgItem(IDC_STATIC_KJ);
CDC*pDC=pWnd->GetDC();
(2)获取对话框矩形的长和宽
CRectrectpic;
GetDlgItem(IDC_STATIC_KJ)->GetWindowRect(&rectpic);
(3)创建画笔对象并对画笔进行颜色设置
CPen*RedPen=newCPen();
RedPen->CreatePen(PS_SOLID,1RGB(255,0,0));
(4)选中当前画笔并保存以前画笔
CGdiObject*RedOlderPen=pDC->SelectObject(RedPen);
(5)绘制直方图(图像坐标自己算)
矩形pDC->Rectangle(9,327,312,468);
移动pDC->MoveTo(15,331);
直线pDC->LineTo(15,488);
文字pDC->TextOut(15+48*i,450,str);
(6)恢复以前画笔
pDC->SelectObject(RedOlderPen);
deleteRedPen;
ReleaseDC(pDC);
第三步:
源代码与详细注释思想
在ImageZFTDlg.cpp中修改OnPaint函数:
[cpp] viewplain copy
1.//****************绘制原图直方图*********************//
2.void CImageZFTDlg:
:
OnPaint()
3.{
4. CPaintDC dc(this); // device context for painting
5.
6. // TODO:
Add your message handler code here
7.
8. /********************************************************************************/
9. /* 重点知识:
(XX)
10. /* 如何在View.cpp中把一个变量的值传给其它对话框
11. /*
12. /* 错误一:
在View.h中定义的pubic变量只能在View.cpp中用
13. /* 错误二:
定义一个Struct.h中存全局变量,在2个函数中分别调用#include "Struct.h"
14. /*