gusucode.com > VC 实现的二维小波变换用于图像去噪、压缩等源码程序 > HaffmanDlg.cpp

    // HaffmanDlg.cpp : implementation file
//

#include "stdafx.h"
#include "小波变换.h"
#include "HaffmanDlg.h"
#include "math.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CHaffmanDlg dialog


CHaffmanDlg::CHaffmanDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHaffmanDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHaffmanDlg)
	m_avgcodelen = 0.0;
	m_efficiency = 0.0;
	m_entropy = 0.0;
	m_compressionrate = 0.0;
	//}}AFX_DATA_INIT
}


void CHaffmanDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHaffmanDlg)
	DDX_Control(pDX, IDC_LISTHUFFMAN, m_listhuffman);
	DDX_Text(pDX, IDC_EDITAVGCODELEN, m_avgcodelen);
	DDX_Text(pDX, IDC_EDITEFFICIENCY, m_efficiency);
	DDX_Text(pDX, IDC_EDITENTROPY, m_entropy);
	DDX_Text(pDX, IDC_EDITCOMPRESSIONRATE, m_compressionrate);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CHaffmanDlg, CDialog)
	//{{AFX_MSG_MAP(CHaffmanDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHaffmanDlg message handlers

BOOL CHaffmanDlg::OnInitDialog() 
{
	CString	str;
	LONG	i,j,k;	
	double	fT;
	// ListCtrl的ITEM
	LV_ITEM lvitem;
	// 中间变量,保存ListCtrl中添加的ITEM编号
	int		iActualItem;
	// 调用默认得OnInitDialog()函数
	CDialog::OnInitDialog();
	// 初始化变量
	m_entropy = 0.0;
	m_avgcodelen = 0.0;	
	// 计算图像熵
	for (i = 0; i < m_iColorNum; i ++)
	{		
		if (m_fFreq[i] > 0)// 判断概率是否大于0
		{
			m_entropy -= m_fFreq[i] * log(m_fFreq[i]) / log(2.0);
		}
	}	
	double*	fTemp;// 保存计算中间结果的数组	
	int	*	iMap;// 保存映射关系的数组	
	// 分配内存
	fTemp = new double[m_iColorNum];
	iMap  = new int[m_iColorNum];	
	// 设置List控件样式
	m_listhuffman.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);	
	// 给List控件添加Header
	m_listhuffman.InsertColumn(0, "灰度值", LVCFMT_CENTER, 60, 0);
	m_listhuffman.InsertColumn(1, "出现频率", LVCFMT_CENTER, 80, 0);
	m_listhuffman.InsertColumn(2, "哈夫曼编码", LVCFMT_CENTER, 150, 1);
	m_listhuffman.InsertColumn(3, "码字长度", LVCFMT_CENTER, 80, 2);	
	// 设置样式为文本
	lvitem.mask = LVIF_TEXT;	
	// 初始化fTemp为m_fFreq
	m_strCode = new CString[m_iColorNum];
	for (i = 0; i < m_iColorNum; i ++)
	{
		fTemp[i] = m_fFreq[i];
		iMap[i] = i;
	}
	// 用冒泡法对进行灰度值出现的概率排序,结果保存在数组fTemp中
	for (j = 0; j < m_iColorNum - 1; j ++)
	{
		for (i = 0; i < m_iColorNum - j - 1; i ++)
		{
			if (fTemp[i] > fTemp[i + 1])
			{
				// 互换
				fT = fTemp[i];
				fTemp[i] = fTemp[i + 1];
				fTemp[i + 1] = fT;				
				// 更新映射关系
				for (k = 0; k < m_iColorNum; k ++)
				{					
					if (iMap[k] == i)// 判断是否是fTemp[i]的子节点
					{						
						iMap[k] = i + 1;// 改变映射到节点i+1
					}
					else if (iMap[k] == i + 1)
					{					
						iMap[k] = i;	// 改变映射到节点i
					}
				}
			}
		}
	}
	// 计算哈夫曼编码表	
	// 找到概率大于0处才开始编码
	for (i = 0; i < m_iColorNum - 1; i ++)
	{	
		if (fTemp[i] > 0)	// 判断概率是否大于0
		{
			break;
		}
	}	
	// 开始编码
	for (; i < m_iColorNum - 1; i ++)
	{
		// 更新m_strCode
		for (k = 0; k < m_iColorNum; k ++)
		{			
			if (iMap[k] == i)// 判断是否是fTemp[i]的子节点
			{				
				m_strCode[k] = "1" + m_strCode[k];// 改变编码字符串
			}
			else if (iMap[k] == i + 1)
			{
				m_strCode[k] = "0" + m_strCode[k];// 改变编码字符串
			}
		}		
		fTemp[i + 1] += fTemp[i];	// 概率最小的两个概率相加,保存在fTemp[i + 1]中	
		// 改变映射关系
		for (k = 0; k < m_iColorNum; k ++)
		{			
			if (iMap[k] == i)// 判断是否是fTemp[i]的子节点
			{				
				iMap[k] = i + 1;// 改变映射到节点i+1
			}
		}		
		// 重新排序
		for (j = i + 1; j < m_iColorNum - 1; j ++)
		{
			if (fTemp[j] > fTemp[j + 1])
			{
				// 互换
				fT = fTemp[j];
				fTemp[j] = fTemp[j + 1];
				fTemp[j + 1] = fT;				
				// 更新映射关系
				for (k = 0; k < m_iColorNum; k ++)
				{					
					if (iMap[k] == j)// 判断是否是fTemp[i]的子节点
					{					
						iMap[k] = j + 1;// 改变映射到节点j+1
					}
					else if (iMap[k] == j + 1)
					{					
						iMap[k] = j;// 改变映射到节点j
					}
				}
			}
			else
			{				
				break;// 退出循环
			}
		}
	}
	// 计算平均码字长度
	for (i = 0; i < m_iColorNum; i ++)
	{	
		m_avgcodelen += m_fFreq[i] * m_strCode[i].GetLength();	// 累加
	}	
	m_efficiency = m_entropy / m_avgcodelen;	// 计算编码效率	
	m_compressionrate=m_avgcodelen/8.0;
	//////////////////////////////////////////////////////////
	// 输出计算结果	
	// 计算平均码字长度
	for (i = 0; i < m_iColorNum; i ++)
	{
		// 添加一项
		lvitem.iItem = m_listhuffman.GetItemCount();
		str.Format("%u",i);
		lvitem.iSubItem = 0;
		lvitem.pszText= (LPTSTR)(LPCTSTR)str;
		iActualItem = m_listhuffman.InsertItem(&lvitem);		
		// 添加其它列
		lvitem.iItem = iActualItem;		
		// 添加灰度值出现的频率
		lvitem.iSubItem = 1;
		str.Format("%f",m_fFreq[i]);
		lvitem.pszText = (LPTSTR)(LPCTSTR)str;
		m_listhuffman.SetItem(&lvitem);		
		// 添加哈夫曼编码
		lvitem.iSubItem = 2;
		lvitem.pszText = (LPTSTR)(LPCTSTR)m_strCode[i];
		m_listhuffman.SetItem(&lvitem);	
		// 添加码字长度
		lvitem.iSubItem = 3;
		str.Format("%u",m_strCode[i].GetLength());
		lvitem.pszText = (LPTSTR)(LPCTSTR)str;
		m_listhuffman.SetItem(&lvitem);
	}		
	UpdateData(FALSE);	// 保存变动	
	delete fTemp;
	delete iMap;
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}