LZW编码编程实现(C++版)
lzw压缩、解压缩 C语言算法实现
将源文件拷贝到当前目录下,打开源程序lzw.cbp,在main.cpp中更改源文件、压缩文件、解压文件的名称、路径:#define S() (strcpy(sourfile, "sourfile.jpg")) //源文件名及路径#define C() (strcpy(codefile, "codefile.lzw")) //压缩文件名及路径#define D() (strcpy(destfile, "destfile.jpg")) //解压文件名及路径下面是具体实现,总共四个文件://头文件模块:lzw.h#ifndef LZW_H_INCLUDED#define LZW_H_INCLUDED#define N 90000#define M 100typedef unsigned int Uint;/*函数功能: 将sourfile文件用LZW压缩到codefile文件中函数参数:待压缩文件/压缩目标文件函数返回值:压缩成功(TRUE)/压缩失败(FALSE)*/void LzwEncoding(char sourfile[], char codefile[]);/*函数功能: 将codefile文件用LZW解压到destfilefile文件中函数参数:压缩目标文件/解压文件函数返回值:解压成功(TRUE)/解压失败(FALSE)*/void LzwDecoding(char codefile[], char destfile[]);/*函数功能:判断前缀数组与当前字符的结合是否在字典中存在索引函数参数:当前字符(cbuff)函数返回值:在字典中(TRUE)/不在字典中(F ALSE)*/bool IsFindDictKey(Uint buff);/*函数功能:判断前缀数组与当前字符的结合是否在字典中存在索引函数参数:前缀数组(preFix)/前缀数组的有效长度(preCount)/当前字符(cbuff)函数返回值:在字典中(TRUE)/不在字典中(F ALSE)*/bool IsDictValue(Uint preFix[], Uint preCount, Uint cbuff);/*函数功能:查找前缀数组在字典中的索引函数参数:前缀数组(preFix)/前缀数组的有效长度(preCount)函数返回值:前缀数组在字典中的索引*/Uint FindDictKey(Uint preFix[], Uint preCount);extern Uint dict[N][M]; //全局字典extern char sourfile[20]; //全局带压缩文件extern char codefile[20]; //全局压缩文件extern char destfile[20]; //全局解压文件#endif // LZW_H_INCLUDED运行源程序将执行压缩机解压缩两个过程:LzwEncoding(sourfile, codefile); //压缩文件sourfile到codefile LzwDecoding(codefile, destfile); //解压文件codefile到destfile//主函数模块:main.cpp#include <stdio.h>#include <stdlib.h>#include <string.h>#include "lzw.h"#define S() (strcpy(sourfile, "sourfile.pdf"))#define C() (strcpy(codefile, "codefile.lzw"))#define D() (strcpy(destfile, "destfile.pdf"))using namespace std;Uint dict[N][M]; //全局字典int main(void){char sourfile[20];char codefile[20];char destfile[20];S();C();D();LzwEncoding(sourfile, codefile);LzwDecoding(codefile, destfile);return 0;}//压缩模块:LzwEncoding.cpp#include <stdio.h>#include <stdlib.h>#include <windows.h>#include "lzw.h"using namespace std;/*函数功能:查找前缀数组在字典中的索引函数参数:前缀数组(preFix)/前缀数组的有效长度(preCount) 函数返回值:前缀数组在字典中的索引*/Uint DictKey(Uint preFix[], Uint preCount){Uint i;int flag = 0;for (i = 0; i < N; i++){Uint j = preCount;if (dict[i][0] == preCount){flag = 1;while ( j-- ){if (dict[i][j+1] != preFix[j]){flag = 0;break;}}}if ( flag ) break;}return i;}/*函数功能:判断前缀数组与当前字符的结合是否在字典中存在索引函数参数:前缀数组(preFix)/前缀数组的有效长度(preCount)/当前字符((int)sbuff[count]) 函数返回值:在字典中(TRUE)/不在字典中(F ALSE)*/bool IsDictValue(Uint preFix[], Uint preCount, Uint cbuff){int flag = 0;for (Uint i = 0; i < N; i++){if ((dict[i][0] == preCount+1) && (dict[i][preCount+1] == cbuff)){flag = 1;for (Uint j = 0; j < preCount; j++){if (dict[i][j+1] != preFix[j]){flag = 0;break;}}}if ( flag ) break;}if ( flag )return true;elsereturn false;}/*O(n*n)*//*函数功能: 将sourfile文件用LZW压缩到codefile文件中函数参数:待压缩文件/压缩目标文件函数返回值:压缩成功(TRUE)/压缩失败(FALSE)*/void LzwEncoding(char sourfile[], char codefile[]){FILE *sfp; //源文件句柄FILE *cfp; //编码文件句柄BYTE sbuff[N]; //源文件字节缓冲区Uint cbuff[N]; //压缩文件字节缓冲区Uint preCount; //前缀数组小标Uint preFix[N]; //前缀数组Uint dictCount = 255; //字典索引位置Uint cCount = 0; //压缩字节缓冲区下标Uint count = 0; //计数器Uint code; //临时编码if ((sfp = fopen(sourfile, "rb")) == NULL){printf("Read source file error!");exit( 0 );}if ((cfp = fopen(codefile, "wb")) == NULL){printf("Write code file error!");fclose(sfp);exit( 0 );}//初始化字典for (int i = 0; i < N; i++){if (i < 256){dict[i][0] = 1; //第i个索引处有一个字符dict[i][1] = i; //第i个索引处的字符}else{dict[i][0] = 0; //第i个索引处没有字符}}fseek(sfp, 0, SEEK_END);long fl = ftell(sfp); //获取原文件的字节数fseek(sfp, 0, SEEK_SET); //将文件指针移到文件开头处fread(sbuff, sizeof(sbuff[0]), fl, sfp); //将文件一次性读到缓冲区preCount = 0; //初始化前缀数组下标while ( fl-- ) //读取源文件内容并进行编码{if (IsDictValue(preFix, preCount, (int)sbuff[count])) //当前字符串在字典中preFix[preCount++] = (int)sbuff[count]; //将当前字符复制给前缀数组else{ //当前字符串不在字典中dictCount++; //字典增长//将前缀数组对应的索引写入编码文件code = DictKey(preFix, preCount);cbuff[cCount++] = code;//将前缀数组的字符及当前字符添加到字典中Uint icount = preCount; //记录前缀数组的有效长度dict[dictCount][0] = icount+1; //将dictCount索引处的字符数记录到字典while ( icount-- ){dict[dictCount][preCount-icount] = preFix[preCount-icount-1];}dict[dictCount][preCount-icount] = (int)sbuff[count];preCount = 0;preFix[preCount++] = (int)sbuff[count]; //将当前字符复制给前缀数组}count++;}code = DictKey(preFix, preCount);cbuff[cCount++] = code;fwrite(cbuff, sizeof(Uint), cCount, cfp); //将压缩文件整块写入文件fclose(sfp);fclose(cfp);}/* O(n^2*m) *///解压模块:LzwDecoding.cpp#include <stdio.h>#include <stdlib.h>#include <windows.h>#include "lzw.h"using namespace std;/*函数功能:判断buff是否为字典中的一个索引函数参数:无符号整形数buff函数返回值:是(TRUE)/否(FALSE)*/bool IsDictKey(Uint buff){if (dict[buff][0] == 0)return false;return true;}/*函数功能: 将codefile文件用LZW解压到destfilefile文件中函数参数:压缩目标文件/解压文件函数返回值:解压成功(TRUE)/解压失败(FALSE)*/void LzwDecoding(char codefile[], char destfile[]){FILE *cfp; //编码文件句柄FILE *dfp; //源文件句柄Uint oldCount; //old数组下标Uint oldCode[N] = {0}; //解码过的索引值??Uint cbuff[N/4]; //压缩文件缓冲区Uint cCount = 0; //压缩文件缓冲区下标BYTE dbuff[N] = {0}; //解压文件缓冲区Uint dCount = 0; //解压文件缓冲区下标Uint dictCount = 255; //字典长度Uint i, j; //循环变量if ((cfp = fopen(codefile, "rb")) == NULL){printf("Read coding file error!");exit( 0 );}if ((dfp = fopen(destfile, "wb")) == NULL){printf("Write decoding file error!");fclose(cfp);exit( 0 );}//初始化字典for (i = 0; i < N; i++){if (i < 256){dict[i][0] = 1; //第i个索引处有一个字符dict[i][1] = i; //第i个索引处的字符}else{dict[i][0] = 0; //第i个索引处没有字符}}fseek(cfp, 0, SEEK_END);long fl = ftell(cfp)/4; //获取原文件的编码数fseek(cfp, 0, SEEK_SET); //将文件指针移到文件开头处oldCount = 0; //初始化前缀数组下标、处理第一个编码fread(cbuff, sizeof(Uint), fl, cfp);//将压缩文件整块读入dbuff[dCount++]=cbuff[cCount];oldCode[oldCount++]=cbuff[cCount];fl--;while ( fl-- ) //读取源文件内容并进行编码{cCount++; //处理下一编码dictCount++; //字典增长if (IsDictKey(cbuff[cCount])) //字节在字典中{j = oldCount;dict[dictCount][0] = oldCount+1;while ( j-- ) //更新字典dict[dictCount][oldCount-j] = oldCode[oldCount-j-1];dict[dictCount][oldCount-j] = dict[cbuff[cCount]][1];i = dict[cbuff[cCount]][0];while ( i-- ) //将当前索引对应的字典值加入解压文件缓冲区dbuff[dCount++] = dict[cbuff[cCount]][dict[cbuff[cCount]][0]-i];//更新前缀数组oldCount = 0;i = dict[cbuff[cCount]][0];while ( i-- ){oldCode[oldCount]=dict[cbuff[cCount]][oldCount+1];oldCount++;}}else{i = oldCount;while ( i-- ) //前缀数组中的字典值加入解压文件缓冲区dbuff[dCount++]=oldCode[oldCount-i-1];dbuff[dCount++]=oldCode[0];dict[cbuff[cCount]][0] = oldCount+1;j = oldCount;while ( j-- ) //将前缀数组及前缀数组的第一个字符更新到字典dict[dictCount][oldCount-j+1] = oldCode[oldCount-j];dict[dictCount][oldCount-j]=oldCode[0];oldCode[oldCount++]=oldCode[0];}}fwrite(dbuff, sizeof(BYTE), dCount, dfp); //将解压文件缓冲区整块写入解压文件fclose(cfp);fclose(dfp);}改进方案:用结构体代替数组实现全局字典字典!其实现很简单,留给读者自行解决!。
LZW编码算法详解
LZW编码算法详解LZW(Lempel-Ziv & Welch)编码又称字串表编码,是Welch将Lemple和Ziv所提出来的无损压缩技术改进后的压缩方法。
GIF图像文件采用的是一种改良的LZW 压缩算法,通常称为GIF-LZW压缩算法。
下面简要介绍GIF-LZW的编码与解码方程解:例现有来源于二色系统的图像数据源(假设数据以字符串表示):aabbbaabb,试对其进行LZW编码及解码。
1)根据图像中使用的颜色数初始化一个字串表(如表1),字串表中的每个颜色对应一个索引。
在初始字串表的LZW_CLEAR和LZW_EOI分别为字串表初始化标志和编码结束标志。
设置字符串变量S1、S2并初始化为空。
2)输出LZW_CLEAR在字串表中的索引3H(见表2第一行)。
3)从图像数据流中第一个字符开始,读取一个字符a,将其赋给字符串变量S2。
判断S1+S2=“a”在字符表中,则S1=S1+S2=“a”(见表2第二行)。
4)读取图像数据流中下一个字符a,将其赋给字符串变量S2。
判断S1+S2=“aa”不在字符串表中,输出S1=“a”在字串表中的索引0H,并在字串表末尾为S1+S2="aa"添加索引4H,且S1=S2=“a”(见表2第三行)。
5)读下一个字符b赋给S2。
判断S1+S2=“ab”不在字符串表中,输出S1=“a”在字串表中的索引0H,并在字串表末尾为S1+S2=“ab”添加索引5H,且S1=S2=“b”(见表2第四行)。
6)读下一个字符b赋给S2。
S1+S2=“bb”不在字串表中,输出S1=“b”在字串表中的索引1H,并在字串表末尾为S1+S2=“bb”添加索引6H,且S1=S2=“b”(见表2第五行)。
7)读字符b赋给S2。
S1+S2=“bb”在字串表中,则S1=S1+S2=“bb”(见表2第六行)。
8)读字符a赋给S2。
S1+S2=“bba”不在字串表中,输出S1=“bb”在字串表中的索引6H,并在字串表末尾为S1+S2=“bba”添加索引7H,且S1=S2=“a”(见表2第七行)。
实验三LZW编码
实验三LZW编码一、实验目的1、加深对LZW编码的理解;2、掌握LZW编码的程序设计。
二、原理与说明LZW编码的步骤:a ab aa bc ba aab ab bc1 12 4 23 6 7 5 8三、实验内容利用C、VB或VC语言实现LZW编码的算法,掌握LZW编码的程序设计并调试通过。
四、实验设备计算机程序如下:#include<>#include""#include""#include""#include""#define BIRS 12#define HASHING_SHIFT BITS-8#define MAX_V ALUE(1<<BITS)-1#define MAX_CODE MAX_V ALUE-1 #if BITS==14#define TABLE_SIZE 18041#endif#if BITS==13#define TABLE_SIZE 9029#endif#if BITS<=12#define TABLE_SIZE 5021int *code_value;unsigned int *prefix_code;unsigned char *append_character; unsigned char decode_stack[4000];char ok;find match(int hash_perfix,unsigned int hash_character){int index;int offset;index=(hash_character<<HASHING_SHIFT)^hash_prefix;if(index==0)offset=1;elseoffset=TABLE_SIZE-index;while(1){if(code_value[index]==-1)return(index);if(prefix_code[index]==hash_prefix&&append_character[index]==hash_character) return(index);index-=offset;if(index<0)index+=TABLE_SIZE;}}input_code(FILE*input){unsigned int return_value;static int input_bit_count=0;static unsigned long input_bit_buffer=0L;while(input_bit_count<=24){input_bit_buffer|=(unsigned long)getc(input)<<(24-input_bit_count);input_bit_count+=8;}return_value=input_bit_buffer>>(32-BITS);input_bit_buffer<<=BITS;input_bit_count-=BITS;return(return_value);}void output_code(FILE*output,unsigned int code){static int output_bit_count=0;static unsigned long output_bit_buffer=0L;output_bit_buffer|=(unsigned long)code<<(32-BITS-output_bit_count);output_bit_count+=BITS;while(output_bit_count>=8)putc(output_bit_buffer>>24,output);output_bit_buffer<<=8;output_bit_count-=8;}}void compress(FILE *input,FILE *output){unsigned int next_code;unsigned int character;unsigned int string_code;unsigned int index;int i;next_code=256;for(i=0;i<TABLE_SIZE;i++)code_value[i]=-1;i=0;printf("\n\nCompressing...\n);string_code=getc(input);while((character=getc(input))!=(unsigned)EOF) {index=find_match(string_code,character);if(code_value[index]!=-1)string_code=code_value[index];{if(next_code<=MAX_CODE){code_value[index]=next_code++;prefix_code[index]=string_code;append_character[index]=character;}output_code(output,string_code);string_code=character;}}output_code(output,string_code);output_code(output,MAX_V ALUE);output_code(output,0);printf("\n");getchar();void expand(FILE*input,FILE*output){unsigned int next_code;unsigned int nex_code;unsigned int old_code;int character;unsigned char*string;char*decode_string(unsigned char*buffer,unsigned int code)lnext_code=256;counter=0;printf("\n\nExpanding...\n");old_code=input_code(input);character=old_code;putc(old_code,output);while((nex_code=input_code(input))!=(MAX_V ALUE)){if(new_code>=next_code){*decode_stack=character;string=(unsigned char*)decode_string(decode_stcak+1,old_code);}elsestring=(unsigned char*)decode_string(decode_stck,nex_code);character=*string;while(string>=decode_stack)putc(*string--,output);if(next_code<=MAX_CODE){append_character[next_code]=character;next_code++;}old_code=nex_code;}printf("\n");getchar();}char *decode_string(unsigned char*buffer,unsigned int code) {int i;i=0;while(code>255){*buffer++=append_character[code];code=prefix_code[code];if(i++>=4094){printf("Fatal error during code expansion.\n");exit(0);}}*buffer=code;int main(int argc,char*argv[]){FILE*input_file;FILE*output_file;FILE*lzw_file;char input_file_name[81];int select;character=*string;while(string>=decode_stack)putc(*string--,output);if(next_code<=MAX_CODE){prefix_code[next_code]=old_code;append_character[next_code]=character;next_code++;}old_code=new_code;}printf("\n");getchar();}printf("**\n");printf("**********************\n");scanf("%d",&select);if(select==1){if(argc>1)strcpy(input_file_name,argv[1]);else{printf("\nInput file name?");scanf("%s",input_file_name);printf("\nCompressed file name?");scanf("%s",compressed_file_name);}input_file=fopen(input_file_name,"rb");lzw_file=fopen(compressed_filename,"wb");while(input_file==NULL||lzw_file==NULL){printf("Fatal error opening files!\n");printf("\nInput file names?");scanf("%s",input_file_name);printf("\nCompressed file name?");scanf("%s",compressed_file_name);input_file=fopen(input_file_name,"rb");};compress(input_file,lzw_file);fclose(input_file);fclode(lzw_file);free(code_value);else if(select==2){printf("\nOnput file names?");scanf("%s",onput_filename);printf("\nExpanded file name?");scanf("%s",expanded_filename);input_file=fopen(onput_filename,"rb");lzw_file=fopen(expanded_filename,"wb");while(lzw_file==NULL||output_file==NULL){printf("Fatal error opening files!\n");printf("\nOnput file names?");scanf("%s",onput_filename);printf("\nExpanded file name?");scanf("%s",expanded_filename);input_file=fopen(onput_filename,"rb");lzw_file=fopen(expanded_filename,"wb");};expand(lzw_file,output_file);fclose(lzw_file);-11fclose(output_file);}else{exit(0);}printf("\nContinue or not(y/n)?");scanf("%c",&ok);getchar();if(ok=='y'){goto loop;}else{printf("Complete......\n\nPress any key to continue");getchar();free(prefix_code);free(append_character);}return 0;}}-12。
LZW编码详解
1 NULL 2a 3a 4b 5b 6b 7a 8a 9b
NULL 2H
a
aa
0H
ab
0H
bb
1H
bb
bba
6H
aa
aab
4H
NULL a a b b bb a aa b
aa<4H> ab<5H> bb<6H>
bba<7H>
Aab<8H>
LZW编码步骤
(11)读字符b赋给S2。S1+S2=”bb”,在字符串表中,
序号 输入数据S2 S1+S2 输出结果
S1
生成新字符及索引
1
NULL
2
a
3
a
NULL
2H
a
aa
0H
NULL a a
aa<4H>
LZW编码步骤
(5)读下一个字符b赋给S2。判断S1+S2=”ab”不在字符串 表中,输出S1=“a”在字串表中的索引0H,并在字符串表末 尾为S1+S2=“ab”添加索引5H,且S1= S2=“b”
则 S1= S1+S2=“b”
序号 输入数据S2 S1+S2 输出结果
S1
生成新字符及索引
1 NULL 2a 3a 4b 5b 6b 7a 8a 9b 10 b
NULL 2H
a
aa
0H
ab
0H
bb
1H
bb
bba
6H
aa
aab
4H
bb
NULL a a b b bb a aa b bb
aa<4H> ab<5H> bb<6H>
lzw压缩算法的c语言实现
lzw压缩算法的c语言实现1 程序由五个模块组成。
(1) lzw.h 定义了一些基本的数据结构,常量,还有变量的初始化等。
#ifndef __LZW_H__#define __LZW_H__//------------------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <memory.h>//------------------------------------------------------------------------------#define LZW_BASE 0x102// The code base#define CODE_LEN 12 // Max code length#define TABLE_LEN 4099 // It must be prime number and bigger than 2^CODE_LEN=4096.// Such as 5051 is also ok.#define BUFFERSIZE 1024//------------------------------------------------------------------------------typedef struct{HANDLE h_sour; // Source file handle.HANDLE h_dest; // Destination file handle.HANDLE h_suffix; // Suffix table handle.HANDLE h_prefix; // Prefix table handle.HANDLE h_code; // Code table handle.LPWORD lp_prefix; // Prefix table head pointer.LPBYTE lp_suffix; // Suffix table head pointer.LPWORD lp_code; // Code table head pointer.WORD code;WORD prefix;BYTE suffix;BYTE cur_code_len; // Current code length.[ used in Dynamic-Code-Length mode ] }LZW_DATA,*PLZW_DATA;typedef struct{WORD top;WORD index;LPBYTE lp_buffer;HANDLE h_buffer;BYTE by_left;DWORD dw_buffer;BOOL end_flag;}BUFFER_DATA,*PBUFFER_DATA;typedef struct //Stack used in decode{WORD index;HANDLE h_stack;LPBYTE lp_stack;}STACK_DATA,*PSTACK_DATA;//------------------------------------------------------------------------------VOID stack_create( PSTACK_DATA stack ){stack->h_stack = GlobalAlloc( GHND , TABLE_LEN*sizeof(BYTE) );stack->lp_stack = GlobalLock( stack->h_stack );stack->index = 0;}//------------------------------------------------------------------------------VOID stack_destory( PSTACK_DATA stack ){GlobalUnlock( stack->h_stack );GlobalFree ( stack->h_stack );}//------------------------------------------------------------------------------VOID buffer_create( PBUFFER_DATA buffer ){buffer->h_buffer = GlobalAlloc( GHND, BUFFERSIZE*sizeof(BYTE) ); buffer->lp_buffer = GlobalLock( buffer->h_buffer );buffer->top = 0;buffer->index = 0;buffer->by_left = 0;buffer->dw_buffer = 0;buffer->end_flag = FALSE;}//------------------------------------------------------------------------------VOID buffer_destory( PBUFFER_DATA buffer ){GlobalUnlock( buffer->h_buffer );GlobalFree ( buffer->h_buffer );}//------------------------------------------------------------------------------VOID re_init_lzw( PLZW_DATA lzw ) //When code table reached its top it should { //be reinitialized.memset( lzw->lp_code, 0xFFFF, TABLE_LEN*sizeof(WORD) );lzw->code = LZW_BASE;lzw->cur_code_len = 9;}//------------------------------------------------------------------------------VOID lzw_create(PLZW_DATA lzw, HANDLE h_sour, HANDLE h_dest) {WORD i;lzw->h_code = GlobalAlloc( GHND, TABLE_LEN*sizeof(WORD) );lzw->h_prefix = GlobalAlloc( GHND, TABLE_LEN*sizeof(WORD) );lzw->h_suffix = GlobalAlloc( GHND, TABLE_LEN*sizeof(BYTE) );lzw->lp_code = GlobalLock( lzw->h_code );lzw->lp_prefix = GlobalLock( lzw->h_prefix );lzw->lp_suffix = GlobalLock( lzw->h_suffix );lzw->code = LZW_BASE;lzw->cur_code_len = 9;lzw->h_sour = h_sour;lzw->h_dest = h_dest;memset( lzw->lp_code, 0xFFFF, TABLE_LEN*sizeof(WORD) );}//------------------------------------------------------------------------------VOID lzw_destory(PLZW_DATA lzw){GlobalUnlock( lzw->h_code );GlobalUnlock( lzw->h_prefix );GlobalUnlock( lzw->h_suffix );GlobalFree( lzw->h_code );GlobalFree( lzw->h_prefix );GlobalFree( lzw->h_suffix );}//------------------------------------------------------------------------------#endif(2) fileio.h 定义了一些文件操作#ifndef __FILEIO_H__#define __FILEIO_H__//------------------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>//------------------------------------------------------------------------------HANDLE file_handle(CHAR* file_name){HANDLE h_file;h_file = CreateFile(file_name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,0,NULL);return h_file;}//------------------------------------------------------------------------------WORD load_buffer(HANDLE h_sour, PBUFFER_DATA buffer) // Load file to buffer{DWORD ret;ReadFile(h_sour,buffer->lp_buffer,BUFFERSIZE,&ret,NULL);buffer->index = 0;buffer->top = (WORD)ret;return (WORD)ret;}//------------------------------------------------------------------------------WORD empty_buffer( PLZW_DATA lzw, PBUFFER_DATA buffer)// Output buffer to file {DWORD ret;if(buffer->end_flag) // The flag mark the end of decode{if( buffer->by_left ){buffer->lp_buffer[ buffer->index++ ] = (BYTE)( buffer->dw_buffer >>32-buffer->by_left )<<(8-buffer->by_left);}}WriteFile(lzw->h_dest, buffer->lp_buffer,buffer->index,&ret,NULL);buffer->index = 0;buffer->top = ret;return (WORD)ret;}//------------------------------------------------------------------------------#endif(3) hash.h 定义了压缩时所用的码表操作函数,为了快速查找使用了hash算法,还有处理hash冲突的函数#ifndef __HASH_H__#define __HASH_H__//------------------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>//------------------------------------------------------------------------------#define DIV TABLE_LEN#define HASHSTEP 13 // It should bigger than 0.//------------------------------------------------------------------------------WORD get_hash_index( PLZW_DATA lzw ){DWORD tmp;WORD result;DWORD prefix;DWORD suffix;prefix = lzw->prefix;suffix = lzw->suffix;tmp = prefix<<8 | suffix;result = tmp % DIV;return result;}//------------------------------------------------------------------------------WORD re_hash_index( WORD hash ) // If hash conflict occured we must recalculate { // hash index .WORD result;result = hash + HASHSTEP;result = result % DIV;return result;}//------------------------------------------------------------------------------BOOL in_table( PLZW_DATA lzw ) // To find whether current code is already in table. {BOOL result;WORD hash;hash = get_hash_index( lzw );if( lzw->lp_code[ hash ] == 0xFFFF ){result = FALSE;}else{if( lzw->lp_prefix[ hash ] == lzw->prefix &&lzw->lp_suffix[ hash ] == lzw->suffix ){result = TRUE;}else{result = FALSE;while( lzw->lp_code[ hash ] != 0xFFFF ){if( lzw->lp_prefix[ hash ] == lzw->prefix &&lzw->lp_suffix[ hash ] == lzw->suffix ){result = TRUE;break;}hash = re_hash_index( hash );}}}return result;}//------------------------------------------------------------------------------WORD get_code( PLZW_DATA lzw ){WORD hash;WORD code;hash = get_hash_index( lzw );if( lzw->lp_prefix[ hash ] == lzw->prefix &&lzw->lp_suffix[ hash ] == lzw->suffix ){code = lzw->lp_code[ hash ];}else{while( lzw->lp_prefix[ hash ] != lzw->prefix ||lzw->lp_suffix[ hash ] != lzw->suffix ){hash = re_hash_index( hash );}code = lzw->lp_code[ hash ];}return code;}//------------------------------------------------------------------------------ VOID insert_table( PLZW_DATA lzw ){WORD hash;hash = get_hash_index( lzw );if( lzw->lp_code[ hash ] == 0xFFFF ){lzw->lp_prefix[ hash ] = lzw->prefix;lzw->lp_suffix[ hash ] = lzw->suffix;lzw->lp_code[ hash ] = lzw->code;}else{while( lzw->lp_code[ hash ] != 0xFFFF ){hash = re_hash_index( hash );}lzw->lp_prefix[ hash ] = lzw->prefix;lzw->lp_suffix[ hash ] = lzw->suffix;lzw->lp_code[ hash ] = lzw->code;}}//------------------------------------------------------------------------------ #endif(4) encode.h 压缩程序主函数#ifndef __ENCODE_H__#define __ENCODE_H__//------------------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>//------------------------------------------------------------------------------VOID output_code( DWORD code ,PBUFFER_DATA out, PLZW_DATA lzw) {out->dw_buffer |= code << ( 32 - out->by_left - lzw->cur_code_len );out->by_left += lzw->cur_code_len;while( out->by_left >= 8 ){if( out->index == BUFFERSIZE ){empty_buffer( lzw,out);}out->lp_buffer[ out->index++ ] = (BYTE)( out->dw_buffer >> 24 );out->dw_buffer <<= 8;out->by_left -= 8;}}//------------------------------------------------------------------------------VOID do_encode( PBUFFER_DATA in, PBUFFER_DATA out, PLZW_DATA lzw) {WORD prefix;while( in->index != in->top ){if( !in_table(lzw) ){// current code not in code table// then add it to table and output prefixinsert_table(lzw);prefix = lzw->suffix;output_code( lzw->prefix ,out ,lzw );lzw->code++;if( lzw->code == (WORD)1<< lzw->cur_code_len ){// code reached current code top(1<<cur_code_len) // then current code length add onelzw->cur_code_len++;if( lzw->cur_code_len == CODE_LEN + 1 ){re_init_lzw( lzw );}}}else{// current code already in code table// then output nothingprefix = get_code(lzw);}lzw->prefix = prefix;lzw->suffix = in->lp_buffer[ in->index++ ];}}//------------------------------------------------------------------------------ VOID encode(HANDLE h_sour,HANDLE h_dest){LZW_DATA lzw;BUFFER_DATA in ;BUFFER_DATA out;BOOL first_run = TRUE;lzw_create( &lzw ,h_sour,h_dest );buffer_create( &in );buffer_create( &out );while( load_buffer( h_sour, &in ) ){if( first_run ){// File length should be considered but here we simply// believe file length bigger than 2 bytes.lzw.prefix = in.lp_buffer[ in.index++ ];lzw.suffix = in.lp_buffer[ in.index++ ];first_run = FALSE;}do_encode(&in , &out, &lzw);}output_code(lzw.prefix, &out , &lzw);output_code(lzw.suffix, &out , &lzw);out.end_flag = TRUE;empty_buffer( &lzw,&out);lzw_destory( &lzw );buffer_destory( &in );buffer_destory( &out );}//------------------------------------------------------------------------------#endif(5) decode.h 解压函数主函数#ifndef __DECODE_H__#define __DECODE_H__//------------------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>//------------------------------------------------------------------------------VOID out_code( WORD code ,PBUFFER_DATA buffer,PLZW_DATA lzw,PSTACK_DATA stack){WORD tmp;if( code < 0x100 ){stack->lp_stack[ stack->index++ ] = code;}else{stack->lp_stack[ stack->index++ ] = lzw->lp_suffix[ code ];tmp = lzw->lp_prefix[ code ];while( tmp > 0x100 ){stack->lp_stack[ stack->index++ ] = lzw->lp_suffix[ tmp ];tmp = lzw->lp_prefix[ tmp ];}stack->lp_stack[ stack->index++ ] = (BYTE)tmp;}while( stack->index ){if( buffer->index == BUFFERSIZE ){empty_buffer(lzw,buffer);}buffer->lp_buffer[ buffer->index++ ] = stack->lp_stack[ --stack->index ] ; }}//------------------------------------------------------------------------------VOID insert_2_table(PLZW_DATA lzw ){lzw->lp_code[ lzw->code ] = lzw->code;lzw->lp_prefix[ lzw->code ] = lzw->prefix;lzw->lp_suffix[ lzw->code ] = lzw->suffix;lzw->code++;if( lzw->code == ((WORD)1<<lzw->cur_code_len)-1 ){lzw->cur_code_len++;if( lzw->cur_code_len == CODE_LEN+1 )lzw->cur_code_len = 9;}if(lzw->code >= 1<<CODE_LEN ){re_init_lzw(lzw);}}//------------------------------------------------------------------------------WORD get_next_code( PBUFFER_DATA buffer , PLZW_DATA lzw ) {BYTE next;WORD code;while( buffer->by_left < lzw->cur_code_len ){if( buffer->index == BUFFERSIZE )load_buffer( lzw->h_sour, buffer );}next = buffer->lp_buffer[ buffer->index++ ];buffer->dw_buffer |= (DWORD)next << (24-buffer->by_left);buffer->by_left += 8;}code = buffer->dw_buffer >> ( 32 - lzw->cur_code_len );buffer->dw_buffer <<= lzw->cur_code_len;buffer->by_left -= lzw->cur_code_len;return code;}//------------------------------------------------------------------------------VOID do_decode( PBUFFER_DATA in, PBUFFER_DATA out, PLZW_DATA lzw, PSTACK_DATA stack){WORD code;WORD tmp;while( in->index != in->top ){code = get_next_code( in ,lzw );if( code < 0x100 ){// code already in table// then simply output the codelzw->suffix = (BYTE)code;}else{if( code < lzw->code ){// code also in table// then output code chaintmp = lzw->lp_prefix[ code ];while( tmp > 0x100 ){tmp = lzw->lp_prefix[ tmp ];}lzw->suffix = (BYTE)tmp;}else// code == lzw->code// code not in table// add code into table// and out put codetmp = lzw->prefix;while( tmp > 0x100 ){tmp = lzw->lp_prefix[ tmp ];}lzw->suffix = (BYTE)tmp;}}insert_2_table( lzw );out_code(code,out,lzw,stack);lzw->prefix = code;}}//------------------------------------------------------------------------------ VOID decode( HANDLE h_sour, HANDLE h_dest ){LZW_DATA lzw;BUFFER_DATA in ;BUFFER_DATA out;STACK_DATA stack;BOOL first_run;first_run = TRUE;lzw_create( &lzw ,h_sour,h_dest );buffer_create( &in );buffer_create( &out );stack_create(&stack );while( load_buffer( h_sour, &in ) ){if( first_run ){lzw.prefix = get_next_code( &in, &lzw );lzw.suffix = lzw.prefix;out_code(lzw.prefix, &out, &lzw , &stack);first_run = FALSE;}do_decode(&in , &out, &lzw, &stack);}empty_buffer( &lzw,&out);lzw_destory( &lzw );buffer_destory( &in );buffer_destory( &out );stack_destory( &stack);}#endif2 下面给出一个应用上面模块的简单例子#include <stdio.h>#include <stdlib.h>//------------------------------------------------------------------------------#include "lzw.h"#include "hash.h"#include "fileio.h"#include "encode.h"#include "decode.h"//------------------------------------------------------------------------------ HANDLE h_file_sour;HANDLE h_file_dest;HANDLE h_file;CHAR* file_name_in = "d:\\code.c";CHAR* file_name_out= "d:\\encode.e";CHAR* file_name = "d:\\decode.d";//------------------------------------------------------------------------------ int main(int argc, char *argv[]){h_file_sour = file_handle(file_name_in);h_file_dest = file_handle(file_name_out);h_file = file_handle(file_name);encode(h_file_sour, h_file_dest); // decode(h_file_dest,h_file);CloseHandle(h_file_sour);CloseHandle(h_file_dest);CloseHandle(h_file);return 0;}。
lzw压缩算法的c语言实现
标准的LZW压缩原理:~~~~~~~~~~~~~~~~~~先来解释一下几个基本概念:LZW压缩有三个重要的对象:数据流(CharStream)、编码流(CodeStream)和编译表(String Table)。
在编码时,数据流是输入对象(图象的光栅数据序列),编码流就是输出对象(经过压缩运算的编码数据);在解码时,编码流则是输入对象,数据流是输出对象;而编译表是在编码和解码时都须要用借助的对象。
字符(Character):最基础的数据元素,在文本文件中就是一个字节,在光栅数据中就是一个像素的颜色在指定的颜色列表中的索引值;字符串(String):由几个连续的字符组成;前缀(Prefix):也是一个字符串,不过通常用在另一个字符的前面,而且它的长度可以为0;根(Root):单个长度的字符串;编码(Code):一个数字,按照固定长度(编码长度)从编码流中取出,编译表的映射值;图案:一个字符串,按不定长度从数据流中读出,映射到编译表条目.LZW压缩的原理:提取原始图象数据中的不同图案,基于这些图案创建一个编译表,然后用编译表中的图案索引来替代原始光栅数据中的相应图案,减少原始数据大小。
看起来和调色板图象的实现原理差不多,但是应该注意到的是,我们这里的编译表不是事先创建好的,而是根据原始图象数据动态创建的,解码时还要从已编码的数据中还原出原来的编译表(GIF文件中是不携带编译表信息的),为了更好理解编解码原理,我们来看看具体的处理过程:编码器(Compressor)~~~~~~~~~~~~~~~~编码数据,第一步,初始化一个编译表,假设这个编译表的大小是12位的,也就是最多有4096个单位,另外假设我们有32个不同的字符(也可以认为图象的每个像素最多有32种颜色),表示为a,b,c,d,e...,初始化编译表:第0项为a,第1项为b,第2项为c...一直到第31项,我们把这32项就称为根。
开始编译,先定义一个前缀对象Current Prefix,记为[.c.],现在它是空的,然后定义一个当前字符串Current String,标记为[.c.]k,[.c.]就为Current Prefix,k就为当前读取字符。
c语言lzw编码解码
LZW(Lempel-Ziv-Welch)是一种无损数据压缩算法。
以下是一个简单的C语言实现的LZW编码和解码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_CODE_SIZE 128typedef struct {int code;char ch;} Code;void init_codes(Code codes[]) {for (int i = 0; i < MAX_CODE_SIZE; i++) {codes[i].code = i;codes[i].ch = i;}}int next_code(Code codes[], char ch) {for (int i = 0; i < MAX_CODE_SIZE; i++) {if (codes[i].ch == ch) {return codes[i].code;}}return -1;}void compress(char *input, char *output) {Code codes[MAX_CODE_SIZE];init_codes(codes);int input_len = strlen(input);int output_index = 0;int current_code = 256;int current_len = 1;int max_len = 1;int next_index = 0;output[output_index++] = codes[current_code].ch;for (int i = 1; i < input_len; i++) {next_index = next_code(codes, input[i]);current_len++;if (next_index != -1) {current_code = next_index;} else {current_code = codes[current_code].code;codes[current_code].ch = input[i];current_code++;current_len = 1;}if (current_len > max_len) {max_len = current_len;}if (current_len == max_len && current_code < MAX_CODE_SIZE) { output[output_index++] = codes[current_code].ch;current_code++;current_len = 0;max_len = 1;}}output[output_index] = '\0';}void decompress(char *input, char *output) {Code codes[MAX_CODE_SIZE];init_codes(codes);int input_len = strlen(input);int output_index = 0;int current_code = 0;int current_len = 0;int max_len = 0;int next_index = 0;while (input[current_code] != '\0') {current_len++;next_index = next_code(codes, input[current_code]);if (next_index != -1) {current_code = next_index;} else {codes[current_code].ch = input[current_code];current_code++;current_len = 1;}if (current_len > max_len) {max_len = current_len;}if (current_len == max_len && current_code < MAX_CODE_SIZE) {output[output_index++] = codes[current_code].ch;current_code++;current_len = 0;max_len = 0;}}output[output_index] = '\0';}int main() {char input[] = "ABABABABA";char output[256];compress(input, output);printf("Compressed: %s", output);char decompressed[256];decompress(output, decompressed);printf("Decompressed: %s", decompressed);return 0;}```这个示例中,`init_codes`函数用于初始化编码表,`next_code`函数用于查找下一个编码,`compress`函数用于压缩输入字符串,`decompress`函数用于解压缩输出字符串。
用C++实现数据无损压缩、解压(使用LZW算法)
用C++实现数据无损压缩、解压(使用LZW算法)小俊发表于 2008-9-10 14:50:00推荐LZW压缩算法由Lemple-Ziv-Welch三人共同创造,用他们的名字命名。
LZW就是通过建立一个字符串表,用较短的代码来表示较长的字符串来实现压缩。
LZW压缩算法是Unisys的专利,有效期到2003年,所以对它的使用是有限制的。
字符串和编码的对应关系是在压缩过程中动态生成的,并且隐含在压缩数据中,解压的时候根据表来进行恢复,算是一种无损压缩。
个人认为LZW很适用于嵌入式系统上。
因为:1、压缩和解压速度比较快,尤其是解压速度;2、占用资源少;3、压缩比也比较理想;4、适用于文本和图像等出现连续重复字节串的数据流。
LZW算法有一点比较特别,就是压缩过程中产生的字符串对应表,不需要保存到压缩数据中,因为这个表在解压过程中能自动生成回来。
LZW算法比较简单,我是按照这本书上写的算法来编程的:以下是源代码:class LZWCoder{private:struct TStr{char *string;unsigned int len;};TStr StrTable[4097];unsigned int ItemPt;unsigned int BytePt;unsigned char BitPt;unsigned char Bit[8];unsigned char Bits;unsigned int OutBytes;void InitStrTable();void CopyStr(TStr *d, TStr s);void StrJoinChar(TStr *s, char c);unsigned int InStrTable(TStr s);void AddTableEntry(TStr s);void WriteCode(char *dest, unsigned int b);unsigned int GetNextCode(char *src);void StrFromCode(TStr *s, unsigned int c);void WriteString(char *dest, TStr s);public:unsigned int Encode(char *src, unsigned int len, char *dest);unsigned int Decode(char *src, unsigned int *len, char *dest);LZWCoder();~LZWCoder();};void LZWCoder::InitStrTable(){unsigned int i;for(i = 0; i < 256; i ++){StrTable[i].string = (char *)realloc(StrTable[i].string, 1);StrTable[i].string[0] = i;StrTable[i].len = 1;}StrTable[256].string = NULL;StrTable[256].len = 0;StrTable[257].string = NULL;StrTable[257].len = 0;ItemPt = 257;Bits = 9;}void LZWCoder::CopyStr(TStr *d, TStr s){unsigned int i;d->string = (char *)realloc(d->string, s.len);for(i = 0; i < s.len; i ++)d->string[i] = s.string[i];d->len = s.len;}void LZWCoder::StrJoinChar(TStr *s, char c){s->string = (char *)realloc(s->string, s->len + 1);s->string[s->len ++] = c;}unsigned int LZWCoder::InStrTable(TStr s){unsigned int i,j;bool b;for(i = 0; i <= ItemPt; i ++){if(StrTable[i].len == s.len){b = true;for(j = 0; j < s.len; j ++)if(StrTable[i].string[j] != s.string[j]){b = false;break;}if(b) return i;}}return 65535;}void LZWCoder::AddTableEntry(TStr s){CopyStr(&StrTable[++ItemPt], s);void LZWCoder::WriteCode(char *dest, unsigned int b){unsigned char i;for(i = 0; i < Bits; i++){Bit[BitPt ++] = (b & (1 << (Bits - i - 1))) != 0;if(BitPt == 8){BitPt = 0;dest[BytePt ++] = (Bit[0] << 7)+ (Bit[1] << 6)+ (Bit[2] << 5)+ (Bit[3] << 4)+ (Bit[4] << 3)+ (Bit[5] << 2)+ (Bit[6] << 1)+ Bit[7];}}}unsigned int LZWCoder::GetNextCode(char *src){unsigned char i;unsigned int c = 0;for(i = 0; i < Bits; i ++){c = (c << 1) + ((src[BytePt] & (1 << (8 - (BitPt ++) - 1))) ! = 0);if(BitPt == 8){BitPt = 0;BytePt ++;}}return c;void LZWCoder::StrFromCode(TStr *s, unsigned int c){CopyStr(s, StrTable[c]);}void LZWCoder::WriteString(char *dest, TStr s){unsigned int i;for(i = 0; i < s.len; i++)dest[OutBytes ++] = s.string[i];}unsigned int LZWCoder::Encode(char *src, unsigned int len, char *dest){TStr Omega, t;char k;unsigned int i;unsigned int p;BytePt = 0;BitPt = 0;InitStrTable();WriteCode(dest, 256);Omega.string = NULL;Omega.len = 0;t.string = NULL;t.len = 0;for(i = 0; i < len; i ++){k = src[i];CopyStr(&t, Omega);StrJoinChar(&t, k);if(InStrTable(t) != 65535)CopyStr(&Omega, t);else{WriteCode(dest, InStrTable(Omega));AddTableEntry(t);switch(ItemPt){case 512: Bits = 10; break;case 1024: Bits = 11; break;case 2048: Bits = 12; break;case 4096: WriteCode(dest, 256); InitStrTable();}Omega.string = (char *)realloc(Omega.string, 1);Omega.string[0] = k;Omega.len = 1;}}WriteCode(dest, InStrTable(Omega));WriteCode(dest, 257);Bits = 7;WriteCode(dest, 0);free(Omega.string);free(t.string);return BytePt;}unsigned int LZWCoder::Decode(char *src, unsigned int *len, char *dest){unsigned int code, oldcode;TStr t, s;BytePt = 0;BitPt = 0;OutBytes = 0;t.string = NULL;t.len = 0;s.string = NULL;s.len = 0;InitStrTable();while((code = GetNextCode(src)) != 257){if(code == 256){InitStrTable();code = GetNextCode(src);if(code == 257) break;StrFromCode(&s, code);WriteString(dest, s);oldcode = code;}else{if(code <= ItemPt){StrFromCode(&s, code);WriteString(dest, s);StrFromCode(&t, oldcode);StrJoinChar(&t, s.string[0]);AddTableEntry(t);switch(ItemPt){case 511: Bit s = 10; break;case 1023: Bi ts = 11; break;case 2047: Bi ts = 12; break;}oldcode = code;}else{StrFromCode(&s, oldcode);StrJoinChar(&s, s.string[0]);WriteString(dest, s);AddTableEntry(s);switch(ItemPt){case 511: Bit s = 10; break;case 1023: Bi ts = 11; break;case 2047: Bi ts = 12; break;}oldcode = code;}}}free(t.string);free(s.string);*len = BytePt + (BitPt != 0);return OutBytes;}LZWCoder::LZWCoder(){unsigned int i;for(i = 0; i < 4097; i ++){StrTable[i].string = NULL;StrTable[i].len = 0;}}LZWCoder::~LZWCoder(){unsigned int i;for(i = 0; i < 4097; i ++)free(StrTable[i].string);}用法:LZWCoder *Coder;Coder = new LZWCoder();然后用Coder->Encode(char *src, unsigned int len, char *dest);Coder->Decode(char *src, unsigned int *len, char *dest);进行压缩或解压。
LZW编码
实验2 用C语言实现LZW编码1.实验目的1)通过实验进一步掌握LZW编码的原理2)能正确C语言实现LZW编、解码2.实验要求给出字符,能正确输出编码,并能进行译码3.实验内容1)编码过程LZW编码是围绕称为词典的转换表来完成的。
这张转换表用来存放称为前缀(Prefix)的字符序列,并且为每个表项分配一个码字(Code word),或者叫做序号,如表6所示。
这张转换表实际上是把8位ASCII字符集进行扩充,增加的符号用来表示在文本或图像中出现的可变长度ASCII字符串。
扩充后的代码可用9位、10位、11位、12位甚至更多的位来表示。
Welch的论文中用了12位,12位可以有4096个不同的12位代码,这就是说,转换表有4096个表项,其中256个表项用来存放已定义的字符,剩下3840个表项用来存放前缀(Prefix)。
表6 词典LZW编码器(软件编码器或硬件编码器)就是通过管理这个词典完成输入与输出之间的转换。
LZW编码器的输入是字符流(Charstream),字符流可以是用8位ASCII字符组成的字符串,而输出是用n位(例如12位)表示的码字流(Codestream),码字代表单个字符或多个字符组成的字符串。
LZW编码器使用了一种很实用的分析(parsing)算法,称为贪婪分析算法(greedy parsing algorithm)。
在贪婪分析算法中,每一次分析都要串行地检查来自字符流(Charstream)的字符串,从中分解出已经识别的最长的字符串,也就是已经在词典中出现的最长的前缀(Prefix)。
用已知的前缀(Prefix)加上下一个输入字符C也就是当前字符(Current character)作为该前缀的扩展字符,形成新的扩展字符串——缀-符串(String):Prefix.C。
这个新的缀-符串(String)是否要加到词典中,还要看词典中是否存有和它相同的缀-符串String。
如果有,那么这个缀-符串(String)就变成前缀(Prefix),继续输入新的字符,否则就把这个缀-符串(String)写到词典中生成一个新的前缀(Prefix),并给一个代码。
LZW编码算法详解
LZW编码算法详解LZW(Lempel-Ziv & Welch)编码又称字串表编码,是Welch将Lemple和Ziv所提出来的无损压缩技术改进后的压缩方法。
GIF图像文件采用的是一种改良的LZW 压缩算法,通常称为GIF-LZW压缩算法。
下面简要介绍GIF-LZW的编码与解码方程解:例现有来源于二色系统的图像数据源(假设数据以字符串表示):aabbbaabb,试对其进行LZW编码及解码。
1)根据图像中使用的颜色数初始化一个字串表(如表1),字串表中的每个颜色对应一个索引。
在初始字串表的LZW_CLEAR和LZW_EOI分别为字串表初始化标志和编码结束标志。
设置字符串变量S1、S2并初始化为空。
2)输出LZW_CLEAR在字串表中的索引3H(见表2第一行)。
3)从图像数据流中第一个字符开始,读取一个字符a,将其赋给字符串变量S2。
判断S1+S2=“a”在字符表中,则S1=S1+S2=“a”(见表2第二行)。
4)读取图像数据流中下一个字符a,将其赋给字符串变量S2。
判断S1+S2=“aa”不在字符串表中,输出S1=“a”在字串表中的索引0H,并在字串表末尾为S1+S2="aa"添加索引4H,且S1=S2=“a”(见表2第三行)。
5)读下一个字符b赋给S2。
判断S1+S2=“ab”不在字符串表中,输出S1=“a”在字串表中的索引0H,并在字串表末尾为S1+S2=“ab”添加索引5H,且S1=S2=“b”(见表2第四行)。
6)读下一个字符b赋给S2。
S1+S2=“bb”不在字串表中,输出S1=“b”在字串表中的索引1H,并在字串表末尾为S1+S2=“bb”添加索引6H,且S1=S2=“b”(见表2第五行)。
7)读字符b赋给S2。
S1+S2=“bb”在字串表中,则S1=S1+S2=“bb”(见表2第六行)。
8)读字符a赋给S2。
S1+S2=“bba”不在字串表中,输出S1=“bb”在字串表中的索引6H,并在字串表末尾为S1+S2=“bba”添加索引7H,且S1=S2=“a”(见表2第七行)。
LZW压缩算法C#源码
LZW压缩算法C#源码using System;using System.IO;namespace ponents{public class LZWEncoder{private static readonly int EOF = -1;private int imgW, imgH;private byte[] pixAry;private int initCodeSize;private int remaining;private int curPixel;// GIFCOMPR.C - GIF Image compression routines//// Lempel-Ziv compression based on 'compress'. GIF modifications by// David Rowley (mgardi@)// General DEFINEsstatic readonly int BITS = 12;static readonly int HSIZE = 5003; // 80% occupancy// GIF Image compression - modified 'compress'//// Based on: compress.c - File compression ala IEEE Computer, June 1984.//// By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)// Jim McKie (decvax!mcvax!jim)// Steve Davies (decvax!vax135!petsd!peora!srd)// Ken Turkowski (decvax!decwrl!turtlevax!ken)// James A. Woods (decvax!ihnp4!ames!jaw)// Joe Orost (decvax!vax135!petsd!joe)int n_bits; // number of bits/codeint maxbits = BITS; // user settable max # bits/codeint maxcode; // maximum code, given n_bitsint maxmaxcode = 1 << BITS; // should NEVER generate this codeint[] htab = new int[HSIZE];//这个是放hash的筒⼦,在这⾥⾯可以很快的找到1个keyint[] codetab = new int[HSIZE];int hsize = HSIZE; // for dynamic table sizingint free_ent = 0; // first unused entry// block compression parameters -- after all codes are used up,// and compression rate changes, start over.bool clear_flg = false;// Algorithm: use open addressing double hashing (no chaining) on the// prefix code / next character combination. We do a variant of Knuth's// algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime// secondary probe. Here, the modular division first probe is gives way// to a faster exclusive-or manipulation. Also do block compression with// an adaptive reset, whereby the code table is cleared when the compression// ratio decreases, but after the table fills. The variable-length output// codes are re-sized at this point, and a special CLEAR code is generated// for the decompressor. Late addition: construct the table according to// file size for noticeable speed improvement on small files. Please direct// questions about this implementation to ames!jaw.int g_init_bits;int ClearCode;int EOFCode;// output//// Output the given code.// Inputs:// code: A n_bits-bit integer. If == -1, then EOF. This assumes// that n_bits =< wordsize - 1.// Outputs:// Outputs code to the file.// Assumptions:// Chars are 8 bits long.// Algorithm:// Maintain a BITS character long buffer (so that 8 codes will// fit in it exactly). Use the VAX insv instruction to insert each// code in turn. When the buffer fills up empty it and start over.int cur_accum = 0;int cur_bits = 0;int [] masks ={0x0000,0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,0x00FF,0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF,0xFFFF };// Number of characters so far in this 'packet'int a_count;// Define the storage for the packet accumulatorbyte[] accum = new byte[256];//----------------------------------------------------------------------------public LZWEncoder(int width, int height, byte[] pixels, int color_depth) {imgW = width;imgH = height;pixAry = pixels;initCodeSize = Math.Max(2, color_depth);}// Add a character to the end of the current packet, and if it is 254// characters, flush the packet to disk.void Add(byte c, Stream outs){accum[a_count++] = c;if (a_count >= 254)Flush(outs);}// Clear out the hash table// table clear for block compressvoid ClearTable(Stream outs){ResetCodeTable(hsize);free_ent = ClearCode + 2;clear_flg = true;Output(ClearCode, outs);}// reset code table// 全部初始化为-1void ResetCodeTable(int hsize){for (int i = 0; i < hsize; ++i)htab[i] = -1;}void Compress(int init_bits, Stream outs){int fcode;int i /* = 0 */;int c;int ent;int disp;int hsize_reg;int hshift;// Set up the globals: g_init_bits - initial number of bits//原始数据的字长,在gif⽂件中,原始数据的字长可以为1(单⾊图),4(16⾊),和8(256⾊)//开始的时候先加上1//但是当原始数据长度为1的时候,开始为3//因此原始长度1->3,4->5,8->9//?为何原始数据字长为1的时候,开始长度为3呢??//如果+1=2,只能表⽰四种状态,加上clearcode和endcode就⽤完了。
实验二 LZW编码算法的实现
实验二LZW编码算法的实现一、实验目的1、学习Matlab软件的使用和编程2、进一步深入理解LZW编码算法的原理二、实验内容阅读Matlab代码,画原理图。
三、实验原理LZW算法中,首先建立一个字符串表,把每一个第一次出现的字符串放入串表中,并用一个数字来表示,这个数字与此字符串在串表中的位置有关,并将这个数字存入压缩文件中,如果这个字符串再次出现时,即可用表示它的数字来代替,并将这个数字存入文件中。
压缩完成后将串表丢弃。
如"print"字符串,如果在压缩时用266表示,只要再次出现,均用266表示,并将"print"字符串存入串表中,在图象解码时遇到数字266,即可从串表中查出266所代表的字符串"print",在解压缩时,串表可以根据压缩数据重新生成。
四、LZW编码的Matlab源程序及运行结果function lzw_test(binput)if(nargin<1)binput=false;elsebinput=true;end;if binputn=0;while(n==0)P=input('please input a string:','s')%提示输入界面n=length(P);end;else%Tests the special decoder caseP='Another problem on long files is that frequently the compression ratio begins...';end;lzwInput=uint8(P);[lzwOutput,lzwTable]=norm2lzw(lzwInput);[lzwOutput_decode,lzwTable_decode]=lzw2norm(lzwOutput);fprintf('\n');fprintf('Input:');%disp(P);%fprintf('%02x',lzwInput);fprintf('%s',num2str(lzwInput));fprintf('\n');fprintf('Output:');%fprintf('%02x',lzwOutput);fprintf('%s',num2str(lzwOutput));fprintf('\n');fprintf('Output_decode:');%fprintf('%02x',lzwOutput);fprintf('%s',num2str(lzwOutput_decode));fprintf('\n');fprintf('\n');for ii=257:length(lzwTable.codes)fprintf('Output_encode---Code:%s,LastCode%s+%s Length%3d\n',num2str(ii), num2str(lzwTable.codes(ii).lastCode),...num2str(lzwTable.codes(ii).c),lzwTable.codes(ii).codeLength)fprintf('Output_decode---Code:%s,LastCode%s+%s Length%3d\n',num2str(ii), num2str(lzwTable_decode.codes(ii).lastCode),...num2str(lzwTable_decode.codes(ii).c),lzwTable_decode.codes(ii).codeLength) end;function[output,table]=lzw2norm(vector,maxTableSize,restartTable)%LZW2NORM LZW Data Compression(decoder)%For vectors,LZW2NORM(X)is the uncompressed vector of X using the LZW algorithm. %[...,T]=LZW2NORM(X)returns also the table that the algorithm produces.%%For matrices,X(:)is used as input.%%maxTableSize can be used to set a maximum length of the table.Default%is4096entries,use Inf for ual sizes are12,14and16%bits.%%If restartTable is specified,then the table is flushed when it reaches%its maximum size and a new table is built.%%Input must be of uint16type,while the output is a uint8.%Table is a cell array,each element containig the corresponding code.%%This is an implementation of the algorithm presented in the article%%See also NORM2LZW%$Author:Giuseppe Ridino'$%$Revision:1.0$$Date:10-May-200414:16:08$%How it decodes:%%Read OLD_CODE%output OLD_CODE%CHARACTER=OLD_CODE%WHILE there are still input characters DO%Read NEW_CODE%IF NEW_CODE is not in the translation table THEN%STRING=get translation of OLD_CODE%STRING=STRING+CHARACTER%ELSE%STRING=get translation of NEW_CODE%END of IF%output STRING%CHARACTER=first character in STRING%add translation of OLD_CODE+CHARACTER to the translation table%OLD_CODE=NEW_CODE%END of WHILE%Ensure to handle uint8input vector and convert%to a rowif~isa(vector,'uint16'),error('input argument must be a uint16vector')Endvector=vector(:)';if(nargin<2)maxTableSize=4096;restartTable=0;end;if(nargin<3)restartTable=0;end;function code=findCode(lastCode,c)%Look up code value%if(isempty(lastCode))%fprintf('findCode:----+%02x=',c);%else%fprintf('findCode:%04x+%02x=',lastCode,c);%end;if(isempty(lastCode))code=c+1;%fprintf('%04x\n',code);return;Elseii=table.codes(lastCode).prefix;jj=find([table.codes(ii).c]==c);code=ii(jj);%if(isempty(code))%fprintf('----\n');%else%fprintf('%04x\n',code);%end;return;end;Endfunction[]=addCode(lastCode,c)%Add a new code to the tablee.c=c;%NB using variable in parent to avoid allocation coststCode=lastCode;e.prefix=[];e.codeLength=table.codes(lastCode).codeLength+1;table.codes(table.nextCode)=e;table.codes(lastCode).prefix=[table.codes(lastCode).prefix table.nextCode];table.nextCode=table.nextCode+1;%if(isempty(lastCode))%fprintf('addCode:----+%02x=%04x\n',c,table.nextCode-1);%else%fprintf('addCode:%04x+%02x=%04x\n',lastCode,c,table.nextCode-1);%end;Endfunction str=getCode(code)%Output the string for a codel=table.codes(code).codeLength;str=zeros(1,l);for ii=l:-1:1str(ii)=table.codes(code).c;code=table.codes(code).lastCode;end;Endfunction[]=newTable%Build the initial table consisting of all codes of length1.The strings%are stored as prefixCode+character,so that testing is very quick.To%speed up searching,we store a list of codes that each code is the prefix%for.e.c=0;stCode=-1;e.prefix=[];e.codeLength=1;table.nextCode=2;if(~isinf(maxTableSize))table.codes(1:maxTableSize)=e;%Pre-allocate for speedElsetable.codes(1:65536)=e;%Pre-allocate for speedend;for c=1:255e.c=c;stCode=-1;e.prefix=[];e.codeLength=1;table.codes(table.nextCode)=e;table.nextCode=table.nextCode+1;end;End%%Main loop%e.c=0;stCode=-1;e.prefix=[];e.codeLength=1;newTable;output=zeros(1,3*length(vector),'uint8');%assume compression of33%outputIndex=1;lastCode=vector(1);output(outputIndex)=table.codes(vector(1)).c;outputIndex=outputIndex+1;character= table.codes(vector(1)).c;、、tic;for vectorIndex=2:length(vector),%if mod(vectorIndex,1000)==0%fprintf('Index:%5d,Time%.1fs,Table Length%4d,Complete%.1f%%\n', outputIndex,toc,table.nextCode-1,vectorIndex/length(vector)*100);%*ceil(log2(size(table, 2)))/8);%tic;%end;element=vector(vectorIndex);if(element>=table.nextCode)%add codes not in table,a special case.str=[getCode(lastCode)character];else,str=getCode(element);Endoutput(outputIndex+(0:length(str)-1))=str;outputIndex=outputIndex+length(str);if((length(output)-outputIndex)<1.5*(length(vector)-vectorIndex))output=[output zeros(1,3*(length(vector)-vectorIndex),'uint8')];end;if(length(str)<1)keyboard;end;character=str(1);if(table.nextCode<=maxTableSize)addCode(lastCode,character);if(restartTable&&table.nextCode==maxTableSize+1)%fprintf('New table\n');newTable;end;end;lastCode=element;end;output=output(1:outputIndex-1);table.codes=table.codes(1:table.nextCode-1);Endfunction[output,table]=norm2lzw(vector,maxTableSize,restartTable)%NORM2LZW LZW Data Compression Encoder%For vectors,NORM2LZW(X)is the compressed vector of X using the LZW algorithm. %[...,T]=NORM2LZW(X)returns also the table that the algorithm produces.%For matrices,X(:)is used as input.%maxTableSize can be used to set a maximum length of the table.Default%is4096entries,use Inf for ual sizes are12,14and16%bits.%If restartTable is specified,then the table is flushed when it reaches%its maximum size and a new table is built.%Input must be of uint8type,while the output is a uint16.%Table is a cell array,each element containing the corresponding code.%This is an implementation of the algorithm presented in the article%See also LZW2NORM%$Author:Giuseppe Ridino'$%$Revision:1.0$$Date:10-May-200414:16:08$%Revision:%Change the code table structure to improve the performance.%date:22-Apr-2007%by:Haiyong Xu%Rework the code table completely to get reasonable performance.%date:24-Jun-2007%by:Duncan Barclay%How it encodes:%STRING=get input character%WHILE there are still input characters DO%CHARACTER=get input character%IF STRING+CHARACTER is in the string table then%STRING=STRING+character%ELSE%output the code for STRING%add STRING+CHARACTER to the string table%STRING=CHARACTER%END of IF%END of WHILE%output the code for STRING%Ensure to handle uint8input vector and convert%to a double row to make maths workif~isa(vector,'uint8'),error('input argument must be a uint8vector')Endvector=double(vector(:)');if(nargin<2)maxTableSize=4096;restartTable=0;end;if(nargin<3)restartTable=0;end;function code=findCode(lastCode,c)%Look up code value%if(isempty(lastCode))%fprintf('findCode:----+%02x=',c);%else%fprintf('findCode:%04x+%02x=',lastCode,c);%end;if(isempty(lastCode))code=c+1;%fprintf('%04x\n',code);return;Elseii=table.codes(lastCode).prefix;jj=find([table.codes(ii).c]==c);code=ii(jj);%if(isempty(code))%fprintf('----\n');%else%fprintf('%04x\n',code);%end;return;end;code=[];return;Endfunction[]=addCode(lastCode,c)%Add a new code to the tablee.c=c;%NB using variable in parent to avoid allocation coststCode=lastCode;e.prefix=[];e.codeLength=table.codes(lastCode).codeLength+1;table.codes(table.nextCode)=e;table.codes(lastCode).prefix=[table.codes(lastCode).prefix table.nextCode];table.nextCode=table.nextCode+1;%if(isempty(lastCode))%fprintf('addCode:----+%02x=%04x\n',c,table.nextCode-1);%else%fprintf('addCode:%04x+%02x=%04x\n',lastCode,c,table.nextCode-1);%end;Endfunction[]=newTable%Build the initial table consisting of all codes of length1.The strings%are stored as prefixCode+character,so that testing is very quick.To%speed up searching,we store a list of codes that each code is the prefix%for.e.c=0;stCode=-1;e.prefix=[];e.codeLength=1;table.nextCode=2;if(~isinf(maxTableSize))table.codes(1:maxTableSize)=e;%Pre-allocate for speedElsetable.codes(1:65536)=e;%Pre-allocate for speedend;for c=1:255e.c=c;stCode=-1;e.prefix=[];e.codeLength=1;table.codes(table.nextCode)=e;table.nextCode=table.nextCode+1;end;End%%Main loop%e.c=0;stCode=-1;e.prefix=[];e.codeLength=1;newTable;output=vector;outputIndex=1;lastCode=[];tic;for index=1:length(vector),%if mod(index,1000)==0%fprintf('Index:%5d,Time%.1fs,Table Length%4d,Ratio%.1f%%\n',index,toc, table.nextCode-1,outputIndex/index*100);%*ceil(log2(size(table,2)))/8);%tic;%end;code=findCode(lastCode,vector(index));if~isempty(code)lastCode=code;Elseoutput(outputIndex)=lastCode;outputIndex=outputIndex+1;%fprintf('output****:%04x\n',lastCode);if(table.nextCode<=maxTableSize)addCode(lastCode,vector(index));if(restartTable&&table.nextCode==maxTableSize+1)%fprintf('New table\n');newTable;end;end;lastCode=findCode([],vector(index));end;end;output(outputIndex)=lastCode;output((outputIndex+1):end)=[];output=uint16(output);table.codes=table.codes(1:table.nextCode-1);End五、运行结果1、请写下实验结果Input:111111111111111111111111111111111111111111111111111111111111111111111111111111 Output:?????????????????????????????Input:123123123123123123123123123123123123123123123123123123123123123123123 Output:?????????????????????????????2、请在实验代码中加入计算压缩比例的代码,并显示上述两种输入的不同压缩比。
多媒体技术LZW编码实验报告(word文档良心出品)
多媒体技术LZW编码实验报告班级姓名学号实验名称:LZW算法的编程实现实验内容:用C++语言编写程序来实现LZW算法一、LZW定义:LZW就是通过建立一个字符串表,用较短的代码来表示较长的字符串来实现压缩. 字符串和编码的对应关系是在压缩过程中动态生成的,并且隐含在压缩数据中,解压的时候根据表来进行恢复,算是一种无损压缩.在本次实验中我们就进行了LZW编码以及译码简单算法的编写。
LZW编码又称字串表编码,是无损压缩技术改进后的压缩方法。
它采用了一种先进的串表压缩,将每个第一次出现的串放在一个串表当中,用一个数字来表示串,压缩文件只进行数字的存贮,则不存贮串,从而使图像文件的压缩效率得到了较大的提高。
LZW编码算法的原理是首先建立一个词典,即跟缀表。
对于字符串流,我们要进行分析,从词典中寻找最长匹配串,即字符串P在词典中,而字符串P+后一个字符C不在词典中。
此时,输出P对应的码字,将P+C放入词典中。
经过老师的举例,我初步知道了对于一个字符串进行编码的过程。
二、编码的部分算法与分析如下:首先根据需要得建立一个初始化词典。
这里字根分别为 A B C。
具体的初始化算法如下:void init()//词典初始化{dic[0]="A";dic[1]="B";dic[2]="C";//字根为A,B,Cfor(int i=3;i<30;i++)//其余为空{dic[i]="";}}对于编码算法的建立,则需先建立一个查找函数,用于查找返回序号:int find(string s){int temp=-1;for(int i=0;i<30;i++){if(dic[i]==s) temp=i+1;}return temp;}接下来就可以编写编码算法了。
void code(string str){init();//初始化char temp[2];temp[0]=str[0];//取第一个字符temp[1]='\0';string w=temp;int i=1;int j=3;//目前字典存储的最后一个位置cout<<"\n 编码为:";for(;;){char t[2];t[0]=str[i];//取下一字符t[1]='\0';string k=t;if(k=="") //为空,字符串结束{cout<<" "<<find(w);break;//退出for循环,编码结束}if(find(w+k)>-1){w=w+k;i++;}else{cout<<" "<<find(w);string wk=w+k;dic[j++]=wk;w=k;i++;}}cout<<endl;for(i=0;i<j;i++){cout<<setw(45)<<i+1<<setw(12)<<dic[i]<<endl;}cout<<endl;}三、译码是编码的逆过程:在译码中根缀表仍为A,B,C。
C++实现lzw编码的简单方案
C++实现lzw编码的简单方案#include#include#include#includestruct stringcode{ char string[50];int len;};int ISINDic(stringcode str,stringcode dict[50],int len2)//判断出字符串若在,并返回字典中的位置{ for(int i=0;i<len2;i++)if(dict[i].len==str.len&&strnicmp(dict[i].string,str.string,str.le n)==0)return i+1;return 0;}//判断字符是否在字典中int ISINDic(char str,stringcode dict[50],int len2){ for(int i=1;i<=len2;i++){ if(dict[i-1].len==1&&str==dict[i-1].string[0])return 1;}return 0;}void main(){ int choice,yima[50];int i,j,k,len2=0,m;stringcode zifudata,dict[50],profix;for(i=0;i<50;i++){zifudata.string[i]=0;}for(i=0;i<50;i++){dict[i].len =0;}for(i=0;i<50;i++){yima[i]=0;}cout<<"_____________________LZW算法__________________________"<<endl;cout<<"+++++++++++++++++++++++++++++++++ +++++++++++++++++++++"<<endl;cout<<"学号:0811100211———————姓名:樊军———————"<<endl;cout<<"+++++++++++++++++++++++++++++++++ +++++++++++++++++++++"<<endl;cout<<"请输入所需的功能1:编码 2:译码"<<endl;cin>>choice;if (choice==1) //该段实现编码————————————————————————{cout<<"please input the stringstream"<<endl;cin>>zifudata.string;zifudata.len=strlen(zifudata.string);dict[0].string[0]=zifudata.string[0];dict[0].len=1;int len2=1;for (i=1;i{ if (ISINDic(zifudata.string[i],dict,len2)==0){ dict[len2].len++;dict[len2].string[0]=zifudata.string[i];len2++;}}//此处将不断循环以判断和添加字典中 //编码profix.len=0;j=0;k=1;while(j{ stringcode profixc; //2、保存Profix对应的词典码字(索引)到yima[50]。
LZW编码算法
班级 __ __ 学号__姓名 __ ___评分__________1.实验名称LZW编码与解码算法2.实验目的2.1通过实验进一步掌握LZW编码的原理;2.2 用C/C++等高级程序设计语言实现LZW编码。
3.实验内容步骤或记录(包括源程序或流程和说明等)3.1 实验原理(1)在压缩过程中动态形成一个字符列表(字典)。
(2)每当压缩扫描图像发现一个词典中没有的字符序列,就把该字符序列存到字典中,并用字典的地址(编码)作为这个字符序列的代码,替换原图像中的字符序列,下次再碰到相同的字符序列,就用字典的地址代替字符序列3.2实验步骤LZW编码算法的具体执行步骤如下:步骤1:开始时的词典包含所有可能的根(Root),而当前前缀P是空的;步骤2:当前字符(C) :=字符流中的下一个字符;步骤3:判断缀-符串P+C是否在词典中(1) 如果“是”:P := P+C // (用C扩展P) ;(2) 如果“否”①把代表当前前缀P的码字输出到码字流;②把缀-符串P+C添加到词典;③令P := C //(现在的P仅包含一个字符C);步骤4:判断码字流中是否还有码字要译(1) 如果“是”,就返回到步骤2;(2) 如果“否”①把代表当前前缀P的码字输出到码字流;②结束。
3.3 源程序#include<iostream>#include<string>using namespace std;const int N=200;class LZW{private: string Dic[200];//存放词典int code[N];//存放编码过的码字public: LZW(){//设置词典根Dic[0]='a';Dic[1]='b';Dic[2]='c';string *p=Dic;//定义指针指向词典中的字符} void Bianma(string cs[N]);//进行编码int IsDic(string e);//判断是否在词典中int codeDic(string f);void display(int g);//显示结果};void LZW::Bianma(string cs[N]){string P,C,K;P=cs[0];int l=0;for(int i=1;i<N;i++){C=cs[i];//当前字符(C) :=字符流中的下一个字符 K=P+C;if(IsDic(K)) P=K;//P+C在词典中,用C扩展P else{//P+C不在词典中code[l]=codeDic(P);Dic[3+l]=K;//将P+C加入词典P=C;l++;}if(N-1==i)//如果字符流中没有字符需要编码code[l]=codeDic(P);}display(l);}int LZW::IsDic(string e){//如果字符流中还有字符需要编码for(int b=0; b<200; b++){ if(e==Dic[b]) return 1; }return 0;}int LZW::codeDic(string f){int w=0;for(int y=0;y<200;y++)if(f==Dic[y]){w=y+1;break;}return w;}void LZW::display(int g){cout<<"经过LZW编码后的码字如下:"<<endl;for(int i=0;i<=g;i++)cout<<code[i];cout<<endl;cout<<"经LZW编码后的词典如下:"<<endl;for(int r=0;r<g+3;r++)cout<<r+1<<Dic[r]<<endl;}int main(){LZW t;string CSstream[N];// 存放要进行LZW编码的字符序列int length;// 要进行LZW编码的字符序列长度cout<<"请输入所求码子序列的长度:";cin>>length;while(length>=N){cout<<"该长度太长,请重新输入:";cin>>length;}cout<<"请输入要进行LZW编码的字符序列:"<<endl; for(int a=0;a<length;a++)cin>>CSstream[a];t.Bianma(CSstream);return 0;}4.实验环境(包括软、硬件平台)硬件:装有32M以上内存MPC;软件:Windows XP操作系统、Visual C++高级语言环境。
用C++实现数据无损压缩、解压(使用LZW算法)
用C++实现数据无损压缩、解压(使用LZW算法)小俊发表于 2008-9-10 14:50:00推荐LZW压缩算法由Lemple-Ziv-Welch三人共同创造,用他们的名字命名。
LZW就是通过建立一个字符串表,用较短的代码来表示较长的字符串来实现压缩。
LZW压缩算法是Unisys的专利,有效期到2003年,所以对它的使用是有限制的。
字符串和编码的对应关系是在压缩过程中动态生成的,并且隐含在压缩数据中,解压的时候根据表来进行恢复,算是一种无损压缩。
个人认为LZW很适用于嵌入式系统上。
因为:1、压缩和解压速度比较快,尤其是解压速度;2、占用资源少;3、压缩比也比较理想;4、适用于文本和图像等出现连续重复字节串的数据流。
LZW算法有一点比较特别,就是压缩过程中产生的字符串对应表,不需要保存到压缩数据中,因为这个表在解压过程中能自动生成回来。
LZW算法比较简单,我是按照这本书上写的算法来编程的:以下是源代码:class LZWCoder{private:struct TStr{char *string;unsigned int len;};TStr StrTable[4097];unsigned int ItemPt;unsigned int BytePt;unsigned char BitPt;unsigned char Bit[8];unsigned char Bits;unsigned int OutBytes;void InitStrTable();void CopyStr(TStr *d, TStr s);void StrJoinChar(TStr *s, char c);unsigned int InStrTable(TStr s);void AddTableEntry(TStr s);void WriteCode(char *dest, unsigned int b);unsigned int GetNextCode(char *src);void StrFromCode(TStr *s, unsigned int c);void WriteString(char *dest, TStr s);public:unsigned int Encode(char *src, unsigned int len, char *dest);unsigned int Decode(char *src, unsigned int *len, char *dest);LZWCoder();~LZWCoder();};void LZWCoder::InitStrTable(){unsigned int i;for(i = 0; i < 256; i ++){StrTable[i].string = (char *)realloc(StrTable[i].string, 1);StrTable[i].string[0] = i;StrTable[i].len = 1;}StrTable[256].string = NULL;StrTable[256].len = 0;StrTable[257].string = NULL;StrTable[257].len = 0;ItemPt = 257;Bits = 9;}void LZWCoder::CopyStr(TStr *d, TStr s){unsigned int i;d->string = (char *)realloc(d->string, s.len);for(i = 0; i < s.len; i ++)d->string[i] = s.string[i];d->len = s.len;}void LZWCoder::StrJoinChar(TStr *s, char c){s->string = (char *)realloc(s->string, s->len + 1);s->string[s->len ++] = c;}unsigned int LZWCoder::InStrTable(TStr s){unsigned int i,j;bool b;for(i = 0; i <= ItemPt; i ++){if(StrTable[i].len == s.len){b = true;for(j = 0; j < s.len; j ++)if(StrTable[i].string[j] != s.string[j]){b = false;break;}if(b) return i;}}return 65535;}void LZWCoder::AddTableEntry(TStr s){CopyStr(&StrTable[++ItemPt], s);void LZWCoder::WriteCode(char *dest, unsigned int b){unsigned char i;for(i = 0; i < Bits; i++){Bit[BitPt ++] = (b & (1 << (Bits - i - 1))) != 0;if(BitPt == 8){BitPt = 0;dest[BytePt ++] = (Bit[0] << 7)+ (Bit[1] << 6)+ (Bit[2] << 5)+ (Bit[3] << 4)+ (Bit[4] << 3)+ (Bit[5] << 2)+ (Bit[6] << 1)+ Bit[7];}}}unsigned int LZWCoder::GetNextCode(char *src){unsigned char i;unsigned int c = 0;for(i = 0; i < Bits; i ++){c = (c << 1) + ((src[BytePt] & (1 << (8 - (BitPt ++) - 1))) ! = 0);if(BitPt == 8){BitPt = 0;BytePt ++;}}return c;void LZWCoder::StrFromCode(TStr *s, unsigned int c){CopyStr(s, StrTable[c]);}void LZWCoder::WriteString(char *dest, TStr s){unsigned int i;for(i = 0; i < s.len; i++)dest[OutBytes ++] = s.string[i];}unsigned int LZWCoder::Encode(char *src, unsigned int len, char *dest){TStr Omega, t;char k;unsigned int i;unsigned int p;BytePt = 0;BitPt = 0;InitStrTable();WriteCode(dest, 256);Omega.string = NULL;Omega.len = 0;t.string = NULL;t.len = 0;for(i = 0; i < len; i ++){k = src[i];CopyStr(&t, Omega);StrJoinChar(&t, k);if(InStrTable(t) != 65535)CopyStr(&Omega, t);else{WriteCode(dest, InStrTable(Omega));AddTableEntry(t);switch(ItemPt){case 512: Bits = 10; break;case 1024: Bits = 11; break;case 2048: Bits = 12; break;case 4096: WriteCode(dest, 256); InitStrTable();}Omega.string = (char *)realloc(Omega.string, 1);Omega.string[0] = k;Omega.len = 1;}}WriteCode(dest, InStrTable(Omega));WriteCode(dest, 257);Bits = 7;WriteCode(dest, 0);free(Omega.string);free(t.string);return BytePt;}unsigned int LZWCoder::Decode(char *src, unsigned int *len, char *dest){unsigned int code, oldcode;TStr t, s;BytePt = 0;BitPt = 0;OutBytes = 0;t.string = NULL;t.len = 0;s.string = NULL;s.len = 0;InitStrTable();while((code = GetNextCode(src)) != 257){if(code == 256){InitStrTable();code = GetNextCode(src);if(code == 257) break;StrFromCode(&s, code);WriteString(dest, s);oldcode = code;}else{if(code <= ItemPt){StrFromCode(&s, code);WriteString(dest, s);StrFromCode(&t, oldcode);StrJoinChar(&t, s.string[0]);AddTableEntry(t);switch(ItemPt){case 511: Bit s = 10; break;case 1023: Bi ts = 11; break;case 2047: Bi ts = 12; break;}oldcode = code;}else{StrFromCode(&s, oldcode);StrJoinChar(&s, s.string[0]);WriteString(dest, s);AddTableEntry(s);switch(ItemPt){case 511: Bit s = 10; break;case 1023: Bi ts = 11; break;case 2047: Bi ts = 12; break;}oldcode = code;}}}free(t.string);free(s.string);*len = BytePt + (BitPt != 0);return OutBytes;}LZWCoder::LZWCoder(){unsigned int i;for(i = 0; i < 4097; i ++){StrTable[i].string = NULL;StrTable[i].len = 0;}}LZWCoder::~LZWCoder(){unsigned int i;for(i = 0; i < 4097; i ++)free(StrTable[i].string);}用法:LZWCoder *Coder;Coder = new LZWCoder();然后用Coder->Encode(char *src, unsigned int len, char *dest);Coder->Decode(char *src, unsigned int *len, char *dest);进行压缩或解压。
LZW编码编程实现(C++版)
LZW编码的编程和实现一、实验目的编写源程序,实现LZW的编码和解码二、实验要求1.编码输入若干字母(如abbababac),输出相应的编码2.解码输入若干数字(如122473),输出相应的字母三、编程思想1.编码根缀表已知1 A2 B3 C编码分析字符串流,从词典中寻找最长匹配串,即字符串P在词典中,而字符串P+后一个字符C不在词典中此时,输出P对应的码字,将P+C放入词典中。
如第一步:输入A此时,A在表中,而AB不在表中,则输出A对应的码字1,同时将AB写入表中,此时表为1 A2 B3 C4 AB编码输出为1 (A已编码)第二步,输入B,B在词典中,而BB不在词典中,则输出2,将BB写入表中,此时表为1 A2 B3 C4 AB5 BB编码输出为12 (AB已经编码)....2.解码根缀表为1 A2 B3 C定义如下变量StringP :前一步码字流pW : StringP的第一个字符StringC :当前的码字流cW : StringC的第一个字符第一步输出StringC 并StringP = StringC如:1解码为A,则StringC = A那么输出A,并令StringP = A---------------------------------------------------------------------------第二步1.解码得到StringC,并输出StringC2.将StringP + cW放入词典(如果当前码字不在词典中,则将StringP + cP放入词典中)3.StringP = StringC如:第二步要解码为2,解码为B,则StringC=B,输出B (此时StringP = A)将StringP+cW放入表中,即将AB放入表中,此时表为1 A2 B3 C4 AB四、实验情况及分析编码解码错误提示附:源代码#include<iostream>#include<string>#include<iomanip>using namespace std;string dic[30];int n;int find(string s)//字典中寻找,返回序号{int temp=-1;for(int i=0;i<30;i++){if(dic[i]==s) temp=i+1;}return temp;}void init()//字典初始化{dic[0]="a";dic[1]="b";dic[2]="c";//字根为a,b,cfor(int i=3;i<30;i++)//其余为空{dic[i]="";}}void code(string str){init();//初始化char temp[2];temp[0]=str[0];//取第一个字符temp[1]='\0';string w=temp;int i=1;int j=3;//目前字典存储的最后一个位置cout<<"\n 编码为:";for(;;){char t[2];t[0]=str[i];//取下一字符t[1]='\0';string k=t;if(k=="") //为空,字符串结束{cout<<" "<<find(w);break;//退出for循环,编码结束if(find(w+k)>-1){w=w+k;i++;}else{cout<<" "<<find(w);string wk=w+k;dic[j++]=wk;w=k;i++;}}cout<<endl;for(i=0;i<j;i++){cout<<setw(45)<<i+1<<setw(12)<<dic[i]<<endl; }cout<<endl;}void decode(int c[]){init();int pw,cw;cw=c[0];int j=2;cout<<"\n 译码为:";cout<<dic[cw-1];for(int i=0;i<n-1;i++){pw=cw;cw=c[i+1];if(cw<=j+1){cout<<dic[cw-1];char t[2];t[0]=dic[cw-1][0];t[1]='\0';string k=t;j++;dic[j]=dic[pw-1]+k;}elsechar t[2];t[0]=dic[pw-1][0];t[1]='\0';string k=t;j++;dic[j]=dic[pw-1]+k;cout<<dic[cw-1];}}cout<<endl;for(i=0;i<j+1;i++){cout<<setw(45)<<i+1<<setw(12)<<dic[i]<<endl;}cout<<endl;}void main(){string str;while(1){cout<<"\n\n\ta.编码\tb.译码\n\n";cout<<"请选择:";char cha;cin>>cha;if(cha=='a'){cout<<"\n输入要编码的字符串(由a、b、c组成):"; cin>>str;code(str);}if(cha=='b'){int c[30];cout<<"\n消息序列长度是:";cin>>n;cout<<"\n消息码字依次是:";for(int i=0;i<n;i++){cin>>c[i];}decode(c);}else {cout<<"输入错误!"<<endl;} }。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
LZW编码的编程和实现
一、实验目的
编写源程序,实现LZW的编码和解码
二、实验要求
1.编码输入若干字母(如abbababac),输出相应的编码
2.解码输入若干数字(如122473),输出相应的字母
三、编程思想
1.编码
根缀表已知
1 A
2 B
3 C
编码
分析字符串流,从词典中寻找最长匹配串,即字符串P在词典中,而字符串P+后一个字符C不在词典中
此时,输出P对应的码字,将P+C放入词典中。
如第一步:
输入A
此时,A在表中,而AB不在表中,则输出A对应的码字1,同时将AB写入表中,此时表为
1 A
2 B
3 C
4 AB
编码输出为1 (A已编码)
第二步,输入B,B在词典中,而BB不在词典中,则输出2,将BB写入表中,此时表为
1 A
2 B
3 C
4 AB
5 BB
编码输出为12 (AB已经编码)
....
2.解码
根缀表为
1 A
2 B
3 C
定义如下变量
StringP :前一步码字流
pW : StringP的第一个字符
StringC :当前的码字流
cW : StringC的第一个字符
第一步
输出StringC 并StringP = StringC
如:
1解码为A,则StringC = A
那么
输出A,并令StringP = A
---------------------------------------------------------------------------
第二步
1.解码得到StringC,并输出StringC
2.将StringP + cW放入词典(如果当前码字不在词典中,则将StringP + cP放入词典中)
3.StringP = StringC
如:
第二步要解码为2,解码为B,则StringC=B,输出B (此时StringP = A)
将StringP+cW放入表中,即将AB放入表中,此时表为
1 A
2 B
3 C
4 AB
四、实验情况及分析
编码解码
错误提示
附:源代码
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
string dic[30];
int n;
int find(string s)//字典中寻找,返回序号{
int temp=-1;
for(int i=0;i<30;i++)
{
if(dic[i]==s) temp=i+1;
}
return temp;
}
void init()//字典初始化
{
dic[0]="a";
dic[1]="b";
dic[2]="c";//字根为a,b,c
for(int i=3;i<30;i++)//其余为空
{
dic[i]="";
}
}
void code(string str)
{
init();//初始化
char temp[2];
temp[0]=str[0];//取第一个字符
temp[1]='\0';
string w=temp;
int i=1;
int j=3;//目前字典存储的最后一个位置cout<<"\n 编码为:";
for(;;)
{
char t[2];
t[0]=str[i];//取下一字符
t[1]='\0';
string k=t;
if(k=="") //为空,字符串结束
{
cout<<" "<<find(w);
break;//退出for循环,编码结束
if(find(w+k)>-1)
{
w=w+k;
i++;
}
else
{
cout<<" "<<find(w);
string wk=w+k;
dic[j++]=wk;
w=k;
i++;
}
}
cout<<endl;
for(i=0;i<j;i++)
{
cout<<setw(45)<<i+1<<setw(12)<<dic[i]<<endl; }
cout<<endl;
}
void decode(int c[])
{
init();
int pw,cw;
cw=c[0];
int j=2;
cout<<"\n 译码为:";
cout<<dic[cw-1];
for(int i=0;i<n-1;i++)
{
pw=cw;
cw=c[i+1];
if(cw<=j+1)
{
cout<<dic[cw-1];
char t[2];
t[0]=dic[cw-1][0];
t[1]='\0';
string k=t;
j++;
dic[j]=dic[pw-1]+k;
}
else
char t[2];
t[0]=dic[pw-1][0];
t[1]='\0';
string k=t;
j++;
dic[j]=dic[pw-1]+k;
cout<<dic[cw-1];
}
}
cout<<endl;
for(i=0;i<j+1;i++)
{
cout<<setw(45)<<i+1<<setw(12)<<dic[i]<<endl;
}
cout<<endl;
}
void main()
{
string str;
while(1)
{
cout<<"\n\n\ta.编码\tb.译码\n\n";
cout<<"请选择:";
char cha;
cin>>cha;
if(cha=='a')
{
cout<<"\n输入要编码的字符串(由a、b、c组成):"; cin>>str;
code(str);
}
if(cha=='b')
{
int c[30];
cout<<"\n消息序列长度是:";
cin>>n;
cout<<"\n消息码字依次是:";
for(int i=0;i<n;i++)
{
cin>>c[i];
}
decode(c);
}
else {cout<<"输入错误!"<<endl;
} }。