LZW词典编码
LZW编码算法的步骤如下:
步骤1:将词典初始化为包含所有可能的单字符,当前前缀P初始化为空。
步骤2:当前字符C=字符流中的下一个字符。
步骤3:判断P+C是否在词典中
(1)如果“是”,则用C扩展P,即让P=P+C,返回到步骤2。
(2)如果“否”,则输出与当前前缀P相对应的码字W;将P+C添加到词典中;令P=C,并返回到步骤2
LZW解码算法如下:
步骤1:在开始译码时词典包含所有可能的前缀根。
步骤2:令CW:=码字流中的第一个码字。
步骤3:输出当前缀-符串string.CW到码字流。
步骤4:先前码字PW:=当前码字CW。
步骤5:当前码字CW:=码字流的下一个码字。
步骤6:判断当前缀-符串string.CW 是否在词典中。
(1)如果”是”,则把当前缀-符串string.CW输出到字符流。
当前前缀P:=先前缀-符串string.PW。
当前字符C:=当前前缀-符串string.CW的第一个字符。
把缀-符串P+C添加到词典。
(2)如果”否”,则当前前缀P:=先前缀-符串string.PW。
当前字符C:=当前缀-符串string.CW的第一个字符。
输出缀-符串P+C到字符流,然后把它添加到词典中。
步骤7:判断码字流中是否还有码字要译。
(1)如果”是”,就返回步骤4。
(2)如果”否”,结束。
将所给的.c文件中的内容,都复制到.cpp文件中。
编码
void LZWEncode( FILE *fp, BITFILE *bf)
{
int character;
int string_code;
int index;
unsigned long file_length;
fseek( fp, 0, SEEK_END);//指针指向文件尾
file_length = ftell( fp);//计算文件长度
fseek( fp, 0, SEEK_SET);//指针重新指向文件开头
BitsOutput( bf, file_length, 4*8);//写文件长度
InitDictionary();//初始化词典
string_code = -1;
while( EOF!=(character=fgetc( fp)))//往后读一个字符
{
index = InDictionary( character, string_code);//判断是否在字典中
if( 0<=index)// string+character in dictionary
{
string_code = index;
}
else// string+character not in dictionary
{
output( bf, string_code);//输出string_code
if( MAX_CODE > next_code)// free space in dictionary
{
// add string+character to dictionary
AddToDictionary( character, string_code);
}
string_code = character;//string的编码
}
}
output( bf, string_code);
}
解码
void LZWDecode( BITFILE *bf, FILE *fp)
{
int character;
int new_code, last_code;
int phrase_length;
unsigned long file_length;
file_length = BitsInput( bf, 4*8);
if( -1 == file_length)
file_length = 0;
InitDictionary();
last_code = -1;//同编码
while( 0<file_length)//未没读到文件末尾
{
new_code = input( bf);
if( new_code >= next_code)// 不在字典里,需要解码this is the case CSCSC( not in dict)
{
d_stack[0] = character;
phrase_length = DecodeString( 1, last_code);
}
else
{
phrase_length = DecodeString( 0, new_code);
}
character = d_stack[phrase_length-1];
while( 0<phrase_length)
{
phrase_length --;
fputc( d_stack[ phrase_length], fp);
file_length--;
}
if( MAX_CODE>next_code)// add the new phrase to dictionary
{
AddToDictionary( character, last_code);
}
last_code = new_code;
}
}
bitio.c文件中涉及vs中fopen不安全,要求替换成fopen_s
解决方案:项目 =》属性 =》c/c++ =》预处理器=》点击预处理器定义,编辑,加入_CRT_SECURE_NO_WARNINGS,即可。
命令参数的设置
argv[1][0]是“E”或者“D”。E代表编码,D代表解码,argv[2]为输入文件,argv[3]为输出文件。
结果
各个文件格式压缩率比较
文本类文件基本能压缩,图片类文件基本不能压缩,视频、音频类文件也基本都能大幅压缩
压缩率的表格完成到最后的音频类后,网页崩了,内容消失,没有保存,所以表格略去,其他内容都重写了一遍
上一篇: LZW编码实现(C)
下一篇: LZW字典编码