Algorithm 版 (精华区)

发信人: lofe ()感激生活(), 信区: Algorithm
标  题: Comp -- bitio.c
发信站: 哈工大紫丁香 (Sun Sep  3 08:31:21 2000), 转信

/*
  
   * Listing 4 -- bitio.c
  
   *
  
   * This routine contains a set of bit oriented i/o routines
  
   * used for arithmetic data compression.  The important fact to
  
   * know about these is that the first bit is stored in the msb of
  
   * the first byte of the output, like you might expect.
  
   *
  
   * Both input and output maintain a local buffer so that they only
  
   * have to do block reads and writes.  This is done in spite of the
  
   * fact that C standard I/O does the same thing.  If these
  
   * routines are ever ported to assembly language the buffering
  
   * will come in handy.
  
   *
  
   */
  
  #include <stdio.h>
  
  #include <stdlib.h>
  
  #include "coder.h"
  
  #include "bitio.h"

  
  #define BUFFER_SIZE 256
  
  static char buffer[ BUFFER_SIZE + 2 ]; /* This is the i/o buffer    */
  
  static char *current_byte;             /* Pointer to current byte   */

  
  static int output_mask;                /* During output, this byte  */
  
                                         /* contains the mask that is */
  
                                         /* applied to the output byte*/
  
                                         /* if the output bit is a 1  */

  
  static int input_bytes_left;           /* During input, these three */
  
  static int input_bits_left;            /* variables keep track of my*/
  
  static int past_eof;                   /* input state.  The past_eof*/
  
                                         /* byte comes about because  */
  
                                         /* of the fact that there is */
  
                                         /* a possibility the decoder */
  
                                         /* can legitimately ask for  */
  
                                         /* more bits even after the  */
  
                                         /* entire file has been      */
  
                                         /* sucked dry.               */


  
  /*
  
   * This routine is called once to initialze the output bitstream.
  
   * All it has to do is set up the current_byte pointer, clear out
  
   * all the bits in my current output byte, and set the output mask
  
   * so it will set the proper bit next time a bit is output.
  
   */
  
  void initialize_output_bitstream()
  
{
  
      current_byte = buffer;
  
      *current_byte = 0;
  
      output_mask = 0x80;
  
}

  
  /*
  
   * The output bit routine just has to set a bit in the current byte
  
   * if requested to.  After that, it updates the mask.  If the mask
  
   * shows that the current byte is filled up, it is time to go to the
  
   * next character in the buffer.  If the next character is past the
  
   * end of the buffer, it is time to flush the buffer.
  
   */
  
  void output_bit( FILE *stream, int bit )
  
{
  
      if ( bit )
  
          *current_byte |= output_mask;
  
      output_mask >>= 1;
  
      if ( output_mask == 0 )
  
      {
  
          output_mask = 0x80;
  
          current_byte++;
  
          if ( current_byte == ( buffer + BUFFER_SIZE ) )
  
          {
  
              fwrite( buffer, 1, BUFFER_SIZE, stream );
  
              current_byte = buffer;
  
          }
  
          *current_byte = 0;
  
      }
  
}

  
  /*
  
   * When the encoding is done, there will still be a lot of bits and
  
   * bytes sitting in the buffer waiting to be sent out.  This routine
  
   * is called to clean things up at that point.
  
   */
  
  void flush_output_bitstream( FILE *stream )
  
{
  
      fwrite( buffer, 1, (size_t)( current_byte - buffer ) + 1, stream );
  
      current_byte = buffer;
  
}

  
  /*
  
   * Bit oriented input is set up so that the next time the input_bit
  
   * routine is called, it will trigger the read of a new block.  That
  
   * is why input_bits_left is set to 0.
  
   */
  
  void initialize_input_bitstream()
  
{
  
      input_bits_left = 0;
  
      input_bytes_left = 1;
  
      past_eof = 0;
  
}

  
  /*
  
   * This routine reads bits in from a file.  The bits are all sitting
  
   * in a buffer, and this code pulls them out, one at a time.  When the
  
   * buffer has been emptied, that triggers a new file read, and the
  
   * pointers are reset.  This routine is set up to allow for two dummy
  
   * bytes to be read in after the end of file is reached.  This is because
  
   * we have to keep feeding bits into the pipeline to be decoded so that
  
   * the old stuff that is 16 bits upstream can be pushed out.
  
   */
  
  short int input_bit( FILE *stream )
  
{
  
      if ( input_bits_left == 0 )
  
      {
  
          current_byte++;
  
          input_bytes_left--;
  
          input_bits_left = 8;
  
          if ( input_bytes_left == 0 )
  
          {
  
              input_bytes_left = fread( buffer, 1, BUFFER_SIZE, stream );
  
              if ( input_bytes_left == 0 )
  
              {
  
                  if ( past_eof )
  
                  {
  
                      fprintf( stderr, "Bad input file\n" );
  
                      exit( -1 );
  
                  }
  
                  else
  
                  {
  
                      past_eof = 1;
  
                      input_bytes_left = 2;
  
                  }
  
              }
  
              current_byte = buffer;
  
          }
  
      }
  
      input_bits_left--;
  
      return ( ( *current_byte >> input_bits_left ) & 1 );
  
}

  
  /*
  
   * When monitoring compression ratios, we need to know how many
  
   * bytes have been output so far.  This routine takes care of telling
  
   * how many bytes have been output, including pending bytes that
  
   * haven't actually been written out.
  
   */
  
  long bit_ftell_output( FILE *stream )
  
{
  
      long total;

  
      total = ftell( stream );
  
      total += current_byte - buffer;
  
      total += underflow_bits/8;
  
      return( total );
  
}

  
  /*
  
   * When monitoring compression ratios, we need to know how many bits
  
   * have been read in so far.  This routine tells how many bytes have
  
   * been read in, excluding bytes that are pending in the buffer.
  
   */
  
  long bit_ftell_input( FILE *stream )
  
{
  
      return( ftell( stream ) - input_bytes_left + 1 );
  
}

  
  
--
          _____________________________
          Every problem has a solution.

optooff@mail.hust.edu.cn
www.netease.com/~hansen
※ 修改:.haojs 于 Sep  3 08:28:54 修改本文.[FROM: bbs.hit.edu.cn]
--
※ 转寄:.武汉白云黄鹤站 bbs.whnet.edu.cn.[FROM: bbs.hit.edu.cn]

--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: haojs.bbs@bbs.whnet.]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:206.232毫秒