⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ouyangimageview.cpp

📁 软件是用VisualStudio6.0制作而成
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	
	// 锁定DIB
	lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
	
	// 找到DIB图像象素起始位置
	lpDIBBits = ::FindDIBBits(lpDIB);
	
	// 获取当前DIB颜色数目
	iColorNum = ::DIBNumColors(lpDIB);
	
	// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图,其它的可以类推)
	if (iColorNum != 256)
	{
		// 提示用户
		MessageBox("目前只支持256色位图哈夫曼编码!", "系统提示" , 
			MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
		
		// 返回
		return;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	/******************************************************************************
	// 开始计算各个灰度级出现的频率	
	//
	// 如果需要对其它序列进行哈夫曼编码,只需改动此处即可,例如,直接赋值:
	   iColorNum = 8;
	   fFreq = new FLOAT[iColorNum];
	   fFreq[0] = 0.04;
	   fFreq[1] = 0.05;
	   fFreq[2] = 0.06;
	   fFreq[3] = 0.07;
	   fFreq[4] = 0.10;
	   fFreq[5] = 0.10;
	   fFreq[6] = 0.18;
	   fFreq[7] = 0.40;
	// 这样就可以对指定的序列进行哈夫曼编码
	******************************************************************************/
	
	// 分配内存
	fFreq = new FLOAT[iColorNum];
	
	// 计算DIB宽度
	lWidth = ::DIBWidth(lpDIB);
	
	// 计算DIB高度
	lHeight = ::DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	lLineBytes = WIDTHBYTES(lWidth * 8);
	
	// 重置计数为0
	for (i = 0; i < iColorNum; i ++)
	{
		// 清零
		fFreq[i] = 0.0;
	}
	
	// 计算各个灰度值的计数(对于非256色位图,此处给数组fFreq赋值方法将不同)
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lWidth; j ++)
		{
			// 指向图像指针

			lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;	
			// 指向图像指针			
			// 计数加1
			fFreq[*(lpSrc)] += 1;
		}
	}
	
	// 计算图像象素总数
	lCountSum = lHeight * lWidth;
	
	// 计算各个灰度值出现的概率
	for (i = 0; i < iColorNum; i ++)
	{
		// 计算概率
		fFreq[i] /= (FLOAT)lCountSum;
	}
	
	// 计算各个灰度级出现的频率结束
	/*****************************************************************************/
	
	// 创建对话框
	CDlgHuffman dlgPara;
	
	// 初始化变量值
	dlgPara.m_fFreq = fFreq;
	dlgPara.m_iColorNum = iColorNum;
	m_iColorNum=iColorNum ;
//	CString Huffmans=(LPCSTR)(dlgPara.m_strCode);
//	m_strCode=&Huffmans;
//	m_strCode=dlgPara.m_strCode ;
	// 显示对话框
	dlgPara.DoModal();
	
	CString	str;
				
	// 保存计算中间结果的数组
	FLOAT *	fTemp;
	
	// 保存映射关系的数组
	int	*	iMap;
	
	// 分配内存
	fTemp = new FLOAT[m_iColorNum];
	iMap  = new int[m_iColorNum];
	FLOAT fT;
	// 初始化fTemp为m_fFreq
	for (i = 0; i < m_iColorNum; i ++)
	{
		// 赋值
		fTemp[i] = 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 ++)
				{
					// 判断是否是fTemp[i]的子节点
					if (iMap[k] == i)
					{
						// 改变映射到节点i+1
						iMap[k] = i + 1;
					}
					else if (iMap[k] == i + 1)
					{
						// 改变映射到节点i
						iMap[k] = i;
					}
				}
			}
		}
	}
	
	//////////////////////////////////////////////////////////
	// 计算哈夫曼编码表
	
	// 找到概率大于0处才开始编码
	for (i = 0; i < m_iColorNum - 1; i ++)
	{
		// 判断概率是否大于0
		if (fTemp[i] > 0)
		{
			break;
		}
	}
	
	// 开始编码
	for (; i < m_iColorNum - 1; i ++)
	{
		// 更新m_strCode
		for (k = 0; k < m_iColorNum; k ++)
		{
			// 判断是否是fTemp[i]的子节点
			if (iMap[k] == 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 + 1] += fTemp[i];
		
		// 改变映射关系
		for (k = 0; k < m_iColorNum; k ++)
		{
			// 判断是否是fTemp[i]的子节点
			if (iMap[k] == i)
			{
				// 改变映射到节点i+1
				iMap[k] = 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 ++)
				{
					// 判断是否是fTemp[i]的子节点
					if (iMap[k] == j)
					{
						// 改变映射到节点j+1
						iMap[k] = j + 1;
					}
					else if (iMap[k] == j + 1)
					{
						// 改变映射到节点j
						iMap[k] = j;
					}
				}
			}
			else
			{
				// 退出循环
				break;
			}
		}
	}

