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

📄 060-073.html

📁 The primary purpose of this book is to explain various data-compression techniques using the C progr
💻 HTML
📖 第 1 页 / 共 2 页
字号:
*/             if ( putc( first, output-&gt;file ) != first)                  fatal_error( "Error writing byte counts\n" );             if ( putc( last, output-&gt;file ) != last)                  fatal_error( "Error writing byte counts\n" );             for ( i = first ; i &lt;= last ; i&#43;&#43; ) &#123;                 if ( putc( nodes[ i ]. count, output-&gt;file ) !=                      (int) nodes[ i ]. count)                      fatal_error( "Error writing byte counts\n" );             &#125;       &#125;       if ( putc( 0, output-&gt;file ) != 0              fatal_error( "Error writing byte counts\n" );&#125;/** When expanding, I have to read in the same set of counts.  This is* quite a bit easier that the process of writing them out, since no* decision making needs to be done.  All I do is read in first, check* to see if I am all done, and if not, read in last and a string of* counts.*/void input_counts( input, nodes)BIT_FILE *input;NODE *nodes;&#123;     int first;     int last;     int i;     int c;     for ( i = 0 ; i &lt; 256 ; i&#43;&#43; )         nodes[ i ]. count = 0;     if ( ( first = getc( input-&gt;file ) ) == EOF)          fatal_error( "Error reading byte counts\n" );     if ( ( last = getc( input-&gt;file ) ) == EOF )          fatal_error( "Error reading byte counts\n);     for ( ; ; ) &#123;         for ( i = first ; i &lt;= last ; i&#43;&#43; )             if ( ( c = getc( input-&gt;file ) ) == EOF)                  fatal_error( "Error reading byte counts\n" );             else                  nodes[ i ]. count = (unsigned int) c;         if ( ( first = getc( input-&gt;file ) ) == EOF )              fatal_error( "Error reading byte counts\n" );         if ( first == 0)              break;         if ( ( last = getc( input-&gt;file ) ) == EOF )              fatal_error( "Error reading byte counts\n" );     &#125;     nodes[ END_OF_STREAM ].count = 1;&#125;/** This routine counts the frequency of occurence of every byte in* the input file.  It marks the place in the input stream where it* started, counts up all the bytes, then returns to the place where* it started.  In most C implementations, the length of a file* cannot exceed an unsigned long, so this routine should always* work.*/#ifndef SEEK_SET#define SEEK_SET 0#endifvoid count_bytes( input, counts)FILE *input;unsigned long *counts;&#123;     long input_marker;     int c;     input_marker = ftell( input );     while ( ( c = getc( input ) ) != EOF )         counts[ c ]&#43;&#43;;     fseek( input, input_marker, SEEK_SET );&#125;/** In order to limit the size of my Huffman codes to 16 bits, I scale* my counts down so they fit in an unsigned char, and then store them* all as initial weights in my NODE array.  The only thing to be* careful of is to make sure that a node with a non-zero count doesn't* get scaled down to 0.  Nodes with values of 0 don't get codes.*/void scale_counts( counts, nodes )unsigned long *counts;NODE *nodes;&#123;     unsigned long max_count;     int i;     max_count = 0;     for ( i = 0 ; i &lt; 256 ; i&#43;&#43; )         if ( counts[ i ] &gt; max_count )              max_count = counts[ i ] ;     if ( max_count == 0 ) &#123;          counts[ 0 ] = 1;          max_count = 1;     &#125;     max_count = max_count / 255;     max_count = max_count &#43; 1;     for ( i = 0 ; i &lt; 256 ; i&#43;&#43; ) &#123;          nodes[ i ].count = (unsigned int)                                 ( counts[ i ] / max_count );          if ( nodes[ i ].count == 0 &#38;&#38; counts[ i ] !=0 );               nodes[ i ].count = 1;     &#125;     nodes[ END_OF_STREAM ]. count = 1;&#125;/** Building the Huffman tree is fairly simple.  All of the active nodes* are scanned in order to locate the two nodes with the minimum* weights.  These two weights are added together and assigned to a new* node.  The new node makes the two minimum nodes into its 0 child* and 1 child.  The two minimum nodes are then marked as inactive.* This process repeats until there is only one node left, which is* the root node.  The tree is done, and the root node is passed back* to the calling routine.** Node 513 is used here to arbitratily provide a node with a guaran* teed maximum value.  It starts off being min_1 and min_2.  After all* active nodes have been scanned, I can tell if there is only one* active node left by checking to see if min_1 is still 513.*/int build_tree( nodes )NODE *nodes;&#123;     int next_free;     int i;     int min_1;     int min_2;     nodes[ 513 ].count = Oxffff;     for ( next_free = END_OF_STREAM &#43; 1 ; ; next_free&#43;&#43; ) &#123;          min_1 = 513;          min_2 = 513;          for ( i = 0 ; i &lt; next_free; i&#43;&#43; )              if ( nodes[ i ].count != 0) &#123;                  if ( nodes[ i ].count &lt; nodes[ min_1 ].count ) &#123;                   min_2 &#43; min_1;                   min_1 = i;                  &#125; else if ( nodes[ i ].count                              &lt; nodes[ min_2 ].count)                    min_2 = i;              &#125;          if ( min_2 == 513 )               break;          nodes[ next_free ].count = nodes[ min_1 ].count                                      &#43; 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_free ].child_0 = min_1;          nodes[ next_free ].child_1 = min_2;          &#125;          next_free--;          nodes[ next_free ].saved_count = nodes[ next_free ].count;          return( next_free );&#125;/** Since the Huffman tree is built as a decoding tree, there is* no simple way to get the encoding values for each symbol out of* it.  This routine recursively walks through the tree, adding the* child bits to each code until it gets to a leaf.  When it gets* to a leaf, it stores the code value in the CODE element, and* returns.*/void convert_tree_to_code( nodes, codes, code_so_far, bits, node )NODE *nodes;CODE *codes;unsigned int code_so_far;int bits;int node;&#123;     if ( node &lt;= END_OF_STREAM ) &#123;          codes[ node ].code = code_so_far;          codes[ node ].code_bits = bits;          return;     &#125;     code_so_far &lt;&lt;= 1;     bits&#43;&#43;;     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 );&#125;/** If the -d command line option is specified, this routine is called* to print out some of the model information after the tree is built.* Note that this is the only place that the saved_count NODE element* is used for anything at all, and  in this case it is just for* diagnostic information.  By the time I get here, and the tree has* been built, every active element will have 0 in its count.*/void print_mode1( nodes, codes )NODE *nodes;CODE *codes;&#123;     int i;     for ( i = 0 ; i &lt; 513 ; i&#43;&#43; ) &#123;       if ( nodes[ i ].saved_count != 0 ) &#123;            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 &#38;&#38; i &lt;= END_OF_STREAM ) &#123;                printf( " Huffman code=" );                FilePrintBinary( stdout, codes[ i ].code,                                 codes[ i ].code_bits );            &#125;            printf( "\n" );       &#125;     &#125;&#125;/** The print_model routine uses this function to print out node num* bers.  The catch is if it is a printable character, it gets printed* out as a character.  This makes the debug output a little easier to* read.*/void print_char( c )int c;&#123;     if ( c &gt;= 0x20 &#38;&#38; c &lt; 127 )          printf( "`%c'", c );     else          printf( "%3d", c );&#125;/** Once the tree gets built, and the CODE table is built, compressing* the data is a breeze.  Each byte is read in, and its corresponding* Huffman code is sent out.*/void compress_data( input, output, codes )FILE *input;BIT_FILE *output;CODE *codes;&#123;     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 );&#125;/** Expanding compressed data is a little harder than the compression* phase.  As each new symbol is decoded, the tree is traversed,* starting at the root node, reading a bit in, and taking either the* child_0 or child_1 path.  Eventually, the tree winds down to a* leaf node, and the corresponding symbol is output.  If the symbol* is the END_OF_STREAM symbol, it doesn't get written out, and* instead the whole process terminates.*/void expand_data( input, output, nodes, root_node )BIT_FILE *input;FILE *output;NODE *nodes;int root_node;&#123;     int node;     for ( ; ; ) &#123;         node = root_node;         do &#123;              if ( InputBit( input ) )                   node = nodes[ node ].child_1;              else                   node = nodes[ node ].child_0;         &#125; while ( node . END_OF_STREAM );         if ( node == END_OF_STREAM )              break;         if ( ( putc( node, output ) ) != node )              fatal_error( "Error trying to write byte to output" );     &#125;&#125;/******************************End of HUFF.C***************************/</PRE><!--  END CODE //--><P><BR></P><CENTER><TABLE BORDER><TR><TD><A HREF="058-060.html">Previous</A></TD><TD><A HREF="../ewtoc.html">Table of Contents</A></TD><TD><A HREF="074-074.html">Next</A></TD></TR></TABLE></CENTER></TD></TR></TABLE></BODY></HTML>

⌨️ 快捷键说明

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