📄 pc_lzw.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 + -