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

📄 huff.c

📁 用c++实现文件的压缩
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#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<next_tree; i++ )
            if( nodes[i].count!=0 ){
                if( nodes[i].count<nodes[min_1].count ) {
                    min_2=min_1;
                    min_1=i;
                  }
                else if( nodes[i].count<nodes[min_2].count )
                     min_2=i;
                }
       if( min_2==513 )
           break;
       nodes[next_tree].count=nodes[min_1].count+nodes[min_2].count;
       nodes[min_1].saved_count=nodes[min_1].count;
       nodes[min_1].count=0;
       nodes[min_2].saved_count=nodes[min_2].count;
       nodes[min_2].count=0;
       nodes[next_tree].child_0=min_1;
       nodes[next_tree].child_1=min_2;
     }
  next_tree--;
  nodes[next_tree].saved_count=nodes[next_tree].count;
  return( next_tree );
}


void convert_tree_to_code( NODE * nodes,CODE * codes,
                           unsigned int code_so_far,int bits,int node)
{
  if( node<=END_OF_STREAM) {
      codes[node].code=code_so_far;
      codes[node].code_bits=bits;
      return;
     }
  code_so_far<<=1;
  bits++;
  convert_tree_to_code( nodes,codes,code_so_far,bits,nodes[node].child_0 );
  convert_tree_to_code( nodes,codes,code_so_far|1,bits,nodes[node].child_1);
}

void print_model( NODE * nodes, CODE * codes )
{
  int i;

  for( i=0; i<513; i++ ) {
       if( nodes[i].saved_count!=0 ) {
           printf( "node=" );
           print_char( i );
           printf( "count=%3d",nodes[i].saved_count );
           printf( "child_0=" );
           print_char( nodes[i].child_0 );
           printf( "child_1=" );
           print_char( nodes[i].child_1 );
           if( codes && i<=END_OF_STREAM ){
               printf( "Huffman code=" );
               FilePrintBinary( stdout,codes[i].code,codes[i].code_bits );
             }
           printf( "\n" );
         }
    }
}


void print_char( int c )
{
  if( c>=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" );
      }
}



  




          

















⌨️ 快捷键说明

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