文章目录
一. 实验名称
LZW编解码算法实现与分析
二. 实验目的
掌握词典编码的基本原理,用c语言编程实现LZW编码器,并分析编码原理。
三. 实验要求
-
首先调试LZW的编码程序,以一个文本文件作为输入,得到输出的LZW编码文件。
-
以实验步骤一得到的编码文件作为输入,编写LZW的解码程序。在写解码程序时需要对关键语句加上注释,并说明进行何操作。在实验报告中重点说明当前码字在词典中不存在时应如何处理并解释原因。
-
选择至少十种不同格式类型的文件,使用LZW编码器进行压缩得到输出的压缩比特流文件。对各种不同格式的文件进行压缩效率的分析。
四. 实验原理
1.主函数
代码
int main(int argc, char** argv) {
FILE* fp;
BITFILE* bf;
if (argc<4) {
fprintf(stdout, "usage: \n%s <o> <ifile> <ofile>\n", argv[0]);
fprintf(stdout, "\t<o>: E or D reffers encode or decode\n");
fprintf(stdout, "\t<ifile>: input file name\n");
fprintf(stdout, "\t<ofile>: output file name\n");
return -1;
}
if ('E' == argv[1][0]) {
//打开输入文件
fp = fopen(argv[2], "rb");
//创建输出文件
bf = OpenBitFileOutput(argv[3]);
if (NULL != fp && NULL != bf) {
LZWEncode(fp, bf);
PrintDictionary();
fclose(fp);
CloseBitFileOutput(bf);
fprintf(stdout, "encoding done\n");
}
}
else if ('D' == argv[1][0]) {
//创建输出文件
bf = OpenBitFileInput(argv[2]);
//打开解压文件
fp = fopen(argv[3], "wb");
if (NULL != fp && NULL != bf) {
LZWDecode(bf, fp);
PrintDictionary();
fclose(fp);
CloseBitFileInput(bf);
fprintf(stdout, "decoding done\n");
}
}
else {
fprintf(stderr, "not supported operation\n");
}
return 0;
}
2.编码原理和实现算法
原理
- 代号替代词条:LZW的编码思想是不断地从字符流中提取新的字符串,通俗地理解为新“词条”,然后用代号也就是码字表示这个词条。这样一来,对字符流的编码就变成了用码字去替换字符流,生成码字流,从而达到压缩数据的目的。
- 动态生成词典,新词条=旧词条+新字符:LZW编码是围绕称为词典的转换表来完成的。LZW编码器通过管理这个词典完成输入与输出之间的转换。
- 输入字符流输出码字流:LZW编码器的输入是字符流,字符流可以是用8位ASCII字符组成的字符串,而输出是用n位(例如12位)表示的码字流。
过程
代码
- 输入:字符流fp
- 输出:码字流bf
void LZWEncode(FILE* fp, BITFILE* bf) {
int character; //C
int string_code;//P
int index; //词典中的索引值
unsigned long file_length;
fseek(fp, 0, SEEK_END); //fp指针定位到文末
file_length = ftell(fp);//获取输入文件长度
fseek(fp, 0, SEEK_SET); //fp指针从新定位到开头
BitsOutput(bf, file_length, 4 * 8);//输出的二进制文件
InitDictionary(); //初始化词典
string_code = -1; //当前前缀p置空
// 当前字符c=字符流中fp的下一个字符
while (EOF != (character = fgetc(fp)))
{
//判断是否在字典当中,若在词典中返回索引值,若不在返回-1
index = InDictionary(character, string_code);
// 如果从词典中找到
if