我用的是一本vc数字图像处理的huffman压缩代码,但是不能实现压缩,压缩出来的文件大小和原来的没有差别,大家帮帮忙,给我个能压缩的代码或者帮我看看下面这段代码是哪里错了,实在搞不懂
/*************************************************************************
*
* 函数名称:
* Huffman()
*
* 参数:
* HDIB hDIB - 待编码DIB句柄
* CString strPath - 要装载的文件路径
*
* 返回值:
* BOOL - 成功返回True,否则返回False。
*
* 说明:
* 该函数对指定DIB位图进行编码
*
*************************************************************************/BOOL CCoding::Huffman(HDIB hDIB, CString strPath)
{
// 循环变量
LONG i;
LONG j;
LONG k; // 灰度计数
int nNs[256]; // 灰度概率分布
float fPs[256]; // 映射关系
int iMap[256];
// Huffman编码
CString m_strCode [256]; // 变量初始化
memset(nNs, 0, sizeof(nNs)); // 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
CString strTemp2;
strTemp2.Format("the pixelformat is = %d",m_clsDIB.DIBBitCount(lpDIB));
MessageBox(strTemp2,"sp",MB_OK); // 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
CString strTemp1;
strTemp1.Format("the lpDIBBits = %d",*lpDIBBits);
MessageBox(strTemp1,"sp",MB_OK);
//MessageBox("the lpDIBBits = "+strTmp.Format("%d", *lpDIBBits),"sp",MB_OK);
//MessageBox("the pixelformat is = "+strTmp.Format("%d", m_clsDIB.DIBBitCount(lpDIB)),"sp",MB_OK);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return FALSE;
}
// 更改光标形状
BeginWaitCursor(); //////////////////////////////////////////////////////////
// 计算灰度概率分布
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB); // 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
//
// 对各像素进行灰度分布统计
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
// 对各像素进行灰度统计
unsigned char V = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
nNs[V]++;
}
} // 计算灰度分布密度
for(i = 0; i < 256; i++)
fPs[i] = nNs[i] / (lHeight * lLineBytes * 1.0f); // 初始化
for (i = 0; i < 256; i ++)
iMap[i] = i;
//////////////////////////////////////////////////////////
// 用冒泡法对fPs[]进行排序 for (j = 0; j < 256 - 1; j ++)
{
for (i = 0; i < 256 - j - 1; i ++)
{
if (fPs[i] > fPs[i + 1])
{
// 互换
float fTemp = fPs[i];
fPs[i] = fPs[i + 1];
fPs[i + 1] = fTemp;
// 更新映射关系
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[i]的子节点
if (iMap[k] == i)
{
// 映射到节点i+1
iMap[k] = i + 1;
}
else if (iMap[k] == i + 1)
{
// 映射到节点i
iMap[k] = i;
}
}
}
}
}
//////////////////////////////////////////////////////////
// 计算哈夫曼编码表
for (i = 0; i < 256 - 1; i ++)
{
// 寻找第一个不为0的概率灰度级
if (fPs[i] > 0)
break;
}
// 开始编码
for (i = i; i < 256 - 1; i ++)
{
// 更新m_strCode
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[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];
}
// 概率最小的两个概率相加,结果保存到fPs[i + 1]
fPs[i + 1] += fPs[i];
// 改变映射关系
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[i]的子节点
if (iMap[k] == i)
{
// 映射到节点i+1
iMap[k] = i + 1;
}
}
// 重新排序
for (j = i + 1; j < 256 - 1; j ++)
{
if (fPs[j] > fPs[j + 1])
{
// 互换
float fTemp = fPs[j];
fPs[j] = fPs[j + 1];
fPs[j + 1] = fTemp;
// 更新映射关系
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[i]的子节点
if (iMap[k] == j)
{
// 映射到节点j+1
iMap[k] = j + 1;
}
else if (iMap[k] == j + 1)
{
// 映射到节点j
iMap[k] = j;
}
}
}
else
{
// 退出循环
break;
}
}
} //////////////////////////////////////////////////////////
// 对DIB进行编码压缩
// 位掩码
unsigned char Mask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
CString strTemp = ""; // 打开文件
CFile file;
file.Open(strPath, CFile::modeCreate | CFile::modeReadWrite); // 对各像素进行编码
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
unsigned char V = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
strTemp += m_strCode[V];
CString strTemp2;
strTemp2.Format("the strTemp's content is "+strTemp);
MessageBox(strTemp2,"sp",MB_OK);
int len = strTemp.GetLength();
int loop = 0;
// 保存编码后的数据
do{
unsigned char T = 0;
for (k = 0; k < min(8, strTemp.GetLength()); k++)
{
if (strTemp.Mid(k, 1) == "1")
T |= Mask[k];
}
file.Write(&T, 1);
loop++;
len -= 8;
if (strTemp.GetLength() < 8)
break;
else
strTemp = strTemp.Right(strTemp.GetLength() - 8);
}while (len >= 8);
}
}
// 关闭文件
file.Close(); // 解除锁定
::GlobalUnlock((HGLOBAL) hDIB); // 恢复光标
EndWaitCursor(); // 返回TRUE
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* Huffman()
*
* 参数:
* HDIB hDIB - 待编码DIB句柄
* CString strPath - 要装载的文件路径
*
* 返回值:
* BOOL - 成功返回True,否则返回False。
*
* 说明:
* 该函数对指定DIB位图进行编码
*
*************************************************************************/BOOL CCoding::Huffman(HDIB hDIB, CString strPath)
{
// 循环变量
LONG i;
LONG j;
LONG k; // 灰度计数
int nNs[256]; // 灰度概率分布
float fPs[256]; // 映射关系
int iMap[256];
// Huffman编码
CString m_strCode [256]; // 变量初始化
memset(nNs, 0, sizeof(nNs)); // 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
CString strTemp2;
strTemp2.Format("the pixelformat is = %d",m_clsDIB.DIBBitCount(lpDIB));
MessageBox(strTemp2,"sp",MB_OK); // 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
CString strTemp1;
strTemp1.Format("the lpDIBBits = %d",*lpDIBBits);
MessageBox(strTemp1,"sp",MB_OK);
//MessageBox("the lpDIBBits = "+strTmp.Format("%d", *lpDIBBits),"sp",MB_OK);
//MessageBox("the pixelformat is = "+strTmp.Format("%d", m_clsDIB.DIBBitCount(lpDIB)),"sp",MB_OK);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return FALSE;
}
// 更改光标形状
BeginWaitCursor(); //////////////////////////////////////////////////////////
// 计算灰度概率分布
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB); // 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
//
// 对各像素进行灰度分布统计
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
// 对各像素进行灰度统计
unsigned char V = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
nNs[V]++;
}
} // 计算灰度分布密度
for(i = 0; i < 256; i++)
fPs[i] = nNs[i] / (lHeight * lLineBytes * 1.0f); // 初始化
for (i = 0; i < 256; i ++)
iMap[i] = i;
//////////////////////////////////////////////////////////
// 用冒泡法对fPs[]进行排序 for (j = 0; j < 256 - 1; j ++)
{
for (i = 0; i < 256 - j - 1; i ++)
{
if (fPs[i] > fPs[i + 1])
{
// 互换
float fTemp = fPs[i];
fPs[i] = fPs[i + 1];
fPs[i + 1] = fTemp;
// 更新映射关系
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[i]的子节点
if (iMap[k] == i)
{
// 映射到节点i+1
iMap[k] = i + 1;
}
else if (iMap[k] == i + 1)
{
// 映射到节点i
iMap[k] = i;
}
}
}
}
}
//////////////////////////////////////////////////////////
// 计算哈夫曼编码表
for (i = 0; i < 256 - 1; i ++)
{
// 寻找第一个不为0的概率灰度级
if (fPs[i] > 0)
break;
}
// 开始编码
for (i = i; i < 256 - 1; i ++)
{
// 更新m_strCode
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[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];
}
// 概率最小的两个概率相加,结果保存到fPs[i + 1]
fPs[i + 1] += fPs[i];
// 改变映射关系
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[i]的子节点
if (iMap[k] == i)
{
// 映射到节点i+1
iMap[k] = i + 1;
}
}
// 重新排序
for (j = i + 1; j < 256 - 1; j ++)
{
if (fPs[j] > fPs[j + 1])
{
// 互换
float fTemp = fPs[j];
fPs[j] = fPs[j + 1];
fPs[j + 1] = fTemp;
// 更新映射关系
for (k = 0; k < 256; k ++)
{
// 判断是否是fPs[i]的子节点
if (iMap[k] == j)
{
// 映射到节点j+1
iMap[k] = j + 1;
}
else if (iMap[k] == j + 1)
{
// 映射到节点j
iMap[k] = j;
}
}
}
else
{
// 退出循环
break;
}
}
} //////////////////////////////////////////////////////////
// 对DIB进行编码压缩
// 位掩码
unsigned char Mask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
CString strTemp = ""; // 打开文件
CFile file;
file.Open(strPath, CFile::modeCreate | CFile::modeReadWrite); // 对各像素进行编码
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
unsigned char V = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
strTemp += m_strCode[V];
CString strTemp2;
strTemp2.Format("the strTemp's content is "+strTemp);
MessageBox(strTemp2,"sp",MB_OK);
int len = strTemp.GetLength();
int loop = 0;
// 保存编码后的数据
do{
unsigned char T = 0;
for (k = 0; k < min(8, strTemp.GetLength()); k++)
{
if (strTemp.Mid(k, 1) == "1")
T |= Mask[k];
}
file.Write(&T, 1);
loop++;
len -= 8;
if (strTemp.GetLength() < 8)
break;
else
strTemp = strTemp.Right(strTemp.GetLength() - 8);
}while (len >= 8);
}
}
// 关闭文件
file.Close(); // 解除锁定
::GlobalUnlock((HGLOBAL) hDIB); // 恢复光标
EndWaitCursor(); // 返回TRUE
return TRUE;
}
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货