home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / HPACK78S.ZIP / lza / pack.c < prev    next >
C/C++ Source or Header  |  1992-09-22  |  4KB  |  159 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                            HPACK Multi-System Archiver                        *
  4. *                            ===========================                        *
  5. *                                                                            *
  6. *                              HPACK Arithmetic Encoder                        *
  7. *                             PACKF.C  Updated 06/11/91                        *
  8. *                                                                            *
  9. * This program is protected by copyright and as such any use or copying of    *
  10. *  this code for your own purposes directly or indirectly is highly uncool    *
  11. *                      and if you do so there will be....trubble.                *
  12. *                 And remember: We know where your kids go to school.            *
  13. *                                                                            *
  14. *        Copyright 1990, 1991  Peter C.Gutmann.  All rights reserved            *
  15. *                                                                            *
  16. ****************************************************************************/
  17.  
  18. #ifdef __MAC__
  19.   #include "defs.h"
  20.   #include "fastio.h"
  21. #else
  22.   #include "defs.h"
  23.   #include "io/fastio.h"
  24. #endif /* __MAC__ */
  25.  
  26. /* Count of no.bytes output */
  27.  
  28. extern long outByteCount;
  29.  
  30. /****************************************************************************
  31. *                                                                            *
  32. *                                Bit Output Routines                            *
  33. *                                                                            *
  34. ****************************************************************************/
  35.  
  36. /* The bit buffer */
  37.  
  38. static BYTE outBuffer;            /* Bit buffer for output */
  39. static int outBitsToGo;            /* Number of bits free in buffer */
  40.  
  41. /* Output a bit */
  42.  
  43. static void outBit( const int bit )
  44.     {
  45.     /* Put bit in buffer */
  46.     outBuffer <<= 1;
  47.     outBuffer |= bit;
  48.  
  49.     /* Output buffer if it is now full */
  50.     if( !--outBitsToGo )
  51.         {
  52.         fputByte( outBuffer );
  53.         outByteCount++;
  54.         outBitsToGo = 8;
  55.         }
  56.     }
  57.  
  58. /****************************************************************************
  59. *                                                                            *
  60. *                            Arithmetic Coding Routines                        *
  61. *                                                                            *
  62. ****************************************************************************/
  63.  
  64. /* The current state of the encoding */
  65.  
  66. WORD low, high;        /* Ends of the current code region */
  67. int bitsToFollow;    /* No.opposing bits to output after the next bit */
  68.  
  69. /* Initialise variables used in the arithmetic coding */
  70.  
  71. void startEncode( void )
  72.     {
  73.     low = 0;
  74.     high = 0xFFFF;            /* Full code range */
  75.     bitsToFollow = 0;        /* No bits to follow next */
  76.  
  77.     /* Set the bit buffer to empty */
  78.     outBitsToGo = 8;
  79.     }
  80.  
  81. /* Encode a symbol */
  82.  
  83. void encode( const int cumFreq0, \
  84.              const int cumFreqLower, const int cumFreqUpper )
  85.     {
  86.     BYTE highBit;
  87.     LONG range = ( LONG ) ( high - low ) + 1L;    /* Size of curr.code region */
  88.  
  89.     /* Narrow the code region to that allotted to this symbol */
  90.     high = low + ( WORD ) ( ( range * cumFreqLower ) / cumFreq0 - 1 );
  91.     low += ( WORD ) ( ( range * cumFreqUpper ) / cumFreq0 );
  92.  
  93.     while( TRUE )
  94.         {
  95.         if( ( high & 0x8000 ) == ( low & 0x8000 ) )
  96.             {
  97.             highBit = ( high & 0x8000 ) ? 1 : 0;
  98.             outBuffer <<= 1;
  99.             outBuffer |= highBit;
  100.             if( !--outBitsToGo )
  101.                 {
  102.                 fputByte( outBuffer );
  103.                 outByteCount++;
  104.                 outBitsToGo = 8;
  105.                 }
  106.             while( bitsToFollow )
  107.                 {
  108.                 outBuffer <<= 1;
  109.                 outBuffer |= !highBit;
  110.                 if( !--outBitsToGo )
  111.                     {
  112.                     fputByte( outBuffer );
  113.                     outByteCount++;
  114.                     outBitsToGo = 8;
  115.                     }
  116.                 bitsToFollow--;
  117.                 }
  118.             }
  119.         else
  120.             if( ( low & 0x4000 ) && !( high & 0x4000 ) )
  121.                     {
  122.                     /* Output an opposite bit later if in middle half */
  123.                     bitsToFollow++;
  124.                     low &= 0x3FFF;
  125.                     high |= 0x4000;
  126.                     }
  127.                 else
  128.                     break;
  129.  
  130.         /* Now scale up code range */
  131.         low <<= 1;            /* low = 2 * low */
  132.         high <<= 1;            /* 2 * high + 1 */
  133.         high++;
  134.         }
  135.     }
  136.  
  137. /* Finish encoding the stream by outputting two bits that select the quarter
  138.    that the current code range contains */
  139.  
  140. void endEncode( void )
  141.     {
  142.     BYTE bit = ( low & 0x4000 ) ? 0 : 1, padding;
  143.     static BYTE padBits[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
  144.  
  145.     bitsToFollow++;
  146.     outBit( bit );
  147.     while( bitsToFollow-- )
  148.         outBit( !bit );
  149.  
  150.     /* Flush out the last bits, padding with ones or zeroes depending on
  151.        the value of the last bit */
  152.     if( outBitsToGo < 8 )
  153.         {
  154.         padding = ( outBuffer & 1 ) ? padBits[ outBitsToGo ] : 0;
  155.         fputByte( ( outBuffer << outBitsToGo ) | padding );
  156.         outByteCount++;
  157.         }
  158.     }
  159.