⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pc_lzw.cpp

📁 基于LWIP的服务器
💻 CPP
字号:

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "Winsock.h"
#include "pc_server.h"
#include "pc_lzw.h"


int *code_value;                      /* This is the code value array */
unsigned int *prefix_code;            /* This array holds the prefix codes */
unsigned char *append_character;      /* This array holds the appended chars */
unsigned char decode_stack[4000];     /* This array holds the decoded string */

int num_bits=INIT_BITS;               /* Starting with 9 bit codes */
unsigned long bytes_in=0,bytes_out=0; /* Used to monitor compression ratio */
int max_code;                         /* old MAX_CODE */
unsigned long checkpoint=CHECK_TIME;  /* For compression ratio monitoring */

/* MODIFIED This is the new compression routine. The first two 9-bit codes 
 * have been reserved for communication between the compressor and expander.
 */


void compress(FILE *input, FILE *output)
{
   unsigned int next_code=FIRST_CODE;
   unsigned int character;
   unsigned int string_code;
   unsigned int index;
   int i,             /* All purpose integer */
   ratio_new,         /* New compression ratio as a percentage */
   ratio_old=100;     /* Original ratio at 100% */
   max_code = MAXVAL(num_bits); 

   for (i=0;i<TABLE_SIZE;i++)   /* Initialize the string table first */
      code_value[i]=-1;
   printf("Compressing\n");
   string_code=getc(input);     /* Get the first code */

 /* This is the main compression loop. Notice when the table is full we try
  * to increment the code size. Only when num_bits == MAX_BITS and the code
  * value table is full do we start to monitor the compression ratio.
  */
   while((character=getc(input)) != (unsigned)EOF) {
      if (!(++bytes_in % 1000)) {     /* Count input bytes and pacifier */
         putchar('.');
      }
      index=find_match(string_code,character);
      if (code_value[index] != -1)
         string_code=code_value[index];
      else {
         if ((int)next_code <= max_code ) {
            code_value[index]=next_code++;
            prefix_code[index]=string_code;
            append_character[index]=character;
         }
         output_code(output,string_code);   /* Send out current code */
         string_code=character;
         if ((int)next_code > max_code) {      /* Is table Full? */
            if ( num_bits < MAX_BITS) {     /* Any more bits? */
               putchar('+');
               max_code = MAXVAL(++num_bits);  /* Increment code size then */
            }
            else if (bytes_in > checkpoint) {         /* At checkpoint? */
               if (num_bits == MAX_BITS ) {
                ratio_new = bytes_out*100/bytes_in; /* New compression ratio */
                if (ratio_new > ratio_old) {        /* Has ratio degraded? */
                  output_code(output,CLEAR_TABLE); /* YES,flush string table */
                  putchar('C');
                  num_bits=INIT_BITS;
                  next_code=FIRST_CODE;        /* Reset to FIRST_CODE */
                  max_code = MAXVAL(num_bits); /* Re-Initialize this stuff */
                  bytes_in = bytes_out = 0;
                  ratio_old=100;               /* Reset compression ratio */
                  for (i=0;i<TABLE_SIZE;i++)   /* Reset code value array */
                        code_value[i]=-1;
               }
               else                                /* NO, then save new */
               ratio_old = ratio_new;            /* compression ratio */
            }
            checkpoint = bytes_in + CHECK_TIME;    /* Set new checkpoint */
            }
         }
      }
   }
   output_code(output,string_code);   /* Output the last code */
   if ((int)next_code == max_code) {       /* Handles special case for bit */
      ++num_bits;                     /* increment on EOF */
      putchar('+');
   }
   output_code(output,TERMINATOR);    /* Output the end of buffer code */
   output_code(output,0);             /* Flush the output buffer */
   output_code(output,0);
   output_code(output,0);
   putchar('\n');
}
/* UNCHANGED from original
 * This is the hashing routine.
 */
