www.pudn.com > inet_stock.zip > LZW15.C


#include 
#include 
#include 
#include 

#include "lzw.h"

#define         BITS            15
#define         MAX_CODE        ((1L<> 8) +1)  //137
#define         END_OF_STREAM   256
#define         BUMP_CODE       257
#define         FLUSH_CODE      258
#define         FIRST_CODE      259
#define         UNUSED          -1

unsigned int find_child_node(int parent_code,int child_character);
unsigned int decode_string(unsigned int offset,unsigned int code);

void  InitializeStorage(void);
void  InitializeDictionary(void);
void  ExitLzw(void);

//char *CompressionName ="lzw 15 bit Encode";
//char *Usage         ="in-file out-file\n\n";
//this package inlude file:bitio.c/lzw15.c/lzw.h

typedef struct tag_dictionary
{
	int code_value;
	int parent_code;
	char character;
}dictionary;

dictionary *dict[TABLE_BANKS];

#define DICT(i) dict[i >> 8][i&0xff]
//char decode_stack[TABLE_SIZE];
char *decode_stack=NULL;

unsigned int next_code;
int current_code_bits;
unsigned int next_bump_code;

void ExitLzw()
{
	int i;
	for(i=0;iMAX_CODE)
			{
				OutputBits(output,(unsigned long)FLUSH_CODE,current_code_bits);
				InitializeDictionary();
			}
			else if(next_code>next_bump_code)
			{
				OutputBits(output,(unsigned long)BUMP_CODE,current_code_bits);
				current_code_bits++;
				next_bump_code<<=1;
				next_bump_code|=1;
				//putc('B',stdout);
			}
		}
	}
	OutputBits(output,(unsigned int)string_code,current_code_bits);
	OutputBits(output,(unsigned int)END_OF_STREAM,current_code_bits);
	ExitLzw();
	CloseOutputBitFile(output);
	fclose(input);  
}

void CompressMemFile(char *ptr,long len,char *outfile)
{
	int character;
	int string_code;
	unsigned int index;
	BIT_FILE *output;
	
	output =OpenOutputBitFile(outfile);
    if(output ==NULL)
    {
		fatal_error("Can not open output file");
		return;    
    }

	InitializeStorage();
	InitializeDictionary();

	if(len==0)
		string_code =EOF;
	else
	{
		string_code =*ptr++;
		len--;
	}
	if(string_code == EOF)
		string_code = END_OF_STREAM;

	for(;;)
	{
		if(len==0L)
		{
			character =EOF;
			break;
		}
		else
		{
			character =*ptr++;
			len--;
		}

		index =find_child_node(string_code,character);
		if(DICT(index).code_value !=-1)
			string_code =DICT(index).code_value;
		else
		{
			DICT(index).code_value =next_code++;
			DICT(index).parent_code=string_code;
			DICT(index).character=(char)character;

			OutputBits(output,(unsigned long)string_code,current_code_bits);
			string_code =character;
			if(next_code>MAX_CODE)
			{
				OutputBits(output,(unsigned long)FLUSH_CODE,current_code_bits);
				InitializeDictionary();
			}
			else if(next_code>next_bump_code)
			{
				OutputBits(output,(unsigned long)BUMP_CODE,current_code_bits);
				current_code_bits++;
				next_bump_code<<=1;
				next_bump_code|=1;
				//putc('B',stdout);
			}
		}
	}
	OutputBits(output,(unsigned int)string_code,current_code_bits);
	OutputBits(output,(unsigned int)END_OF_STREAM,current_code_bits);
	ExitLzw();
	CloseOutputBitFile(output);	
}

void ExpandFile(char *infile,char *outfile)
{
	unsigned int new_code;
	unsigned int old_code;
	int character;
	unsigned int count;

    FILE * output;
    BIT_FILE * input;
    
    decode_stack =(char *)_fmalloc((size_t)TABLE_SIZE);
    if(decode_stack ==NULL)
    	fatal_error("can not get decode_stack space");
    	
	output = fopen(outfile,"wb");
    if(output==NULL)
    {
		fatal_error("Can not open output file");
		return;
    }
	input =OpenInputBitFile(infile);
    if(input ==NULL)
    {
		fatal_error("Can not open input file");
		fclose(output);
		_ffree(decode_stack);
		return;    
    }

	InitializeStorage();
	for(;;)
	{
		InitializeDictionary();
		old_code =(unsigned int)InputBits(input,current_code_bits);

		if(old_code == END_OF_STREAM)
		{
			CloseInputBitFile(input);
			fclose(output); 
			ExitLzw();              
			_ffree(decode_stack);
			return;
		}       
		character =old_code;
		putc(old_code,output);

		for(;;)
		{
			new_code =(unsigned int) InputBits(input,current_code_bits);
			if(new_code == END_OF_STREAM)
			{
				CloseInputBitFile(input);
				fclose(output);                 
				ExitLzw();                      
				_ffree(decode_stack);						
				return;
			}       
			if(new_code == FLUSH_CODE)
				break;
			if(new_code == BUMP_CODE)
			{
				current_code_bits++;
				//putc('B',stdout);
				continue;
			}
			if(new_code >= next_code)
			{
				decode_stack[0] =(char )character;
				count =decode_string(1,old_code);
			}
			else
				count =decode_string(0,new_code);
			character =decode_stack[count -1];
			while(count>0)
				putc(decode_stack[--count],output);
			DICT(next_code).parent_code =old_code;
			DICT(next_code).character =(char)character;
			next_code++;
			old_code = new_code;
		}
	}
}

unsigned int find_child_node(int parent_code ,int child_character)
{
	unsigned int index;
	unsigned int offset;
    
	index =(child_character <<(BITS-8)) ^parent_code;
	if(index ==0)
		offset =1;
	else
		offset =(unsigned int)(TABLE_SIZE -(long)index);
	for(;;)
	{
		if(DICT(index).code_value ==UNUSED)
			return(index);
		if(DICT(index).parent_code ==parent_code &&
				DICT(index).character ==(char)child_character)
			return(index);
		if((long)index >=(long)offset)
			index =(unsigned int)((long)index -(long)offset);
		else
			index=index +(unsigned int)(TABLE_SIZE-(long)offset);
	}
}

unsigned int decode_string(unsigned int count,unsigned int code)
{
	while(code>255)
	{
		decode_stack[count++] =DICT(code).character;
		code =DICT(code).parent_code;
	}
	decode_stack[count++] =(char)code;
	return(count);
}