home *** CD-ROM | disk | FTP | other *** search
/ The Elite Hackers Toolkit / TheEliteHackersToolkitVolume1_1998.rar / HACKERS.BIN / hackers / snow_tar.gz / snow.tar / snow / compress.c next >
C/C++ Source or Header  |  1996-12-28  |  4KB  |  272 lines

  1. /*
  2.  * Compression routines for the SNOW steganography program.
  3.  * Uses simple Huffman coding.
  4.  *
  5.  * Written by Matthew Kwan - December 1996
  6.  */
  7.  
  8. #include "snow.h"
  9.  
  10.  
  11. /*
  12.  * The Huffman codes.
  13.  */
  14.  
  15. static const char    *huffcodes[256] = {
  16. #include "huffcode.h"
  17. };
  18.  
  19.  
  20. /*
  21.  * Local variables used for compression.
  22.  */
  23.  
  24. static int    compress_bit_count;
  25. static int    compress_value;
  26. static int    compress_bits_in;
  27. static int    compress_bits_out;
  28.  
  29.  
  30. /*
  31.  * Initialize the compression routines.
  32.  */
  33.  
  34. void
  35. compress_init (void)
  36. {
  37.     compress_bit_count = 0;
  38.     compress_value = 0;
  39.     compress_bits_in = 0;
  40.     compress_bits_out = 0;
  41.  
  42.     encrypt_init ();
  43. }
  44.  
  45.  
  46. /*
  47.  * Compress a single bit.
  48.  */
  49.  
  50. BOOL
  51. compress_bit (
  52.     int        bit,
  53.     FILE        *inf,
  54.     FILE        *outf
  55. ) {
  56.     if (!compress_flag)
  57.         return (encrypt_bit (bit, inf, outf));
  58.  
  59.     compress_bits_in++;
  60.     compress_value = (compress_value << 1) | bit;
  61.  
  62.     if (++compress_bit_count == 8) {
  63.         const char    *s;
  64.  
  65.         for (s = huffcodes[compress_value]; *s != '\0'; s++) {
  66.         int    bit;
  67.  
  68.         if (*s == '1')
  69.             bit = 1;
  70.         else if (*s == '0')
  71.             bit = 0;
  72.         else {
  73.             fprintf (stderr, "Illegal Huffman character '%c'\n", *s);
  74.             return (FALSE);
  75.         }
  76.  
  77.         if (!encrypt_bit (bit, inf, outf))
  78.             return (FALSE);
  79.         compress_bits_out++;
  80.         }
  81.  
  82.         compress_value = 0;
  83.         compress_bit_count = 0;
  84.     }
  85.  
  86.     return (TRUE);
  87. }
  88.  
  89.  
  90. /*
  91.  * Flush the contents of the compression routines.
  92.  */
  93.  
  94. BOOL
  95. compress_flush (
  96.     FILE        *inf,
  97.     FILE        *outf
  98. ) {
  99.     if (compress_bit_count != 0 && !quiet_flag)
  100.         fprintf (stderr, "Warning: residual of %d bits not compressed\n",
  101.                             compress_bit_count);
  102.  
  103.     if (compress_bits_out > 0 && !quiet_flag) {
  104.         double    cpc = (double) (compress_bits_in - compress_bits_out)
  105.                     / (double) compress_bits_in * 100.0;
  106.  
  107.         if (cpc < 0.0)
  108.         fprintf (stderr,
  109. "Compression enlarged data by %.2f%% - recommend not using compression\n",
  110.                                 -cpc);
  111.         else
  112.         fprintf (stderr, "Compressed by %.2f%%\n", cpc);
  113.     }
  114.  
  115.     return (encrypt_flush (inf, outf));
  116. }
  117.  
  118.  
  119. /*
  120.  * Local variables used for output.
  121.  */
  122.  
  123. static int    output_bit_count;
  124. static int    output_value;
  125.  
  126.  
  127. /*
  128.  * Initialize the output variables.
  129.  */
  130.  
  131. static void
  132. output_init (void)
  133. {
  134.     output_bit_count = 0;
  135.     output_value = 0;
  136. }
  137.  
  138.  
  139. /*
  140.  * Output a single bit.
  141.  */
  142.  
  143. static BOOL
  144. output_bit (
  145.     int        bit,
  146.     FILE        *outf
  147. ) {
  148.     output_value = (output_value << 1) | bit;
  149.  
  150.     if (++output_bit_count == 8) {
  151.         if (fputc (output_value, outf) == EOF) {
  152.         perror ("Output file");
  153.         return (FALSE);
  154.         }
  155.  
  156.         output_value = 0;
  157.         output_bit_count = 0;
  158.     }
  159.  
  160.     return (TRUE);
  161. }
  162.  
  163.  
  164. /*
  165.  * Flush the contents of the output routines.
  166.  */
  167.  
  168. static BOOL
  169. output_flush (
  170.     FILE        *outf
  171. ) {
  172.     if (output_bit_count > 2 && !quiet_flag)
  173.         fprintf (stderr, "Warning: residual of %d bits not output\n",
  174.                             output_bit_count);
  175.  
  176.     return (TRUE);
  177. }
  178.  
  179.  
  180. /*
  181.  * Local variables used for uncompression.
  182.  */
  183.  
  184. static int    uncompress_bit_count;
  185. static char    uncompress_value[256];
  186.  
  187.  
  188. /*
  189.  * Initialize the uncompression routines.
  190.  */
  191.  
  192. void
  193. uncompress_init (void)
  194. {
  195.     uncompress_bit_count = 0;
  196.  
  197.     output_init ();
  198. }
  199.  
  200.  
  201. /*
  202.  * Find the Huffman code string that matches.
  203.  */
  204.  
  205. static int
  206. huffcode_find (
  207.     const char    *str
  208. ) {
  209.     int        i;
  210.  
  211.     for (i=0; i<256; i++)
  212.         if (strcmp (str, huffcodes[i]) == 0)
  213.         return (i);
  214.  
  215.     return (-1);
  216. }
  217.  
  218.  
  219. /*
  220.  * Uncompress a single bit.
  221.  */
  222.  
  223. BOOL
  224. uncompress_bit (
  225.     int        bit,
  226.     FILE        *outf
  227. ) {
  228.     int        code;
  229.  
  230.     if (!compress_flag)
  231.         return (output_bit (bit, outf));
  232.  
  233.     uncompress_value[uncompress_bit_count++] = bit ? '1' : '0';
  234.     uncompress_value[uncompress_bit_count] = '\0';
  235.  
  236.     if ((code = huffcode_find (uncompress_value)) >= 0) {
  237.         int        i;
  238.  
  239.         for (i=0; i<8; i++) {
  240.         int    b = ((code & (128 >> i)) != 0) ? 1 : 0;
  241.  
  242.         if (!output_bit (b, outf))
  243.             return (FALSE);
  244.         }
  245.  
  246.         uncompress_bit_count = 0;
  247.     }
  248.  
  249.     if (uncompress_bit_count >= 255) {
  250.         fprintf (stderr, "Error: Huffman uncompress buffer overflow\n");
  251.         return (FALSE);
  252.     }
  253.  
  254.     return (TRUE);
  255. }
  256.  
  257.  
  258. /*
  259.  * Flush the contents of the uncompression routines.
  260.  */
  261.  
  262. BOOL
  263. uncompress_flush (
  264.     FILE        *outf
  265. ) {
  266.     if (uncompress_bit_count > 2 && !quiet_flag)
  267.         fprintf (stderr, "Warning: residual of %d bits not uncompressed\n",
  268.                             uncompress_bit_count);
  269.  
  270.     return (output_flush (outf));
  271. }
  272.