unsigned int find_match(int hash_prefix, unsigned int hash_character)
{
   int index, offset;

   index = (hash_character << HASHING_SHIFT ) ^ hash_prefix;
   if (index == 0 )
      offset=1;
   else
      offset = TABLE_SIZE - index;
   while(1) {
      if (code_value[index] == -1 )
         return(index);
      if ((int)prefix_code[index] == hash_prefix && (unsigned int) append_character[index] == hash_character)
         return(index);
      index -= offset;
      if (index < 0)
         index += TABLE_SIZE;
   }
   return index;
}
/* MODIFIED This is the modified expansion routine. It must now check for the
 * CLEAR_TABLE code and know when to increment the code size.
 */
void expand(FILE *input, FILE *output)
{
   unsigned int next_code=FIRST_CODE;
   unsigned int new_code;
   unsigned int old_code;
   int character,
   counter=0,
   clear_flag=1;          /* Need to clear the code value array */
   unsigned char *string;
   unsigned char *decode_string(unsigned char *buffer, unsigned int code);
	
   num_bits=INIT_BITS;                  
   max_code = MAXVAL(num_bits);
   printf("Expanding\n");

   while((new_code=input_code(input)) != TERMINATOR) {
      if (clear_flag) {       /* Initialize or Re-Initialize */
         clear_flag=0;
         old_code=new_code;   /* The next three lines have been moved */
         character=old_code;  /* from the original */
         putc(old_code,output);
         continue;
      }
      if (new_code == CLEAR_TABLE) {     /* Clear string table */
         clear_flag=1;
         num_bits=INIT_BITS;
         next_code=FIRST_CODE;
         putchar('C');
         max_code = MAXVAL(num_bits);
         continue;
      }
      if (++counter == 1000) {           /* Pacifier */
         counter=0;
         putchar('.');
      }
      if (new_code >= next_code) {       /* Check for string+char+string */
         *decode_stack=character;
         string=decode_string(decode_stack+1,old_code);
      }
      else
         string=decode_string(decode_stack,new_code);

      character = *string;              /* Output decoded string in reverse */
      while (string >= decode_stack)
         putc(*string--,output);

      if ((int)next_code <= max_code) {      /* Add to string table if not full */
         prefix_code[next_code]=old_code;
         append_character[next_code++]=character;
         if ((int)next_code == max_code && num_bits < MAX_BITS) {
            putchar('+');
            max_code = MAXVAL(++num_bits);
         }
      }
      old_code=new_code;
   }
   putchar('\n');
}
/* UNCHANGED from original
 * Decode a string from the string table, storing it in a buffer.
 * The buffer can then be output in reverse order by the expansion
 * program.
 */
unsigned char *decode_string(unsigned char *buffer, unsigned int code)
{
   int i=0;

   while(code > 255 ) {
      *buffer++ = append_character[code];
      code=prefix_code[code];
      if (i++ >= 4000 ) {
         printf("Error during code expansion\n");
         return (buffer);
      }
   }
   *buffer=code;
   return(buffer);
}

/* UNCHANGED from original
 * Input a variable length code.
 */
unsigned 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-num_bits);
   input_bit_buffer <<= num_bits;
   input_bit_count -= num_bits;
   return(return_value);
}
/* MODIFIED Output a variable length code.
 */
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 - num_bits - output_bit_count);
   output_bit_count += num_bits;
   while (output_bit_count >= 8) {
      putc(output_bit_buffer >> 24, output);
      output_bit_buffer <<= 8;
      output_bit_count -= 8;
      bytes_out++;                    /* ADDED for compression monitoring */
   }
}

        uint8 HexToBin(char Ch)
{
    if (Ch >= '0' && Ch <='9')
    {
        return (Ch - '0');    
    }
    else
    {
        return (Ch - 'A' + 0x0a);    
    }
}

      uint8 Load2Hex(char Ch1, char Ch2)
{
    return ((HexToBin(Ch1) << 4) | HexToBin(Ch2));
}

