www.pudn.com > HuffmanForFile.zip > HUFF.C


#include  
#include  
#include  
#include  
#include "bitio.h" 
#include "errhand.h" 
#include "main.h" 
 
typedef struct tree_node{ 
  unsigned int count; 
  unsigned int saved_count; 
  int child_0; 
  int child_1; 
  }NODE; 
 
typedef struct code{ 
  unsigned int code; 
  int code_bits; 
  }CODE; 
 
#define END_OF_STREAM 256 
 
void count_bytes( FILE * input,unsigned long * long_counts ); 
void scale_counts( unsigned long * long_counts,NODE * nodes ); 
int build_tree( NODE * nodes ); 
void convert_tree_to_code( NODE * nodes, 
                           CODE * codes, 
                           unsigned int code_so_far, 
                           int bits, 
                           int node ); 
void output_counts( BIT_FILE * output,NODE * nodes ); 
void input_counts( BIT_FILE * input,NODE * nodes ); 
void print_model( NODE * nodes,CODE * codes ); 
void compress_data( FILE * input,BIT_FILE * output,CODE * codes ); 
void expand_data( BIT_FILE * input,FILE * output,NODE * nodes,int root_node); 
void print_char( int c ); 
 
char * CompressionName="Rights reserved JIANGSU JINSUI COMPUTER SYSTEM co. ltd\nWritten by Zhangli in 7/20/1997.\n"; 
char * Usage="infile outfile [-d]\n\n Specifying -d will dump the modeling data\n"; 
 
 
void CompressFile( FILE * input,BIT_FILE * output,int argc,char * argv[] ) 
{ 
  unsigned long * counts; 
  NODE * nodes; 
  CODE * codes; 
  int root_node; 
 
  counts=( unsigned long * ) calloc( 256,sizeof( unsigned long ) ); 
  if( counts==NULL ) 
      fatal_error( "Error allccating counts array\n" ); 
  if( ( nodes=( NODE * )calloc( 514,sizeof( NODE ) ) )==NULL ) 
      fatal_error( "Error allocating nodes array\n" ); 
  if( ( codes=( CODE * )calloc( 257,sizeof( CODE ) ) )==NULL ) 
      fatal_error( "Error allocating codes array!\n" ); 
  count_bytes( input,counts ); 
  scale_counts( counts,nodes ); 
  output_counts( output,nodes ); 
  root_node=build_tree( nodes ); 
  convert_tree_to_code( nodes,codes,0,0,root_node ); 
  if( argc>0 && strcmp( argv[0],"-d" )==0 ) 
      print_model( nodes,codes ); 
  compress_data( input,output,codes ); 
  free( ( char * ) counts ); 
  free( ( char * ) nodes ); 
  free( ( char * ) codes ); 
} 
 
void ExpandFile( BIT_FILE * input,FILE * output, int argc, char * argv[] ) 
{ 
  NODE * nodes; 
  int root_node; 
 
  if( ( nodes=( NODE * )calloc( 514,sizeof( NODE ) ) )==NULL ) 
      fatal_error( "Error allocating nodes array!" ); 
  input_counts( input,nodes ); 
  root_node=build_tree( nodes ); 
  if( argc>0 && strcmp( argv[0],"-d" )==0 ) 
      print_model( nodes,0 ); 
  expand_data( input,output,nodes,root_node ); 
  free( ( char * ) nodes ); 
} 
 
void output_counts( BIT_FILE * output,NODE * nodes ) 
{ 
  int first; 
  int last; 
  int next; 
  int i; 
 
  first=0; 
  while( first<255 && nodes[first].count==0 ) 
         first++; 
  for( ; first<256; first=next ){ 
       last=first+1; 
       for( ; ; ){ 
            for( ; last<256; last++ ) 
                   if( nodes[last].count==0 ) 
                       break; 
            last--; 
            for( next=last+1; next<256; next++ ) 
                 if( nodes[next].count!=0 ) 
                     break; 
            if( next>255 ) 
                break; 
            if( ( next-last)>3 ) 
                break; 
            last=next; 
           } 
       if( putc( first,output->file )!=first ) 
           fatal_error( "Error writing byte counts!\n" ); 
       if( putc( last,output->file )!=last ) 
           fatal_error( "Error writing byte counts!\n" ); 
       for( i=first; i<=last; i++ ) { 
            if( putc( nodes[i].count,output->file )!=(int)nodes[i].count ) 
                fatal_error( "Error writing byte counts!\n" ); 
            } 
         } 
  if( putc( 0,output->file)!=0 ) 
      fatal_error( "Error writing byte counts!" ); 
} 
         
