一番蛋疼的调试修改终于工作正常
#include "stdafx.h"
//CLZW类实现
#include "LZW.h"
//华丽的分割线--------------------------------------------------------
//创建对象时初始化数据
CLZW::CLZW()
{
hash_code=0;
hash_prefix=0;
hash_suffix=0;
symbol_head=0;
symbol_tail=0;
symbol_stack=0;
}
//华丽的分割线--------------------------------------------------------
CLZW::~CLZW()
//销毁对象时释放内存
{
if(hash_code) free(hash_code);
if(hash_prefix) free(hash_prefix);
if(hash_suffix) free(hash_prefix);
if(symbol_head) free(symbol_head);
if(symbol_tail) free(symbol_tail);
if(symbol_stack) free(symbol_stack);
}
//华丽的分割线--------------------------------------------------------
int CLZW::GetDataBlock(char *buf)
//零长度块标志数据块结束
{
int count;
if ((count=getc(infile))!=EOF)
{
if(count>0)
{
if(fread(buf,1,count,infile)!=(size_t)count)
{
return -1;
}
}
}
return count;
}
//华丽的分割线--------------------------------------------------------
void CLZW::SkipDataBlocks()
//找到数据块结尾
{
char buf[256];
while (GetDataBlock(buf)>0);
}
//华丽的分割线--------------------------------------------------------
void CLZW::ReInitLZW()
//初始化LZW状态
{
n_bits=init_bits;
maxcode=ClearCode<<1;
code_counter=ClearCode+2;//第一个未用的代码值
sp=symbol_stack;//初始化栈使其为空
}
//华丽的分割线--------------------------------------------------------
void CLZW::InitLZWCode(FILE* file,int ibits)
{
//GetCode初始化分配内存
symbol_head=(code_int*)malloc(LZW_TABLE_SIZE*sizeof(code_int));
symbol_tail=(UINT_8*)malloc(LZW_TABLE_SIZE*sizeof(UINT_8));
symbol_stack=(UINT_8*)malloc(LZW_TABLE_SIZE*sizeof(UINT_8));
infile=file;
init_bits=ibits;
last_byte=2;//保证重新复制最后两个字节
last_bit=0;//缓冲区为空
cur_bits=0;//缓冲区的第一个字符
out_of_blocks=false;
//LZWReadByte 初始化
ClearCode=((code_int)1<<(init_bits-1));
EOFCode=ClearCode+1;
first_byte=true;
ReInitLZW();
}
//华丽的分割线--------------------------------------------------------
int CLZW::GetCode()
//从压缩数据中提取以后的code_size个比特
{
int offs,ret,count;
if((cur_bits+n_bits)>last_bit)
{
//重新装 载缓冲区
if(out_of_blocks)
{
return EOFCode;
}
//保持最后两个字节
code_buf[0]=code_buf[last_byte-2];
code_buf[1]=code_buf[last_byte-1];
//装载更多的字节如到达结尾设置标志
if((count=GetDataBlock(&code_buf[2]))==0)
{
out_of_blocks=true;
return EOFCode;
}
//重置计数器
cur_bits=(cur_bits-last_bit)+16;
last_byte=2+count;
last_bit=last_byte*8;
}
//形成积累下一个24位的字符
offs=cur_bits>>3;
cur_accum=code_buf[offs+2]&0xFF;
cur_accum<<=8;
cur_accum|=code_buf[offs+1]&0xFF;
cur_accum<<=8;
cur_accum|=code_buf[offs]&0xFF;
//向右积累排列cur_bit然后通过掩码得到需要的bits数
cur_accum>>=(cur_bits&7);
ret=((int)cur_accum)&((1<<n_bits)-1);
cur_bits+=n_bits;
return ret;
}
//华丽的分割线--------------------------------------------------------
int CLZW::LzwReadByte()
{
static int oldcode;//前一个LZW符
static int firstcode;//原码扩展后的第一个字节
register int code;//当前工作代码
int incode;//保存实际的输入代码
if(first_byte)
{
first_byte=false;
code=ClearCode;
}else{
//如果栈有以前读过的符号返回它
if(sp>symbol_stack)return (int)*(--sp);
//读入新的符号
code=GetCode();
}
if(code==ClearCode)
{
ReInitLZW();
do{
code=GetCode();
}while (code==ClearCode);
if(code>ClearCode){
//保证它是一个未压缩的字节
code=0;
}
firstcode=oldcode=code;
return code;
}
if(code==EOFCode)
{
if(!out_of_blocks)
{
SkipDataBlocks();
out_of_blocks=true;
}
//没有足够的数据
return 257;
}
//得到正常未压缩的字节或LZW符号
incode=code;
if(code>=code_counter)
{
if(code>code_counter)
{
//以免在符号表中产生循环
incode=0;
}
*sp++=(UINT_8) firstcode;
code=oldcode;
}
//如果是一个符号把它扩展后放入栈
while (code>=ClearCode)
{
//符号头:一个字节符
*sp++=symbol_tail[code];
//符号尾:另一个LZW符号
code=symbol_head[code];
}
//表示是一个未被压缩的字节
firstcode=code;
//判别表中是否有空间
if((code=code_counter)<LZW_TABLE_SIZE)
{
//定义一个新的符号=原来的符号+这个符号扩展后的头字节
symbol_head[code]=oldcode;
symbol_tail[code]=(UINT_8) firstcode;
code_counter++;
//增加n_bits
if((code_counter>=maxcode)&&(n_bits<MAX_LZW_BITS))
{
n_bits++;
maxcode<<=1;
}
}
//保存最后的输入符号
oldcode=incode;
//返回符号扩展后的第一个字节
return firstcode;
}//华丽的分割线--------------------------------------------------------
void CLZW::flush_packet()
//清空所有积累的数据
{
if(bytesinpkt>0)
{
//所写入的长度必须大于0
packetbuf[0]=(char)bytesinpkt++;
if(fwrite(packetbuf,1,bytesinpkt,outfile)!=(size_t)bytesinpkt) printf("文件写入错误!");
bytesinpkt=0;
}
}
//华丽的分割线--------------------------------------------------------
void CLZW::CHAR_OUT(int c)
//向缓冲区增加一个字节同时在有必要时向磁盘写数据
{
packetbuf[++bytesinpkt]=(char)(c);
if(bytesinpkt>=255) flush_packet();
}
//华丽的分割线--------------------------------------------------------
//发送一个n_bits比特的代码并重组一个8为的字节
void CLZW::output(code_int code)
{
cur_accum|=((INT32)code)<<cur_bits;
cur_bits+=n_bits;
while(cur_bits>=8)
{
CHAR_OUT(cur_accum&0xFF);
cur_accum>>=8;
cur_bits-=8;
}
//如果下一个输入比最大的代码大则增加它
if(free_code>maxcode)
{
n_bits++;
if(n_bits==MAX_LZW_BITS) maxcode=LZW_TABLE_SIZE;else maxcode=MAXCODE(n_bits);
}
}
//华丽的分割线--------------------------------------------------------
void CLZW::clear_hash()
//清空hash表
{
memset((void*)hash_code,0,HSIZE*sizeof(code_int));
}
//华丽的分割线--------------------------------------------------------
void CLZW::clear_block()
//重置压缩并发送一个清除码
{
clear_hash();
free_code=ClearCode+2;
output(ClearCode);
n_bits=init_bits;
maxcode=MAXCODE(n_bits);
}
//华丽的分割线--------------------------------------------------------
void CLZW::compress_init(FILE* file,int ibits)
//初始化LZW压缩
{
//初始化所有静态变量给hash表分配内存
hash_code=(code_int*)malloc(HSIZE*sizeof(code_int));
hash_prefix=(code_int*)malloc(HSIZE*sizeof(code_int));
hash_suffix=(UINT_8*)malloc(HSIZE*sizeof(UINT_8));
outfile=file;
n_bits=init_bits=ibits;
maxcode=MAXCODE(n_bits);
ClearCode=((code_int)1<<(init_bits-1));
EOFCode=ClearCode+1;
free_code=ClearCode+2;
first_byte=true;
//初始化缓冲区变量
bytesinpkt=0;
cur_accum=0;
cur_bits=0;
//清理hash表
clear_hash();
//给定一个初始清理字符
output(ClearCode);
}
//华丽的分割线--------------------------------------------------------
void CLZW::compress_byte(int c)
//得到和压缩一个8位的字节
{
register hash_int i;
register hash_int disp;
if(first_byte)
{
//初始化一个等待码
waiting_code=c;
first_byte=false;
return;
}
i=((hash_int)c<<(MAX_LZW_BITS-8))+waiting_code;
if(i>=HSIZE) i-=HSIZE;
if(hash_code[i]!=0)
{
if(hash_prefix[i]==waiting_code&&hash_suffix[i]==(UINT_8)c)
{
waiting_code=hash_code[i];
return;
}
if(i==0) disp=1; else disp=HSIZE-i;
while(1)
{
i-=disp;
if(i<0) i+=HSIZE;
if(hash_code[i]==0) break;
if(hash_prefix[i]==waiting_code&&hash_suffix[i]==(UINT_8)c)
{
waiting_code=hash_code[i];
return;
}
}
}
//如果期望的符号不在表中
output(waiting_code);
if(free_code<LZW_TABLE_SIZE)
{
//在hash表里增加一个符号
hash_code[i]=free_code++;
hash_prefix[i]=waiting_code;
hash_suffix[i]=(UINT_8)c;
}else clear_block();
waiting_code=c;
}
//华丽的分割线--------------------------------------------------------
void CLZW::compress_term()
//结尾保存
{
//保存缓冲区里的代码
if(!first_byte) output(waiting_code);
//发送一个结束代码
output(EOFCode);
if(cur_bits>0)
{
CHAR_OUT(cur_accum&0xFF);
}
//保存缓冲区里的代码
flush_packet();
}