//	for (i=0;i<m_iColorNum;i++)
//	{
//		m_strCode[i]=(LPTSTR)(LPCTSTR)m_strCode[i];
//	}

	// 解除锁定
	::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());

	// 恢复光标
	EndWaitCursor();
}

void COuyangImageView::OnHumanGen() 
{
	// 获取文档
	COuyangImageDoc* pDoc = GetDocument();

    CFileDialog fileDlg(FALSE, "*.HUF", "*.HUF", NULL, "HUFFMAN File (*.HUF)|*.HUF||", this);
	fileDlg.m_ofn.Flags |= OFN_FILEMUSTEXIST;
	fileDlg.m_ofn.lpstrTitle = "File to save as";
	// 保存压缩图象
	if (fileDlg.DoModal() == IDOK)
	{	
		// 指向源图像象素的指针
		unsigned char *	lpSrc;
		
		// 指向DIB的指针
		LPSTR	lpDIB;
		
		// 指向DIB象素指针
		LPSTR   lpDIBBits;
		
		// DIB的高度
		LONG	lHeight;
		
		// DIB的宽度
		LONG	lWidth;
		
		// 图像每行的字节数
		LONG	lLineBytes;
		
		// 图像象素总数
		LONG	lCountSum;
		
		// 循环变量
		LONG	i;
		LONG	j;
		LONG	k;
		
		// 保存各个灰度值频率的数组指针
		FLOAT * fFreq;
		
		// 获取当前DIB颜色数目
		int		iColorNum;
		
		// 锁定DIB
		lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
		
		// 找到DIB图像象素起始位置
		lpDIBBits = ::FindDIBBits(lpDIB);
		
		// 获取当前DIB颜色数目
		iColorNum = ::DIBNumColors(lpDIB);
		
		// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图,其它的可以类推)
		if (iColorNum != 256)
		{
			// 提示用户
			MessageBox("目前只支持256色位图哈夫曼编码!", "系统提示" , 
				MB_ICONINFORMATION | MB_OK);
			
			// 解除锁定
			::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
			
			// 返回
			return;
		}
		
		// 更改光标形状
		BeginWaitCursor();
		
		/******************************************************************************
		// 开始计算各个灰度级出现的频率	
		//
		// 如果需要对其它序列进行哈夫曼编码,只需改动此处即可,例如,直接赋值:
		   iColorNum = 8;
		   fFreq = new FLOAT[iColorNum];
		   fFreq[0] = 0.04;
		   fFreq[1] = 0.05;
		   fFreq[2] = 0.06;
		   fFreq[3] = 0.07;
		   fFreq[4] = 0.10;
		   fFreq[5] = 0.10;
		   fFreq[6] = 0.18;
		   fFreq[7] = 0.40;
		// 这样就可以对指定的序列进行哈夫曼编码
		******************************************************************************/
		
		// 分配内存
		fFreq = new FLOAT[iColorNum];
		
		// 计算DIB宽度
		lWidth = ::DIBWidth(lpDIB);
		
		// 计算DIB高度
		lHeight = ::DIBHeight(lpDIB);
		
		// 计算图像每行的字节数
		lLineBytes = WIDTHBYTES(lWidth * 8);
		
		// 重置计数为0
		for (i = 0; i < iColorNum; i ++)
		{
			// 清零
			fFreq[i] = 0.0;
		}
		
		// 计算各个灰度值的计数(对于非256色位图,此处给数组fFreq赋值方法将不同)
		for (i = 0; i < lHeight; i ++)
		{
			for (j = 0; j < lWidth; j ++)
			{
				// 指向图像指针

				lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;	
				// 指向图像指针			
				// 计数加1
				fFreq[*(lpSrc)] += 1;
			}
		}
		
		// 计算图像象素总数
		lCountSum = lHeight * lWidth;
		
		// 计算各个灰度值出现的概率
		for (i = 0; i < iColorNum; i ++)
		{
			// 计算概率
			fFreq[i] /= (FLOAT)lCountSum;
		}
		
		// 计算各个灰度级出现的频率结束
		/*****************************************************************************/
		
		// 创建对话框
		CDlgHuffman dlgPara;
		
		// 初始化变量值
		dlgPara.m_fFreq = fFreq;
		dlgPara.m_iColorNum = iColorNum;
		m_iColorNum=iColorNum ;
		// 显示对话框
	//	dlgPara.DoModal();
		
		CString	str;
					
		// 保存计算中间结果的数组
		FLOAT *	fTemp;
		
		// 保存映射关系的数组
		int	*	iMap;
		
		// 分配内存
		fTemp = new FLOAT[m_iColorNum];
		iMap  = new int[m_iColorNum];
		FLOAT fT;
		// 初始化fTemp为m_fFreq
		for (i = 0; i < m_iColorNum; i ++)
		{
			// 赋值
			fTemp[i] = 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 ++)
					{
						// 判断是否是fTemp[i]的子节点
						if (iMap[k] == i)
						{
							// 改变映射到节点i+1
							iMap[k] = i + 1;
						}
						else if (iMap[k] == i + 1)
						{
							// 改变映射到节点i
							iMap[k] = i;
						}
					}
				}
			}
		}
		
		//////////////////////////////////////////////////////////
		// 计算哈夫曼编码表
		
		// 找到概率大于0处才开始编码
		for (i = 0; i < m_iColorNum - 1; i ++)
		{
			// 判断概率是否大于0
			if (fTemp[i] > 0)
			{
				break;
			}
		}
		
		// 开始编码
		for (; i < m_iColorNum - 1; i ++)
		{
			// 更新m_strCode
			for (k = 0; k < m_iColorNum; k ++)
			{
				// 判断是否是fTemp[i]的子节点
				if (iMap[k] == 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 + 1] += fTemp[i];
			
			// 改变映射关系
			for (k = 0; k < m_iColorNum; k ++)
			{
				// 判断是否是fTemp[i]的子节点
				if (iMap[k] == i)
				{
					// 改变映射到节点i+1
					iMap[k] = 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 ++)
					{
						// 判断是否是fTemp[i]的子节点
						if (iMap[k] == j)
						{
							// 改变映射到节点j+1
							iMap[k] = j + 1;
						}
						else if (iMap[k] == j + 1)
						{
							// 改变映射到节点j
							iMap[k] = j;
						}
					}
				}
				else
				{
					// 退出循环
					break;
				}
			}
		}

		CFileException fe;
		CFile file;
		CString strPath(fileDlg.GetPathName());

		file.Open(strPath, CFile::modeCreate | CFile::modeReadWrite);
	//	file.Write(m_strCode,sizeof(m_strCode));
		// 保存编码后的数据 
		int loop = 0;
		unsigned char Mask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
		CString strTemp = "";
		unsigned char T = 0;
		for (i = 0; i < lHeight; i ++)
		{
			for (j = 0; j < lWidth; j ++)
			{	

				unsigned char V = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
				strTemp += m_strCode[V];
				int len = strTemp.GetLength();
				if(len >= 8)
				{
					for (k = 0; k < 8; k++)
					{
						if (strTemp.Mid(k, 1) == "1")
							T |= Mask[k];
					}
					file.Write(&T, 1);
					loop++;
					T = 0;
					strTemp = strTemp.Right(strTemp.GetLength() - 8);
				}
				else
				{
				}				
			}
		}

		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());

		// 恢复光标
		EndWaitCursor();

		CString strMsg;
		strMsg = "成功创建压缩文件:try.huff ";
		
		// 提示出错
		MessageBox(strMsg, "系统提示", MB_ICONINFORMATION | MB_OK);	
	}
	
}

void COuyangImageView::OnPointSml() 
{

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -