LZW编解码
有具体实验要求可以私聊定制
实验目的
掌握LZW编译码的原理并利用程序实现LZW算法
实验要求
-
输入:任意的数据文件;输出:压缩后的数据文件
-
输入:压缩后的数据文件;输出:原文件
-
源程序格式清晰,注释简单明了
实验环境
MATLAB
实验原理
概念
LZW通过建立一个字典(code table),把不认识的字符串序列加入字典,当下次再次遇到此种字符串序列时,用字典的索引序号代替此序列。通常字典的容量为4096,所以序号(码字)的长度为12bit,一般“单词”的平均长度远大于12bit,因而可以打到压缩的目的。
压缩过程
- 字典初始化
将所有使用到的单字节单词放入字典中,本实验中采用ASCII码表作为初始字典
- 动态数据初始化
初始化新单词存放位置指针,将它指向字典的第一个空位置,读入被压缩文件的第一个字符,作为待处理的当前单词W的尾字符。当前单词的前缀为空
- 扩充字典,构建编码
如果文件再没有字符,输出当前单词W的序号,编码结束。如果文件中还有字符,把当前单词W(的序号)作为前缀,再从被压缩文件中读取一个字符,作为尾字符,得到一个新单词W1
- 判断新单词
如果字典中已有W1,则将W1看做当前单词W,返回第三步
解码算法
- 字典初始化
将字典前256个位置一次分配给0x00到0xFF这256个单字节单词
- 动态数据初始化
初始化新单词存放位置指针P,将它指向字典第一个位置,读取压缩文件第一个码字,查表译码输出,并记忆码字
- 判断是否截止
如果压缩中已经没有码字,解码结束。否则进入下一个码字
- 判断终止符
如果读入码字为无效码字,即0xFFF,则解码结束,否则进入下一步
- 扩充字典,构建编码
如果在压缩字典中已经有改码字对应的单词,则采用递归算法,输出该单词的内容。并将单词的第一个有效字符作为尾字符,将已经记忆的前一个码字作为前缀,组成一个新单词,写入字典中,然后将当前码字记忆下来,返回第三步。
否则,首先在字典中生成新的单词,然后在输出这个单词,将新单词的码字记忆下来,返回第三步,这使得新单词一定是首尾相同的单词
实验步骤
- 了解LZW编译码过程
- 编写程序
- 输入原始文本并得到LZW编码结果
- 将编码结果带入译码程序中并将结果与原文本进行对比判断程序是否编译成功
程序
程序通过对ASCII码表进行读取构建新的字典,因matlab对.mat格式文件读取速度最快,因此将编码结果保存在LZW.mat文件重,方便译码程序的读取,并将扩展字典输出到新的Excel文件内方便再次查看和检查;译码程序最终将译码结果输出到Ori.txt文件中。
编码
clear
clc
% ABCABDABCAAAABBBABCABCA
Str_input = input('请输入一串字符:\n','s');
N = length(Str_input); % 获得输入字符串长度
% 初始字典为ASCII码表
dic_ori = readtable('ASCII.xlsx')
% 规定输出每个LZW码字格式为3位十六进制数
formatSpec = '%03X';
% 循环走完整个字符串,扩充字典
L = ''; % 初始化上一个
T = ''; % 初始化这一个
dic_ext = dic_ori; % 初始化待扩充字典
Out_bits = ''; % 初始化输出码流
for i=1:N % 循环每一个字符
Len_dic = size(dic_ext,1); % 当前字典长度
T = Str_input(i);
LT = strcat(L,T);
for m=1:Len_dic % 循环判断整个字典是否有当前的LT
if strcmp(LT, dic_ext{m,2})==1
L = LT;
break;
else if m==Len_dic % LT不在当前的字典里
% 更新字典
dic_ext{Len_dic+1,1} = Len_dic;
dic_ext(Len_dic+1,2) = {LT};
dic_ext(Len_dic+1,3) = {num2str(Len_dic, formatSpec)};
% 找到P在字典的位置,并输出相应码流
for n=1:Len_dic % 循环判断整个字典中L当前的位置
if strcmp(L, dic_ext{n,2})==1
Out_bits = strcat(Out_bits, num2str((n- 1), formatSpec));
end
end
% 更新L
L = Str_input(i);
end
end
end
end
% 将最后一步的输出加上
% 找到L在字典的位置,并输出相应码流
for n=1:Len_dic % 循环判断整个字典中当前L的位置
if strcmp(L, dic_ext{n,2})==1
Out_bits = strcat(Out_bits, num2str((n- 1), formatSpec));
end
end
rate = length(Str_input)*3/length(Out_bits) % 压缩比
% LZW编码
fprintf('LZW编码后的码字流:\t');disp(Out_bits);
% 输出扩充的字典
fprintf('扩充字典:\n');disp(dic_ext);
% 将更新后字典写入新的Excel表格中方便查看
writetable(dic_ext,'dic_ext.xlsx');
% 将LZW编码保存为mat格式文件
save LZW.mat Out_bits;
最终压缩比为1.7692,达到压缩目的,并且随着初始文本长度的增加和字典的完善,压缩比也会进一步提高。