📄 ouyangimageview.cpp
字号:
// 锁定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 + -