【数据压缩】LZW算法原理与源代码解析
转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/50331883
<勿在浮沙筑高台>
LZW压缩算法原理很easy,因而被广泛地採用,已经被引入主流图像文件格式中。
该算法由Lempel-Ziv-Welch三人发明,这样的技术将定长码字分配给变长信源符号序列,它不须要知道被压缩文件的符号出现概率的先验知识,仅仅须要动态地建立和维护一个字典,和其它压缩算法相比既是缺点也是长处。
1. LZW原理
1.1 概念的理解
LZW通过建立一个字典(code table),把不认识的字符串序列增加字典。当下次再次遇到此种字符串序列时,用字典的索引序号取代此序列,而一个索引序号占用的字节数往往比取代的字符串小的多,以此来达到压缩文件的目的。通常在图像压缩上,因为0-255用于表示灰度级(8位二进制),而我们的索引序号要与灰度级差别开来,因而。字典索引的建立要从256開始,见以下的样例,此样例不表示LZW算法的原型,临时不要关心字典是怎样建立的。
注意到,在上图中,压缩文件里保存了123 256 119 ... ,因为文件数据都是採用二进制形式保存的,解压时为了正确的按位读取。通常压缩文件里,写入的每个数据都是以12位形式写入文件。这时用字典索引號256取代连续的字符序列145 201 4,就是用了12位的数据取代了3个8位的数据。尽管其它的字符以原型写入,比如第一个8位数据123被扩展成12位的123,可是整体上看,仍然达到了压缩的作用。
1.2 压缩过程&流程图
LZW算法採用动态的建立字典的方法,依次读入原文件的字符序列,每次碰到新的连续的字符串。就在字典中增加标示。当下次再次遇到这样的字符串时,就能够用字典索引序号直接取代字符串,写入压缩文件里。在这里引入两个名词: "string","char";string表示前缀。char 表示新读入的字符,每一个字典索引相应一对(string,char);
--------------------------------------------------------------------------------------------------------------------------------------
举个样例:“ABCABC”開始时。初始化字典,索引0~255被初始化为(NULL, i), i =0,1,...,255;让字典从索引號256開始记录,正如上面所说。为了解压时方便识别数据,每次向压缩文件里写数据时,都是12位格式。这时字典索引范围为0~4095;
1. 開始时,读入第一个字符string = A,读下一个字符char = B 。
3. 查字典(A,B),字典中没有找到,在字典索引256中记录(A,B),然后输出前缀A,更新string=char=B,再次读入字符,char=C;
4. 查字典(B,C),字典中没有找到,在字典索引257中记录(B,C),然后输出前缀B,更新string=char=C,再次读入字符。char=A;
5. 查字典(C,A),字典中没有找到,在字典索引258中记录(C,A),然后输出前缀C,更新string=char=A,再次读入字符,char=B;
6. 查字典(A,B),字典能够找到,相应索引號256,然后更新string=256,再次读入字符,char=C;
7. 查字典(256,C),字典中没有找到,在字典索引259中记录(256,C),然后输出前缀256,更新string=char=C,再次读入字符。char=NULL;
8. char = NULL
,文件结束,输出前缀C.
压缩完毕后:A B C
256 C ; 字典不须要写入文件里;
上述过程概括:"前缀string+字符char"在字典中不存在,增加字典。输出前缀,更新前缀=char,读入新字符char;
"前缀string+字符char"在字典中存在,更新前缀=索引號,读入新字符char;
--------------------------------------------------------------------------------------------------------------------------------------
1.3 解压过程&流程图
上述压缩文件为 A B C 256 C ,相同採用上述的步骤。初始化字典,建立字典、查字典的方法能够实现文件的解压缩,可是解压缩过程并不简单等同于压缩过程。解压缩完毕后压缩文件时建立的字典和解压缩建立的字典全然一样。PS:解压缩过程。网上部分博客说法不准确,结果导致我折腾了两天程序 。
------------------------------------------------------------------------------------------------------------------------------------------------
OCODE:表示已经读入的12位数据 ; NCODE:表示新读入的12位数据。
STRING:表示12位数据代表的字符串。CHAR表示被写入文件的字符串的第一个字符;
1. 開始时,初始化字典(0~255),读入第一个数据OCODE = A,输出字典索引OCODE相应的字符串A。读下一个数据NCODE = B 。
2. NCODE在字典中存在,输出table[NCODE]=B,CHAR=B;在字典索引256增加(OCODE,CHAR)=(A,B),更新OCODE=NCODE,读取数据NCODE=C;
3. NCODE在字典中存在,输出table[NCODE]=C,CHAR=C;在字典索引257增加(OCODE,CHAR)=(B,C),更新OCODE=NCODE,读取数据NCODE=256。
4. NCODE在字典中已建立,table[256]=AB,并记录CHAR=A;在字典索引258增加(OCODE,CHAR)=(C,A),更新OCODE=NCODE,读取数据NCODE=C;
5. NCODE在字典中已建立,table[NCODE]=C,CHAR=C。在字典索引259增加(OCODE,CHAR)=(256,C),更新OCODE=NCODE读取数据NCODE=空。
6. 文件结束!跳出循环!
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
你肯定已经注意到,上面举得样例解压缩时读取的NCODE都能够在字典中找到,什么情况下在字典中找不到呢?
压缩这个字符串"ABBBBBBBB"。解压缩时就能够碰到字典中找不到的情况。一定要动手试试,方便你理解整个流程图!
2.关于LZW的使用和改进
上面的样例都是採用12位格式写入文件,可是12位在字典中表示的范围为0~4095,真实去压缩一个文件时,这个大小肯定是不够的,假设扩展字典的范围,占用内存非常大。可是这时能够在文件里增加一个标示。然后又一次初始化字典,表示从此開始。採用新字典继续压缩文件。能够理解成把文件切割成多个小文件,每一个小文件单独採用一张表。通常令256表示新表的開始,257表示文件压缩结束。
从上面的过程能够看到,每个数据都採用12位格式写入文件。无疑造成了内存的浪费,比如256实际上能够用9位二进制表示。所以有非常多人对此进行了改进。採用变长的字典算法。比如当9位的字典写满时。继续採用10位的字典压缩。同一时候也有多算法对查找字典的方法进行了改进,时间上也有非常大的提高!
3.LZW算法的实现
完整project下载:http://download.csdn.net/detail/luoshixian099/9369093
/**********************************
CSDN 勿在浮沙筑高台
http://blog.csdn.net/luoshixian099
【数据压缩】LZW压缩算法 2015年12月17日
***********************************/
#include <iostream>
#include <fstream>
#include "Compress.h"
using namespace std;
#define IN "D:\\my.bmp"
#define OUT "D:\\test.rar"
int main()
{
compress COM(IN,OUT);
if (!COM.CheckFile())
return 0;
COM.Intial(); //压缩初始化
COM.WriteChar(START); //写入開始标志
UINT pre_code = COM.ReadChar();//读取前缀
UINT Count = 0;
while (!COM.CheckEOF())
{
UINT code = COM.ReadChar(); //读入新字符
UINT temp = COM.CheckTable(pre_code, code);//查字典
if (temp == EMPTY)
{
COM.WriteChar(pre_code); //写入前缀
pre_code = code; //更新前缀
}
else if (temp == NEW_TABLE) //字典已满,又一次初始化字典
{
COM.WriteChar(pre_code);
COM.WriteChar(NEW_TABLE);
COM.Intial();
pre_code = code;
}
else
{
pre_code = temp;
}
}
COM.WriteChar(pre_code); //文件结束,输出前缀
COM.WriteEnd();
return 0;
}
/**********************************
CSDN 勿在浮沙筑高台
http://blog.csdn.net/luoshixian099
【数据压缩】LZW解压缩算法 2015年12月17日
***********************************/
#include <iostream>
#include <fstream>
#include "decompress.h"
using namespace std;
#define IN "D:\\test.rar"
#define OUT "D:\\mytest.bmp"
int main()
{
DeCompress DCOM(IN,OUT);
if (!DCOM.CheckFile())
return 0;
DCOM.Intial(); //初始化字典
UINT OCODE, NCODE;
UCHAR FirstChar;
OCODE = DCOM.ReadData(); //读取第一个数据
DCOM.WriteChar(OCODE); //输出 while (!DCOM.CheckEOF())
{
NCODE = DCOM.ReadData(); //读入新数据
if (NCODE == END) //文件结束标志
break;
else if (NCODE == NEW_TABLE) //读入新字典标志
{
OCODE = DCOM.ReadData();
DCOM.WriteChar(OCODE);
DCOM.Intial();
continue;
}
if (DCOM.CheckTable(NCODE)) //在字典中存在
{
DCOM.WriteChar(NCODE); //输出NCODE
FirstChar = DCOM.GetFirstChar(NCODE);//更新NCODE的第一个字符
}
else //字典中不存在
{
DCOM.WriteChar(OCODE);
DCOM.WriteChar(FirstChar);
FirstChar = DCOM.GetFirstChar(OCODE);
}
DCOM.AddtoTable(OCODE, FirstChar); //OCODE+CHAR字典
OCODE = NCODE;
}
DCOM.WriteEnd();
return 0;
}
參考文章:
http://blog.chinaunix.net/uid-23741326-id-3124208.html
http://blog.csdn.net/abcjennifer/article/details/7995426
【数据压缩】LZW算法原理与源代码解析的更多相关文章
- Android源代码解析之(三)-->异步任务AsyncTask
转载请标明出处:一片枫叶的专栏 上一篇文章中我们解说了android中的异步消息机制. 主要解说了Handler对象的使用方式.消息的发送流程等.android的异步消息机制是android中多任务处 ...
- 【数据压缩】LZ78算法原理及实现
在提出基于滑动窗口的LZ77算法后,两位大神Jacob Ziv与Abraham Lempel [1]于1978年又提出了LZ78算法:与LZ77算法不同的是LZ78算法使用树状词典维护历史字符串. [ ...
- 机器学习算法实现解析——word2vec源代码解析
在阅读本文之前,建议首先阅读"简单易学的机器学习算法--word2vec的算法原理"(眼下还没公布).掌握例如以下的几个概念: 什么是统计语言模型 神经概率语言模型的网络结构 CB ...
- GBDT算法原理深入解析
GBDT算法原理深入解析 标签: 机器学习 集成学习 GBM GBDT XGBoost 梯度提升(Gradient boosting)是一种用于回归.分类和排序任务的机器学习技术,属于Boosting ...
- 【数据压缩】LZ77算法原理及实现
1. 引言 LZ77算法是采用字典做数据压缩的算法,由以色列的两位大神Jacob Ziv与Abraham Lempel在1977年发表的论文<A Universal Algorithm for ...
- 2. Attention Is All You Need(Transformer)算法原理解析
1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...
- 3. ELMo算法原理解析
1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...
- 4. OpenAI GPT算法原理解析
1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...
- 5. BERT算法原理解析
1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...
随机推荐
- Appium robotframework-appium (ios 客户端测试)环境搭建
一. 简介 1.1摘要 本人测试新人,最近在搞ios客户端的自动化,准备采用robotframework-appium来实现自动化测试,一边学习一边总结,此安装说明文档是基于mac系统10.11版本, ...
- cocos2d-android 使用 cocos2d 绘图
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha cocos2d-android-1 https://github.com/ZhouWei ...
- Palindromic Tree 回文自动机-回文树 例题+讲解
回文树,也叫回文自动机,是2014年被西伯利亚民族发明的,其功能如下: 1.求前缀字符串中的本质不同的回文串种类 2.求每个本质不同回文串的个数 3.以下标i为结尾的回文串个数/种类 4.每个本质不同 ...
- 「UOJ207」共价大爷游长沙
「UOJ207」共价大爷游长沙 解题思路 : 快速判断两个集合是否完全相等可以随机点权 \(\text{xor}\) 的思路可以用到这道题上面,给每一条路径随机一个点权,维护出经过每一条边的点权的 \ ...
- bzoj 2055: 80人环游世界 -- 上下界网络流
2055: 80人环游世界 Time Limit: 10 Sec Memory Limit: 64 MB Description 想必大家都看过成龙大哥的<80天环游世界>,里面 ...
- [转][Android] ListView中getView的原理+如何在ListView中放置多个item
ListView 和 Adapter 的基础 工作原理: ListView 针对List中每个item,要求 adapter “给我一个视图” (getView). 一个新的视图被返回并显示 如果 ...
- hdu 5210 delete 水题
Delete Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5210 D ...
- Linux下简单分析请求有没有进到本机的工具tcpdump(网络接口的数据包的头信息)
可以通过这个工具快速分析出一个请求到底有没有进入到本机.信息有点简单,对于前期的分析比较有帮助.而对于详细的分析可以借助iptables的raw表进行日志分析. 参考: http://man.linu ...
- JSoup 用法详解
清单 1 // 直接从字符串中输入 HTML 文档 String html = "<html><head><title> 开源中国社区 </titl ...
- SpringMvc的服务器端跳转和客户端跳转
首先,找到 package org.springframework.web.servlet.view; public class InternalResourceViewResolver extend ...