void IntToChar(int intdata,char *chardata)
{
	int i;
	for(i=0;i<4;i++)
	{
		*(chardata+i)=(char)(intdata>>(i*8));
	}
}

int CharToInt(char *chardata)
{
	int temp=0;
	int temp2=0x0;

	temp=(int)(*chardata);
	temp=0x000000ff&temp;
	temp2=temp2|temp;

	temp=(int)(*(chardata+1));
	temp=temp<<8;
	temp=0x0000ff00&temp;
	temp2=temp2|temp;

	temp=(int)(*(chardata+2));
	temp=temp<<16;
	temp=0x00ff0000&temp;
	temp2=temp2|temp;

	temp=(int)(*(chardata+3));
	temp=temp<<24;
	temp=0xff000000&temp;
	temp2=temp2|temp;
	
	return temp2;
}


/*************************************************************************
//   压缩文件函数

//	 file是要压缩的程序文件名 ,out_file为压缩后的文件名
*************************************************************************/
int MakeLzwFile(const char *file,const char *out_file)
{
	FILE *in;
	FILE *out;
	int i=0;
	int n;
	int count=0;
	int end=0;
	unsigned char temp;
	unsigned char data[50];
	unsigned char pSenddata[50];

	n=0;
	code_value=(int*)malloc(TABLE_SIZE*sizeof(unsigned int));
    prefix_code=(unsigned int*)malloc(TABLE_SIZE*sizeof(unsigned int));
    append_character=(unsigned char*)malloc(TABLE_SIZE*sizeof(unsigned char));

   
	//提取程序部分
    in=fopen(file,"rb");
    out=fopen("test","wb");
	fseek(in,18,SEEK_SET);
	while(!feof(in)&&(end==0))
	{
		
        temp=fgetc(in);
		
		//如果该行为写满(16进制数10表示包含16个字节)
		if(temp==0x31)
		{
			fseek(in,7,SEEK_CUR);
	   	    for(i=0;i<32;i++)
			{
				fputc(fgetc(in),out); 
			}
			fseek(in,5,SEEK_CUR);
		}
		//如果该行没有被写满(下一个字节(一个16进制数)表示所包含的字节数)
		else
		{
			temp=fgetc(in);
			count=(int)(temp-0x30);
			if(count>9)
			{
				count=(int)(temp-0x41);
				count=10+count;
			}
				
			for(i=0;i<5;i++)
			{
				temp=fgetc(in);
				if(temp!=0x30)
					end=1;
			}

			//文件结束
			if(end==1)
			{
				fseek(in,1,SEEK_CUR);
	   			for(i=0;i<2*count;i++)
				{
					fputc(fgetc(in),out); 
				}
			}
			//文件没有结束,1000(16进制)字节后又出现一个文件头
			else
			{
				fseek(in,10,SEEK_CUR);
			}
		}		    	
	}
    fclose(out);
    fclose(in);

	//将字符表示的程序改写为2进制
    in=fopen("test","rb");
    out=fopen("test2_bin","wb");
    while(!feof(in))
    {
		
		fread(data,1,2,in);
		for(i=0;i<1;i++)
		{
            pSenddata[i]=Load2Hex(data[2*i], data[2*i+1]);
		}
        fwrite(pSenddata,1,1,out);
	}
	fclose(out);
    fclose(in);

	//压缩2进制文件
   in=fopen("test2_bin","rb");
   out=fopen(out_file,"wb");
   if (in == NULL || out == NULL) {
      printf("Error opening files\n");
	   return 1;
   }
 
   compress(in,out);       /* Call compression routine */


   fclose(in);
   fclose(out);
   free(code_value);                 

   /*
   //解压缩比较
   in=fopen("test.lzw","rb");
   out=fopen("test.out","wb");
   if (in == NULL || out == NULL) {
      printf("Error opening files\n");
	   return 1;
   }

   expand(in,out);         

   fclose(in);                    
   fclose(out);*/
   free(prefix_code);
   free(append_character);
   return 0;

}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -