lzw简介

LZW压缩算法由Lemple-Ziv-Welch 三人共同创造,用他们的名字命名。它采用了一种先进的串表

压缩,将每个第一次出现的串放在一个串表中,用一个数字来表示串,压缩文件只存贮数字,则不

存贮串,从而使图象文件的压缩效率得到较大的提高。奇妙的是,不管是在压缩还是在解压缩的过

程中都能正确的建立这个串表,压缩或解压缩完成后,这个串表又被丢弃。

LZW算法中,首先建立一个字符串表,把每一个第一次出现的字符串放入串表中,并用一个数

字来表示,这个数字与此字符串在串表中的位置有关,并将这个数字存入压缩文件中,如果这个字

符串再次出现时,即可用表示它的数字来代替,并将这个数字存入文件中。压缩完成后将串表丢

弃。如"print" 字符串,如果在压缩时用266表示,只要再次出现,均用266表示,并将"print"字符串

存入串表中,在图象解码时遇到数字266,即可从串表中查出266所代表的字符串"print",在解压缩

时,串表可以根据压缩数据重新生成。

lzw编码举例

编码:输入码流:a  a  b  b  b  a  a  b  b

初始符号集合:

0 1
a b

编码压缩过程:

步骤 间隔 是否存在 输出 标号
1 a - - - - -
2 a a (a,a) N 0 2
3 a b (a,b) N 0 3
4 b b (b,b) N 1 4
5 b b (b,b) Y
6 bb a (bb,a) N 6 5
7 a a (a,a) Y
8 aa b (aa,b) N 4 6
9 b b (b,b) Y
10 bb - - - - -

此时此刻的标号集合:

0 1 2 3 4 5 6 7
a b aa ab bb bba aab -

编码输出为:001646

解码过程:

1)读入第一个编码Code=0H,由于字符串表中存在该索引,因此输出字符串表中0H对应的字符串"a",同时使OldCode=Code=0H。

2)读下一个编码Code=0H,字符串表中存在该索引,输出0H所对应的字符串"a",然后将OldCode=0H所对应的字符串"a"加上Code=0H所对应的字符串的第一个字符"a",即"aa"添加到字串表中,其索引为4H,同时使OldCode=Code=0H。

3)读下一个编码Code=1H,字串表中存在该索引,输出1H所对应的字符串"b",然后将OldCode=0H所对应的字符串"a"加上Code=1H所对应的字符串的第一个字符"b",即"ab"添加到字串表中,其索引为5H,同时使OldCode=Code=1H。

4)读入下一个编码Code=6H,由于字串表中不存在该索引,因此输出OldCode=1H所对应的字符串"b"加上OldCode的第一个字符"b“,即"bb",同时将"bb"添加到字符串表中,其索引为6H,同时使OldCode=Code=6H。

5)读下一个编码Code=4H,字串表中存在该索引,输出4H所对应的字符串"aa",然后将OldCode=6H所对应的字符串"bb"加上Code=4H所对应的字符串的第一个字符"a",即"bba"添加到字串表中,其索引为7H,同时使OldCode=Code=4H。

6)读下一个编码Code=6H,字串表中存在该索引,输出6H所对应的字符串"bb",然后将OldCode=4H所对应的字符串"aa"加上Code=6H所对应的字符串的第一个字符"b",即"aab"添加到字串表中,其索引为8H,同时使OldCode=Code=6H。

7)读下一个编码Code=3H,它等于LZW_EOI,数据解码完毕

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)如果”否”,结束。
解码过程:

具体解压步骤如下:

(1)译码开始时Dictionary包含所有的根。

(2)读入在编码数据流中的第一个码字 cW(它表示一个Root)。

(3)输出String.cW到字符数据流Charstream。

(4)使pW=cW 。

(5)读入编码数 据流 的下一个码字cW 。

(6)目前在字典中有String.cW吗?

YES:1)将String.cW输出给字符数据流;

2)使P=String.pW;

3)使C=String.cW的第一个字符;

4)将字符 串P+C添 加进Dictionray。

NO :1)使P=String.pW ;

2)使C=String.pW的第一个字符;

3)将字符串P+C输出到字符数据流并将其添加进Dictionray(现在它与cW相一致)。

(7)在编码数据 流中还有Codeword吗?

YES:返回(4)继续进行 译码 。

NO:结束译码 。

/** Declaration for bitwise IO** vim: ts=4 sw=4 cindent*/
#ifndef __BITIO__
#define __BITIO__#include <stdio.h>typedef struct{FILE *fp;unsigned char mask;int rack;
}BITFILE;BITFILE *OpenBitFileInput( char *filename);
BITFILE *OpenBitFileOutput( char *filename);
void CloseBitFileInput( BITFILE *bf);
void CloseBitFileOutput( BITFILE *bf);
int BitInput( BITFILE *bf);
unsigned long BitsInput( BITFILE *bf, int count);
void BitOutput( BITFILE *bf, int bit);
void BitsOutput( BITFILE *bf, unsigned long code, int count);
#endif  // __BITIO__
** Definitions for bitwise IO** vim: ts=4 sw=4 cindent*/#include <stdlib.h>
#include <stdio.h>
#include "bitio.h"
BITFILE *OpenBitFileInput( char *filename){BITFILE *bf;bf = (BITFILE *)malloc( sizeof(BITFILE));if( NULL == bf) return NULL;if( NULL == filename)  bf->fp = stdin;else bf->fp = fopen( filename, "rb");if( NULL == bf->fp) return NULL;bf->mask = 0x80;bf->rack = 0;return bf;
}BITFILE *OpenBitFileOutput( char *filename){BITFILE *bf;bf = (BITFILE *)malloc( sizeof(BITFILE));if( NULL == bf) return NULL;if( NULL == filename)    bf->fp = stdout;else bf->fp = fopen( filename, "wb");if( NULL == bf->fp) return NULL;bf->mask = 0x80;bf->rack = 0;return bf;
}void CloseBitFileInput( BITFILE *bf){fclose( bf->fp);free( bf);
}void CloseBitFileOutput( BITFILE *bf){// Output the remaining bitsif( 0x80 != bf->mask) fputc( bf->rack, bf->fp);fclose( bf->fp);free( bf);
}int BitInput( BITFILE *bf){int value;if( 0x80 == bf->mask){bf->rack = fgetc( bf->fp);if( EOF == bf->rack){fprintf(stderr, "Read after the end of file reached\n");exit( -1);}}value = bf->mask & bf->rack;bf->mask >>= 1;if( 0==bf->mask) bf->mask = 0x80;return( (0==value)?0:1);
}unsigned long BitsInput( BITFILE *bf, int count){unsigned long mask;unsigned long value;mask = 1L << (count-1);value = 0L;while( 0!=mask){if( 1 == BitInput( bf))value |= mask;mask >>= 1;}return value;
}void BitOutput( BITFILE *bf, int bit){if( 0 != bit) bf->rack |= bf->mask;bf->mask >>= 1;if( 0 == bf->mask){ // eight bits in rackfputc( bf->rack, bf->fp);bf->rack = 0;bf->mask = 0x80;}
}void BitsOutput( BITFILE *bf, unsigned long code, int count){unsigned long mask;mask = 1L << (count-1);while( 0 != mask){BitOutput( bf, (int)(0==(code&mask)?0:1));mask >>= 1;}
}
#if 0
int main( int argc, char **argv){BITFILE *bfi, *bfo;int bit;int count = 0;if( 1<argc){if( NULL==OpenBitFileInput( bfi, argv[1])){fprintf( stderr, "fail open the file\n");return -1;}}else{if( NULL==OpenBitFileInput( bfi, NULL)){fprintf( stderr, "fail open stdin\n");return -2;}}if( 2<argc){if( NULL==OpenBitFileOutput( bfo, argv[2])){fprintf( stderr, "fail open file for output\n");return -3;}}else{if( NULL==OpenBitFileOutput( bfo, NULL)){fprintf( stderr, "fail open stdout\n");return -4;}}while( 1){bit = BitInput( bfi);fprintf( stderr, "%d", bit);count ++;if( 0==(count&7))fprintf( stderr, " ");BitOutput( bfo, bit);}return 0;
}
#endif

main

struct {int suffix;int parent, firstchild, nextsibling;
} dictionary[MAX_CODE+1];
int next_code;
int d_stack[MAX_CODE]; // stack for decoding a phrase#define input(f) ((int)BitsInput( f, 16))
#define output(f, x) BitsOutput( f, (unsigned long)(x), 16)int DecodeString( int start, int code);
void InitDictionary( void);
void PrintDictionary( void){int n;int count;for( n=256; n<next_code; n++){count = DecodeString( 0, n);printf( "%4d->", n);while( 0<count--) printf("%c", (char)(d_stack[count]));printf( "\n");}
}int DecodeString( int start, int code){int count;count = start;while( 0<=code){d_stack[ count] = dictionary[code].suffix;code = dictionary[code].parent;count ++;}return count;
}
void InitDictionary( void){int i;for( i=0; i<256; i++){dictionary[i].suffix = i;dictionary[i].parent = -1;dictionary[i].firstchild = -1;dictionary[i].nextsibling = i+1;}dictionary[255].nextsibling = -1;next_code = 256;
}
/** Input: string represented by string_code in dictionary,* Output: the index of character+string in the dictionary*      index = -1 if not found*/
int InDictionary( int character, int string_code){int sibling;if( 0>string_code) return character;sibling = dictionary[string_code].firstchild;while( -1<sibling){if( character == dictionary[sibling].suffix) return sibling;sibling = dictionary[sibling].nextsibling;}return -1;
}void AddToDictionary( int character, int string_code){int firstsibling, nextsibling;if( 0>string_code) return;dictionary[next_code].suffix = character;dictionary[next_code].parent = string_code;dictionary[next_code].nextsibling = -1;dictionary[next_code].firstchild = -1;firstsibling = dictionary[string_code].firstchild;if( -1<firstsibling){  // the parent has childnextsibling = firstsibling;while( -1<dictionary[nextsibling].nextsibling ) nextsibling = dictionary[nextsibling].nextsibling;dictionary[nextsibling].nextsibling = next_code;}else{// no child before, modify it to be the firstdictionary[string_code].firstchild = next_code;}next_code ++;
}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 dictionarystring_code = index;}else{   // string+character not in dictionaryoutput( bf, string_code);if( MAX_CODE > next_code){    // free space in dictionary// add string+character to dictionaryAddToDictionary( character, string_code);}string_code = character;}}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;
}
}int main( int argc, char **argv){FILE *fp;BITFILE *bf;if( 4>argc){fprintf( stdout, "usage: \n%s <o> <ifile> <ofile>\n", argv[0]);//fprintf()函数根据指定的format(格式)发送信息(参数)到由stream(流)指定的文件.因此fprintf()可以使得信息输出到指定的文件。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]){ // do encodingfp = fopen( argv[2], "rb");bf = OpenBitFileOutput( argv[3]);if( NULL!=fp && NULL!=bf){LZWEncode( fp, bf);fclose( fp);CloseBitFileOutput( bf);fprintf( stdout, "encoding done\n");}}else if( 'D' == argv[1][0]){    // do decodingbf = OpenBitFileInput( argv[2]);fp = fopen( argv[3], "wb");if( NULL!=fp && NULL!=bf){LZWDecode( bf, fp);fclose( fp);CloseBitFileInput( bf);fprintf( stdout, "decoding done\n");}}else{    // otherwisefprintf( stderr, "not supported operation\n");}return 0;
}

实验结果:

txt 100%(压缩效率)
doc 146%
ppt 130%
pub 15%
jpg 90%
gif 160%

数据压缩实验 LZW编解码算法的实现与分析相关推荐

  1. 实验三 LZW编解码算法实现与分析

    LZW简述 本部分参考wiki https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch LZW压缩算法在1978年提出,由 Abr ...

  2. 【实验三】LZW编解码算法实现与分析

    一.实验目的 1.掌握词典编码的基本原理,用C/C++/Python等语言编程实现LZW解码器并分析编解码算法. 2.选择十种不同格式类型的文件,使用LZW编码器进行压缩得到输出的压缩比特流文件.对各 ...

  3. LZW 编解码算法实现与分析

    实验目的 掌握词典编码的基本原理,用C/C++/Python等语言编程实现LZW解码器并分析编解码算 法. 方法解释 算法说明 所用功能代码 词典树数组结构体 struct {int suffix;/ ...

  4. [实验三]LZW 编解码算法实现与分析

    目录 一.LZW算法 1.1 编码步骤 1.2 解码步骤 1.3 关于有可能出现当前码字CW不在词典中的情况说明 二.代码实现 2.1 程序说明 2.2 数据结构 2.3 bitio.h 2.4 bi ...

  5. 【数据压缩(五)】LZW编解码c语言实现和分析

    一.实验目的 1.掌握词典编码的基本原理 2.C/C++/Python等语言编程实现LZW解码器 3.分析编解码算法 二.实验要求 1.首先调试LZW的编码程序,以一个文本文件作为输入,得到输出的LZ ...

  6. 算法分析与设计实验报告 ——二分搜索程序算法的实现

    算法分析与设计实验报告 --二分搜索程序算法的实现 实验目的及要求 1.理解分治算法的概念和基本要素: 2.理解递归的概念: 3.掌握设计有效算法的分治策略: 4.通过二分搜索技术学习分治策略设计技巧 ...

  7. 数据压缩原理实验4_DPCM编解码

    一.实验原理 DPCM编解码原理 DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统.而预测编码就是根据过去的信号样值来预测下一个信号样值,并将预测值与现实样值得差值进行量化.编码后进行数字信 ...

  8. DPCM编码算法的实现与分析

    目录 DPCM编解码原理 DPCM编码系统的设计 量化误差PSNR DPCM main.cpp 实验结果 实验总结 DPCM编解码原理 DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统.在D ...

  9. 实验三 LZW编解码实验

    一.LZW算法简介 LZW为词典编码的一种,是通过从输入数据中创建"短语词典".在编码过程中遇到词典中出现的"短语"时,编码器就输出其对应的"序号&q ...

  10. 【swjtu】数据结构实验9_多种排序算法的实现

    实验内容及要求: 输入n个整数,分别用希尔排序.快速排序.堆排序和归并排序实现由小到大排序并输出排序结果.要求n=10,15,20进行三组排序实验. 实验目的: 掌握希尔排序.快速排序.堆排序.归并排 ...

最新文章

  1. efishell无法开机shell_电脑出现EFIshellversion解决方法W1048/海尔青春小蓝
  2. ubuntu修改根用户密码
  3. 读债务危机0812:接管房利美和房地美
  4. 300plc与组态王mpi通讯_MPI(DP)-ETH以太网转换器使用手册
  5. python怎么定义全局变量_python中如何定义全局变量
  6. linux编辑文件命令 vi_Linux的vi编辑器
  7. 强制MySQL查询走索引和强制查询不缓存
  8. Ubuntu18.04下基于YoloV4 的Keras物体识别
  9. Atitit 性能指标与性能提升的5个原则与性能提升模型
  10. 整合 activiti 7 springcloud
  11. 保护眼睛——设置WIN7和XP 窗体、Chrome、IE网页背景颜色(zz)
  12. 微信小程序如何引用阿里icon字体
  13. Java-基础篇-03-【选择语句-循环语句-随机数】
  14. 移动硬盘RAW格式,无法识别读取
  15. 人工神经网络通过调整,神经网络怎么调参数
  16. 个人开发者申请微信appKey和appSecret,及响应微信发送的Token验证的Java代码
  17. win10无法启动_win10电脑开机进入不了系统如何解决?
  18. UE5影视动画渲染MRQ分层学习笔记
  19. Mac下7z格式文件解压
  20. 王刚日记:好软文是什么样子的?

热门文章

  1. 个人记账本,教你使用图表格查看项目
  2. plink格式文件的介绍及相互转换
  3. python学英语库_交流学英语的经验-js焦点图怎么写-WinFrom控件库|.net开源控件库|HZHControls官网...
  4. form-group 两种常用使用
  5. 定时删除微信文件夹中重复文件
  6. 从“棱镜门”看回溯技术的应用
  7. 2021年中式面点师(初级)证考试及中式面点师(初级)模拟考试题
  8. java 零拷贝_牛逼哄哄的零拷贝是什么?
  9. 用上瘾模型来看:艾威学院
  10. 美通企业日报 | 人们对传统教育系统的信心正在动摇;90后渴望健康却管不住嘴迈不开腿...