DlgShannon.cpp
上传用户:gdjinyi
上传日期:2013-02-01
资源大小:1701k
文件大小:7k
源码类别:

源码/资料

开发平台:

Visual C++

  1. // DlgShannon.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "ch1_1.h"
  5. #include "DlgShannon.h"
  6. #include <math.h>
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CDlgShannon dialog
  14. CDlgShannon::CDlgShannon(CWnd* pParent /*=NULL*/)
  15. : CDialog(CDlgShannon::IDD, pParent)
  16. {
  17. //{{AFX_DATA_INIT(CDlgShannon)
  18. m_dEntropy = 0.0;
  19. m_dAvgCodeLen = 0.0;
  20. m_dEfficiency = 0.0;
  21. //}}AFX_DATA_INIT
  22. }
  23. void CDlgShannon::DoDataExchange(CDataExchange* pDX)
  24. {
  25. CDialog::DoDataExchange(pDX);
  26. //{{AFX_DATA_MAP(CDlgShannon)
  27. DDX_Control(pDX, IDC_LST_Table, m_lstTable);
  28. DDX_Text(pDX, IDC_EDIT1, m_dEntropy);
  29. DDX_Text(pDX, IDC_EDIT2, m_dAvgCodeLen);
  30. DDX_Text(pDX, IDC_EDIT3, m_dEfficiency);
  31. //}}AFX_DATA_MAP
  32. }
  33. BEGIN_MESSAGE_MAP(CDlgShannon, CDialog)
  34. //{{AFX_MSG_MAP(CDlgShannon)
  35. //}}AFX_MSG_MAP
  36. END_MESSAGE_MAP()
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CDlgShannon message handlers
  39. BOOL CDlgShannon::OnInitDialog() 
  40. {
  41. // 字符串变量
  42. CString str;
  43. // 循环变量
  44. LONG i;
  45. LONG j;
  46. // 中间变量
  47. FLOAT fT;
  48. LONG iTemp;
  49. // 保存计算中间结果的数组
  50. FLOAT * fTemp;
  51. // 保存映射关系的数组
  52. LONG * iMap;
  53. // 当前编码区间的频率和
  54. FLOAT fTotal;
  55. // 计数(编码完成的个数)
  56. LONG iCount = 0;
  57. // 频率和
  58. FLOAT fSum;
  59. // 起始位置
  60. LONG iStart;
  61. // 指向布尔型数组的指针
  62. BOOL * bFinished;
  63. // 调用默认得OnInitDialog()函数
  64. CDialog::OnInitDialog();
  65. // 初始化变量
  66. m_dEntropy = 0.0;
  67. m_dAvgCodeLen = 0.0;
  68. // 计算图像熵
  69. for (i = 0; i < m_iColorNum; i ++)
  70. {
  71. // 判断概率是否大于0
  72. if (m_fFreq[i] > 0)
  73. {
  74. // 计算图像熵
  75. m_dEntropy -= m_fFreq[i] * log(m_fFreq[i]) / log(2.0);
  76. }
  77. }
  78. // 分配内存
  79. fTemp = new FLOAT[m_iColorNum];
  80. m_strCode = new CString[m_iColorNum];
  81. bFinished = new BOOL[m_iColorNum];
  82. iMap  = new LONG[m_iColorNum];
  83. fTotal = 0;
  84. // 初始化fTemp为m_fFreq, bFinished为FALSE
  85. for (i = 0; i < m_iColorNum; i ++)
  86. {
  87. // 赋值
  88. fTemp[i] = m_fFreq[i];
  89. // 初始化映射关系
  90. iMap[i] = i;
  91. // 初始化为FALSE
  92. bFinished[i] = FALSE;
  93. // 计算fTotal
  94. fTotal += m_fFreq[i];
  95. }
  96. // 用冒泡法对进行灰度值出现的概率排序,结果保存在数组fTemp中
  97. for (j = 0; j < m_iColorNum - 1; j ++)
  98. {
  99. for (i = 0; i < m_iColorNum - j - 1; i ++)
  100. {
  101. if (fTemp[i] > fTemp[i + 1])
  102. {
  103. // 互换
  104. fT = fTemp[i];
  105. fTemp[i] = fTemp[i + 1];
  106. fTemp[i + 1] = fT;
  107. // 更新映射关系
  108. iTemp = iMap[i];
  109. iMap[i] = iMap[i+1];
  110. iMap[i+1] = iTemp;
  111. }
  112. }
  113. }
  114. //////////////////////////////////////////////////////////
  115. // 计算香农-弗诺编码表
  116. // 找到概率大于0处才开始编码
  117. for (iStart = 0; iStart < m_iColorNum - 1; iStart ++)
  118. {
  119. // 判断概率是否大于0
  120. if (fTemp[iStart] > 0)
  121. {
  122. // 跳出
  123. break;
  124. }
  125. }
  126. // 初始化变量
  127. fSum = 0;
  128. str = "1";
  129. // 开始编码
  130. while(iCount < m_iColorNum)
  131. {
  132. // 初始化iCount为iStart
  133. iCount = iStart;
  134. // 循环编码
  135. for (i = iStart; i < m_iColorNum; i ++)
  136. {
  137. // 判断是否编码完成
  138. if (bFinished[i] == FALSE)
  139. {
  140. // 编码没有完成,继续编码
  141. // fSum加当前出现的频率
  142. fSum += fTemp[i];
  143. // 判断是否超出总和的一半
  144. if (fSum > fTotal/2.0)
  145. {
  146. // 超出,追加的字符改为0
  147. str = "0";
  148. }
  149. // 编码追加字符1或0
  150. m_strCode[iMap[i]] += str;
  151. // 判断是否编码完一段
  152. if (fSum == fTotal)
  153. {
  154. // 完成一部分编码,重新计算fTotal
  155. // 初始化fSum为0
  156. fSum = 0;
  157. // 判断是否是最后一个元素
  158. if (i == m_iColorNum - 1)
  159. {
  160. // 是最后,设置从起始点开始
  161. j = iStart;
  162. }
  163. else
  164. {
  165. // 不是最后,设置从下一个点开始
  166. j = i + 1;
  167. }
  168. // 保存j值
  169. iTemp = j;
  170. str = m_strCode[iMap[j]];
  171. // 计算下一段的fTotal
  172. fTotal = 0;
  173. for (; j < m_iColorNum; j++)
  174. {
  175. // 判断是否是同一段编码
  176. if ((m_strCode[iMap[j]].Right(1) != str.Right(1)) 
  177. || (m_strCode[iMap[j]].GetLength() != str.GetLength()))
  178. {
  179. // 退出循环
  180. break;
  181. }
  182. // 累加
  183. fTotal += fTemp[j];
  184. }
  185. // 初始化str为1
  186. str = "1";
  187. // 判断是否该段长度为1
  188. if (iTemp + 1 == j)
  189. {
  190. // 是,表示该段编码已经完成
  191. bFinished[iTemp] = TRUE;
  192. }
  193. }
  194. }
  195. else
  196. {
  197. // iCount加1
  198. iCount ++;
  199. // 计算下一次循环的fTotal
  200. // 初始化fSum为0
  201. fSum = 0;
  202. // 判断是否是最后一个元素
  203. if (i == m_iColorNum - 1)
  204. {
  205. // 是最后,设置从起始点开始
  206. j = iStart;
  207. }
  208. else
  209. {
  210. // 不是最后,设置从下一个点开始
  211. j = i + 1;
  212. }
  213. // 保存j值
  214. iTemp = j;
  215. str = m_strCode[iMap[j]];
  216. // 计算下一段的fTotal
  217. fTotal = 0;
  218. for (; j < m_iColorNum; j++)
  219. {
  220. // 判断是否是同一段编码
  221. if ((m_strCode[iMap[j]].Right(1) != str.Right(1)) 
  222. || (m_strCode[iMap[j]].GetLength() != str.GetLength()))
  223. {
  224. // 退出循环
  225. break;
  226. }
  227. // 累加
  228. fTotal += fTemp[j];
  229. }
  230. // 初始化str为1
  231. str = "1";
  232. // 判断是否该段长度为1
  233. if (iTemp + 1 == j)
  234. {
  235. // 是,表示该段编码已经完成
  236. bFinished[iTemp] = TRUE;
  237. }
  238. }
  239. }
  240. }
  241. // 计算平均码字长度
  242. for (i = 0; i < m_iColorNum; i ++)
  243. {
  244. // 累加
  245. m_dAvgCodeLen += m_fFreq[i] * m_strCode[i].GetLength();
  246. }
  247. // 计算编码效率
  248. m_dEfficiency = m_dEntropy / m_dAvgCodeLen;
  249. // 保存变动
  250. UpdateData(FALSE);
  251. //////////////////////////////////////////////////////////
  252. // 输出计算结果
  253. // ListCtrl的ITEM
  254. LV_ITEM lvitem;
  255. // 中间变量,保存ListCtrl中添加的ITEM编号
  256. int iActualItem;
  257. // 设置List控件样式
  258. m_lstTable.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
  259. // 给List控件添加Header
  260. m_lstTable.InsertColumn(0, "灰度值", LVCFMT_LEFT, 60, 0);
  261. m_lstTable.InsertColumn(1, "出现频率", LVCFMT_LEFT, 78, 0);
  262. m_lstTable.InsertColumn(2, "香农弗诺编码", LVCFMT_LEFT, 110, 1);
  263. m_lstTable.InsertColumn(3, "码字长度", LVCFMT_LEFT, 78, 2);
  264. // 设置样式为文本
  265. lvitem.mask = LVIF_TEXT;
  266. // 计算平均码字长度
  267. for (i = 0; i < m_iColorNum; i ++)
  268. {
  269. // 添加一项
  270. lvitem.iItem = m_lstTable.GetItemCount();
  271. str.Format("%u",i);
  272. lvitem.iSubItem = 0;
  273. lvitem.pszText= (LPTSTR)(LPCTSTR)str;
  274. iActualItem = m_lstTable.InsertItem(&lvitem);
  275. // 添加其它列
  276. lvitem.iItem = iActualItem;
  277. // 添加灰度值出现的频率
  278. lvitem.iSubItem = 1;
  279. str.Format("%f",m_fFreq[i]);
  280. lvitem.pszText = (LPTSTR)(LPCTSTR)str;
  281. m_lstTable.SetItem(&lvitem);
  282. // 添加香农弗诺编码
  283. lvitem.iSubItem = 2;
  284. lvitem.pszText = (LPTSTR)(LPCTSTR)m_strCode[i];
  285. m_lstTable.SetItem(&lvitem);
  286. // 添加码字长度
  287. lvitem.iSubItem = 3;
  288. str.Format("%u",m_strCode[i].GetLength());
  289. lvitem.pszText = (LPTSTR)(LPCTSTR)str;
  290. m_lstTable.SetItem(&lvitem);
  291. }
  292. // 返回TRUE
  293. return TRUE;
  294. }