DlgShannon.cpp
上传用户:panpan8800
上传日期:2013-06-29
资源大小:274k
文件大小:7k
源码类别:

图形图像处理

开发平台:

Visual C++

  1. // DlgShannon.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "imageprocessing.h"
  5. #include "DlgCoding.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. // 调用默认得OnInitDialog()函数
  42. CDialog::OnInitDialog();
  43. // 初始化变量
  44. m_dEntropy = 0.0;
  45. m_dAvgCodeLen = 0.0;
  46. // 字符串变量
  47. CString str;
  48. str = "1";
  49. // 循环变量
  50. LONG i;
  51. LONG j;
  52. // 控件ListCtrl的ITEM
  53. LV_ITEM lvItem;
  54. // 保存控件ListCtrl中添加的ITEM编号
  55. int nItem2View;
  56. // 中间变量
  57. double dT;
  58. LONG lTemp;
  59. // 保存计算中间结果的数组
  60. double * dTemp;
  61. dTemp = new double[m_nColorNum];
  62. // 数组用来存放灰度值和其位置之间的映射
  63. LONG * l4Turn;
  64. l4Turn = new LONG[m_nColorNum];
  65. // 当前编码区间的概率和
  66. double dAccum;
  67. dAccum = 1.0;
  68. // 已经编码灰度值概率的统计和
  69. double dSum;
  70. dSum    = 0;
  71. // 已编码灰度值
  72. LONG lCount = 0;
  73. // 起始位置
  74. LONG lBegin;
  75. // 指示编码是否已经完成一段
  76. BOOL * bFinished;
  77. bFinished = new BOOL[m_nColorNum];
  78. // 分配内存
  79. m_strCode = new CString[m_nColorNum];
  80. for (i = 0; i < m_nColorNum; i ++)
  81. {
  82. // 初始化为FALSE
  83. bFinished[i] = FALSE;
  84. // 将概率赋值dTemp数组
  85. dTemp[i] = m_dProba[i];
  86. // 按灰度值大小顺序排列
  87. l4Turn[i] = i;
  88. }
  89. // 用冒泡法对进行灰度值出现的概率排序
  90. // 同时改变灰度值位置的映射关系
  91. for (j = 0; j < m_nColorNum - 1; j ++)
  92. for (i = 0; i < m_nColorNum - j - 1; i ++)
  93. if (dTemp[i] > dTemp[i + 1])
  94. {
  95. // 互换
  96. dT = dTemp[i];
  97. dTemp[i] = dTemp[i + 1];
  98. dTemp[i + 1] = dT;
  99. // 将i和i+1灰度的位置值互换
  100. lTemp = l4Turn[i];
  101. l4Turn[i] = l4Turn[i+1];
  102. l4Turn[i+1] = lTemp;
  103. }
  104. /*******************************************************
  105. 计算香农-弗诺编码表
  106. *******************************************************/
  107. // 从概率大于0处开始编码
  108. for (lBegin = 0; lBegin < m_nColorNum - 1; lBegin ++)
  109. if (dTemp[lBegin] > 0)
  110. break;
  111. // 开始编码
  112. while(lCount < m_nColorNum)
  113. {
  114. // 从概率大于零的灰度值开始编码
  115. lCount = lBegin;
  116. // 对区间进行分割,对每个区间的灰度值编码
  117. for (i = lBegin; i < m_nColorNum; i ++)
  118. {
  119. // 判断是否编码完成
  120. if (bFinished[i] == FALSE)
  121. {
  122. // 增加当前编码区间的概率综合
  123. dSum += dTemp[i];
  124. // 判断是否超出总和的一半
  125. if (dSum > dAccum/2.0)
  126. {
  127. // 超出,追加的字符改为0
  128. str = "0";
  129. }
  130. // 追加字符
  131. m_strCode[l4Turn[i]] = m_strCode[l4Turn[i]] + str;
  132. // 判断是否编码完一段
  133. if (dSum == dAccum)
  134. {
  135. // 完成一部分编码,重新计算dAccum
  136. // 初始化dSum为0
  137. dSum = 0;
  138. // 判断是不是对所有灰度值已经编码一遍
  139. if (i == m_nColorNum - 1)
  140. j = lBegin;
  141. else
  142. j = i + 1;
  143. // 保存j值
  144. lTemp = j;
  145. str = m_strCode[l4Turn[j]];
  146. // 计算下一编码区间的概率总和
  147. dAccum = 0;
  148. for (; j < m_nColorNum; j++)
  149. {
  150. // 判断是否是同一段编码
  151. if ((m_strCode[l4Turn[j]].Right(1) != str.Right(1)) 
  152. || (m_strCode[l4Turn[j]].GetLength() != str.GetLength()))
  153. break;
  154. // 当前区间的概率总和增加
  155. dAccum += dTemp[j];
  156. }
  157. // 码字增加值为1
  158. str = "1";
  159. // 判断该段编码已经完成
  160. if (lTemp + 1 == j)
  161. bFinished[lTemp] = TRUE;
  162. }
  163. }
  164. else
  165. {
  166. //  开始下一轮编码
  167. lCount ++;
  168. // 重新赋2dSum为0
  169. dSum = 0;
  170. // 判断是不是对所有灰度值已经编码一遍
  171. if (i == m_nColorNum - 1)
  172. j = lBegin;
  173. else
  174. j = i + 1;
  175. // 保存j值
  176. lTemp = j;
  177. str = m_strCode[l4Turn[j]];
  178. // 计算下一编码区间的概率总和
  179. dAccum = 0;
  180. for (; j < m_nColorNum; j++)
  181. {
  182. // 判断是否是同一段编码
  183. if ((m_strCode[l4Turn[j]].Right(1) != str.Right(1)) 
  184. || (m_strCode[l4Turn[j]].GetLength() != str.GetLength()))
  185. {
  186. // 退出循环
  187. break;
  188. }
  189. // 累加
  190. dAccum += dTemp[j];
  191. }
  192. str = "1";
  193. // 判断该段编码已经完成
  194. if (lTemp + 1 == j)
  195. bFinished[lTemp] = TRUE;
  196. }
  197. }
  198. }
  199. // 计算图像熵
  200. for (i = 0; i < m_nColorNum; i ++)
  201. {
  202. // 判断概率是否大于0
  203. if (m_dProba[i] > 0)
  204. {
  205. // 计算图像熵
  206. m_dEntropy -= m_dProba[i] * log(m_dProba[i]) / log(2.0);
  207. }
  208. }
  209. // 计算平均码字长度
  210. for (i = 0; i < m_nColorNum; i ++)
  211. {
  212. // 累加
  213. m_dAvgCodeLen += m_dProba[i] * m_strCode[i].GetLength();
  214. }
  215. // 计算编码效率
  216. m_dEfficiency = m_dEntropy / m_dAvgCodeLen;
  217. // 保存变动
  218. UpdateData(FALSE);
  219. /*************************************************
  220. 输出编码结果
  221. *************************************************/
  222. // 设置List控件样式
  223. m_lstTable.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
  224. // 给List控件添加Header
  225. m_lstTable.InsertColumn(0, "灰度值", LVCFMT_LEFT, 60, 0);
  226. m_lstTable.InsertColumn(1, "灰度值概率", LVCFMT_LEFT, 78, 0);
  227. m_lstTable.InsertColumn(2, "香农-弗诺编码", LVCFMT_LEFT, 110, 1);
  228. m_lstTable.InsertColumn(3, "码字长度", LVCFMT_LEFT, 78, 2);
  229. // 设置样式为文本
  230. lvItem.mask = LVIF_TEXT;
  231. // 添加显示
  232. for (i = 0; i < m_nColorNum; i ++)
  233. {
  234. // 第一列显示
  235. lvItem.iItem = m_lstTable.GetItemCount();
  236. str.Format("%u",i);
  237. lvItem.iSubItem = 0;
  238. lvItem.pszText= (LPTSTR)(LPCTSTR)str;
  239. nItem2View = m_lstTable.InsertItem(&lvItem);
  240. // 其它列显示
  241. lvItem.iItem = nItem2View;
  242. // 添加灰度值出现的频率
  243. lvItem.iSubItem = 1;
  244. str.Format("%f",m_dProba[i]);
  245. lvItem.pszText = (LPTSTR)(LPCTSTR)str;
  246. m_lstTable.SetItem(&lvItem);
  247. // 添加香农-弗诺编码
  248. lvItem.iSubItem = 2;
  249. lvItem.pszText = (LPTSTR)(LPCTSTR)m_strCode[i];
  250. m_lstTable.SetItem(&lvItem);
  251. // 添加码字长度
  252. lvItem.iSubItem = 3;
  253. str.Format("%u",m_strCode[i].GetLength());
  254. lvItem.pszText = (LPTSTR)(LPCTSTR)str;
  255. m_lstTable.SetItem(&lvItem);
  256. }
  257. //  内存释放
  258. delete l4Turn;
  259. delete dTemp;
  260. delete bFinished;
  261. return TRUE;
  262. }