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

📄 136-152.html

📁 The primary purpose of this book is to explain various data-compression techniques using the C progr
💻 HTML
📖 第 1 页 / 共 2 页
字号:
* in a row.** This is simple in concept, but it ends up being one of the most* complicated routines in the whole program.  A routine that just* writes out 256 values without attempting to optimize would be much* simpler, but would hurt compression quite a bit on small files.**/void output_counts( output, scaled_counts )FILE *output;unsigned char scaled_counts[];&#123;     int first;     int last;     int next;     int i;     first = 0;     while ( first &lt; 255 &#38;&#38; scaled_counts[ first ] == 0 )               first&#43;&#43;;/** Each time I hit the start of the loop, I assume that first is the* number for a run of non-zero values.  The rest of the loop is* concerned with finding the value for last, which is the end of the* run, and the value of next, which is the start of the next run.* At the end of the loop, I assign next to first, so it starts in on* the next run.*/     for ( ; first &lt; 256 ; first = next ) &#123;       last = first &#43; 1;       for ( ; ; ) &#123;         for ( ; last &lt; 256 ; last&#43;&#43; )           if ( scaled_counts[ last ] == 0 )             break;         last &#150;&#150;;         for ( next = last &#43; 1; next &lt; 256 ; next&#43;&#43; )           if ( scaled_counts[ next ] != 0 )             break;         if ( next &gt; 255 )           break;         if ( ( next - last ) &gt; 3 )           break;         last = next;     &#125;;/** Here is where I output first, last, and all the counts in between.*/        if ( putc( first, output ) != first )          fatal_error( "Error writing byte counts\n" );        if ( putc( last, output ) != last )          fatal_error( "Error writing byte counts\n" );        for ( i = first ; i &lt;= last ; i&#43;&#43; ) &#123;          if ( putc( scaled_counts[ i ], output ) !=            (int) scaled_counts[ i ] )            fatal_error( "Error writing byte counts\n" );        &#125;     &#125;     if ( putc( 0, output ) != 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 )FILE *input;&#123;     int first;     int last;     int i;     int c;     unsigned char scaled_counts[ 256 ];     for ( i = 0 ; i &lt; 256 ; i&#43;&#43; )       scaled_counts[ i ] = 0;     if ( ( first = getc( input ) ) == EOF )       fatal_error( "Error reading byte counts\n" );     if ( ( last = getc( input ) ) == EOF )       fatal_error( "Error reading byte counts\n" );     for ( ; ; ) &#123;       for ( i = first ; i &lt;= last ; i&#43;&#43; )         if ( ( c = getc( input ) ) == EOF )           fatal_error( "Error reading byte counts\n" );         else            scaled_counts[ i ] = (unsigned int) c;       if ( ( first = getc( input ) ) == EOF )         fatal_error( "Error reading byte counts\n" );       if ( first == 0 )         break;       if ( ( last = getc( input ) ) == EOF )         fatal_error( "Error reading byte counts\n" );     &#125;     build_totals( scaled_counts );&#125;/** Everything from here down defines the arithmetic coder section* of the program.*//** These four variables define the current state of the arithmetic* coder/decoder.  They are assumed to be 16 bits long.  Note that* by declaring them as short ints, they will actually be 16 bits* on most 80X86 and 680X0 machines, as well as VAXen.*/static unsigned short int code;/* The present input code value     */static unsigned short int low; /* Start of the current code range  */static unsigned short int high;/* End of the current code range    */long underflow_bits:           /* Number of underflow bits pending *//** This routine must be called to initialize the encoding process.* The high register is initialized to all 1s, and it is assumed that* it has an infinite string of 1s to be shifted into the lower bit* positions when needed.*/void initialize_arithmetic_encoder() &#123;     low = 0;     high = 0xffff;     underflow_bits = 0;&#125;/** At the end of the encoding process, there are still significant* bits left in the high and low registers.  We output two bits,* plus as many underflow bits as are necessary.*/void flush_arithmetic_encoder( stream )BIT_FILE *stream;&#123;     OutputBit( stream, low &#38; 0x4000 );     underflow_bits&#43;&#43;;     while ( underflow_bits&#150;&#150; &gt; 0 )       OutputBit( stream, ~low &#38; 0x4000 );&#125;/** Finding the low count, high count, and scale for a symbol* is really easy, because of the way the totals are stored.* This is the one redeeming feature of the data structure used* in this implementation.*/void convert_int_to_symbol( c, s )int c;SYMBOL *s;&#125;     s-&gt;scale = totals[ END_OF_STREAM &#43; 1];     s-&gt;low_count = totals[ c ];     s-&gt;high_count = totals[ c &#43; 1 ];&#125;/** Getting the scale for the current context is easy.*/void get_symbol_scale( s )SYMBOL *s;&#123;     s-&gt;scale = totals[ END_OF_STREAM &#43; 1 ];&#125;/** During decompression, we have to search through the table until* we find the symbol that straddles the "count" parameter.  When* it is found, it is returned.  The reason for also setting the* high count and low count is so that symbol can be properly removed* from the arithmetic coded input.*/int convert_symbol_to_int( count, s )int count;SYMBOL *s;&#123;     int c;     for ( c = END_OF_STREAM ; count &lt; totals[ c ] ; c&#150;&#150; )        ;     s-&gt;high_count = totals[ c &#43; 1 ];     s-&gt;low_count = totals[ c ];     return( c );&#125;/** This routine is called to encode a symbol.  The symbol is passed* in the SYMBOL structure as a low count, a high count, and a range,* instead of the more conventional probability ranges.  The encoding* process takes two steps.  First, the values of high and low are* updated to take into account the range restriction created by the* new symbol.  Then, as many bits as possible are shifted out to* the output stream.  Finally, high and low are stable again and* the routine returns.*/void encode_symbol( stream, s )BIT_FILE *stream;SYMBOL *s;&#123;  long range;/** These three lines rescale high and low for the new symbol.*/     range = (long) ( high-low ) &#43; 1;     high = low &#43; (unsigned short int)                   (( range * s-&gt;high_count ) / s-&gt;scale - 1 );     low = low &#43; (unsigned short int)                   (( range * s-&gt;low_count ) / s-&gt;scale );/** This loop turns out new bits until high and low are far enough* apart to have stabilized.*/     for ( ; ; ) &#123;/** If this test passes, it means that the MSDigits match, and can* be sent to the output stream.*/     if ( ( high &#38; 0x8000 ) == (  low &#38; 0x8000 ) ) &#123;       OutputBit( stream, high &#38; 0x8000 );       while ( underflow_bits &gt; 0 ) &#123;         OutputBit( stream, ~high &#38; 0x8000 );         underflow_bits&#150;&#150;;       &#125;     &#125;/** If this test passes, the numbers are in danger of underflow, because* the MSDigits don't match, and the 2nd digits are just one apart.*/     else if ( ( low &#38; 0x4000 ) &#38;&#38; !( high &#38; 0x4000 )) &#123;       underflow_bits &#43;= 1;       low &#38;= 0x3fff;       high |= 0x4000;     &#125; else       return ;     low &lt;&lt;= 1;     high &lt;&lt;= 1;     high |= 1;   &#125;&#125;/** When decoding, this routine is called to figure out which symbol* is presently waiting to be decoded.  This routine expects to get* the current model scale in the s-&gt;scale parameter, and it returns* a count that corresponds to the present floating point code;** code = count / s-&gt;scale*/short int get_current_count( s )SYMBOL *s;&#123;     long range;     short int count;     range = (long) ( high - low ) &#43; l;     count = (short int)             ((((long) ( code - low ) &#43; 1 ) * s-&gt;scale-1 ) / range ) ;     return( count );&#125;/** This routine is called to initialize the state of the arithmetic* decoder.  This involves initializing the high and low registers* to their conventional starting values, plus reading the first* 16 bits from the input stream into the code value.*/void initialize_arithmetic_decoder( stream )BIT_FILE *stream;&#123;     int i;     code = 0;     for ( i = 0 ; i &lt; 16 ; i&#43;&#43; ) &#123;       code &lt;&lt;= 1;       code &#43;= InputBit( stream );     &#125;     low = 0;     high = 0xffff;&#125;/** Just figuring out what the present symbol is doesn't remove* it from the input bit stream.  After the character has been* decoded, this routine has to be called to remove it from the* input stream.*/void remove_symbol_from_stream( stream, s )BIT_FILE *stream;SYMBOL *s;&#123;     long range;/** First, the range is expanded to account for the symbol removal.*/     range = (long)( high - low ) &#43; l;     high = low &#43; (unsigned short int)             (( range * s-&gt;high_count ) / s-&gt;scale - 1);     low = low &#43; (unsigned short int)             (( range * s-&gt;low_count ) / s-&gt;scale );*/* Next, any possible bits are shipped out.*/     for ( ; ; ) &#123;/** If the MSDigits match, the bits will be shifted out.*/     if ( ( high &#38; 0x8000 ) == ( low &#38; 0x8000 ) ) &#123;     &#125;/** Else, if underflow is threatening, shift out the 2nd MSDigit.*/     else if ((low &#38; 0x4000) == 0x4000  &#38;&#38; (high &#38; 0x4000) == 0 ) &#123;       code ^= 0x4000;       low &#38;= 0x3ffff;       high |= 0x4000;     &#125; else/** Otherwise, nothing can be shifted out, so I return.*/          return;     low &lt;&lt;= 1;     high &lt;&lt;= 1;     high |= 1;     code &lt;&lt;= 1;     code &#43;= InputBit( stream );   &#125;&#125;/*************************** End of ARITH.C ****************************/</PRE><!--  END CODE //--><P><BR></P><CENTER><TABLE BORDER><TR><TD><A HREF="133-136.html">Previous</A></TD><TD><A HREF="../ewtoc.html">Table of Contents</A></TD><TD><A HREF="../ch06/153-154.html">Next</A></TD></TR></TABLE></CENTER></TD></TR></TABLE></BODY></HTML>

⌨️ 快捷键说明

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