void input_counts( BIT_FILE * input,NODE * nodes ) 
{ 
  int first; 
  int last; 
  int i; 
  int c; 
 
  for( i=0; i<256; i++ ) 
       nodes[i].count=0; 
  if( ( first=getc( input->file ) )==EOF ) 
      fatal_error( "Error reading byte counts!(1)\n" ); 
  if( ( last=getc( input->file ) )==EOF ) 
      fatal_error( "Error reading byte counts!(2)\n" ); 
  for( ; ; ){ 
       for( i=first; i<=last; i++ ) 
            if( ( c=getc( input->file ) )==EOF ) 
                fatal_error( "Error reading byte counts!(3)\n" ); 
             else 
                nodes[i].count=( unsigned int ) c; 
       if( ( first=getc( input->file ) )==EOF ) 
           fatal_error( "Error reading byte counts!(4)\n" ); 
       if( first==0 ) 
           break; 
       if( ( last=getc( input->file ) )==EOF ) 
           fatal_error( "Error reading byte counts!(5)\n" ); 
        } 
  nodes[END_OF_STREAM].count=1; 
} 
 
#ifndef SEEK_SET 
#define SEEK_SET 0 
#endif 
 
void count_bytes( FILE * input,unsigned long * counts ) 
{ 
  long input_marker; 
  int c; 
 
  input_marker=ftell( input ); 
  while( ( c=getc( input ) )!=EOF ) 
         counts[c]++; 
  fseek( input,input_marker,SEEK_SET ); 
} 
 
void scale_counts( unsigned long * counts,NODE * nodes ) 
{ 
  unsigned long max_count; 
  int i; 
 
  max_count=0; 
  for( i=0; i<256; i++ ) 
       if( counts[i]>max_count ) 
           max_count=counts[i]; 
  if( max_count==0 ) { 
      counts[0]=1; 
      max_count=1; 
    } 
  max_count=max_count/255; 
  max_count=max_count+1; 
  for( i=0; i<256; i++ ) { 
       nodes[i].count=( unsigned int )( counts[i]/max_count ); 
       if( nodes[i].count==0 && counts[i]!=0 ) 
           nodes[i].count=1; 
      } 
  nodes[END_OF_STREAM].count=1; 
} 
 
 
int build_tree( NODE * nodes ) 
{ 
  int next_tree; 
  int i; 
  int min_1; 
  int min_2; 
 
  nodes[513].count=0xffff; 
  for( next_tree=END_OF_STREAM+1; ; next_tree++ ){ 
       min_1=513; 
       min_2=513; 
       for( i=0; i=0x20 && c<127 ) 
      printf( "%c",c ); 
  else 
      printf( "%3d",c ); 
} 
 
 
void compress_data( FILE * input,BIT_FILE * output,CODE * codes ) 
{ 
  int c; 
 
  while( ( c=getc( input ) )!=EOF ) 
         OutputBits( output,(unsigned long)codes[c].code,codes[c].code_bits); 
  OutputBits( output,(unsigned long)codes[END_OF_STREAM].code, 
              codes[END_OF_STREAM].code_bits ); 
} 
 
 
void expand_data( BIT_FILE * input,FILE * output,NODE * nodes,int root_node) 
{ 
  int node; 
 
  for( ; ; ){ 
       node=root_node; 
       do{ 
          if( InputBit( input ) ) 
              node=nodes[node].child_1; 
          else 
              node=nodes[node].child_0; 
        }while( node>END_OF_STREAM ); 
        if( node==END_OF_STREAM ) 
            break; 
        if( ( putc( node,output) )!=node) 
            fatal_error( "Error trying to write expanded byte to output!\n" ); 
      } 
}