home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 215 / DDJ9210.ZIP / DFLT14.ZIP / HUFFC.C < prev    next >
Text File  |  1992-06-16  |  3KB  |  119 lines

  1. /* ------------------- huffc.c -------------------- */
  2.  
  3. #include "dflat.h"
  4. #include "htree.h"
  5.  
  6. extern struct htree *ht;
  7. extern int root;
  8. extern int treect;
  9. static int lastchar = '\n';
  10.  
  11. static void compress(FILE *, int, int);
  12. static void outbit(FILE *fo, int bit);
  13.  
  14. static int fgetcx(FILE *fi)
  15. {
  16.     int c;
  17.  
  18.     /* ------- bypass comments ------- */
  19.     if ((c = fgetc(fi)) == ';' && lastchar == '\n')
  20.         do    {
  21.             while (c != '\n' && c != EOF)
  22.                 c = fgetc(fi);
  23.         } while (c == ';');
  24.     lastchar = c;
  25.     return c;
  26. }
  27.  
  28. void main(int argc, char *argv[])
  29. {
  30.     FILE *fi, *fo;
  31.     int c;
  32.     BYTECOUNTER bytectr = 0;
  33.  
  34.     if (argc < 3)   {
  35.         printf("\nusage: huffc infile outfile");
  36.         exit(1);
  37.     }
  38.  
  39.     if ((fi = fopen(argv[1], "rb")) == NULL)    {
  40.         printf("\nCannot open %s", argv[1]);
  41.         exit(1);
  42.     }
  43.     if ((fo = fopen(argv[2], "wb")) == NULL)    {
  44.         printf("\nCannot open %s", argv[2]);
  45.         fclose(fi);
  46.         exit(1);
  47.     }
  48.  
  49.     ht = calloc(256, sizeof(struct htree));
  50.  
  51.     /* - read the input file and count character frequency - */
  52.     while ((c = fgetcx(fi)) != EOF)   {
  53.         c &= 255;
  54.         ht[c].cnt++;
  55.         bytectr++;
  56.     }
  57.  
  58.     /* ---- build the huffman tree ---- */
  59.     buildtree();
  60.  
  61.     /* --- write the byte count to the output file --- */
  62.     fwrite(&bytectr, sizeof bytectr, 1, fo);
  63.  
  64.     /* --- write the tree count to the output file --- */
  65.     fwrite(&treect, sizeof treect, 1, fo);
  66.  
  67.     /* --- write the root offset to the output file --- */
  68.     fwrite(&root, sizeof root, 1, fo);
  69.  
  70.     /* -- write the tree to the output file -- */
  71.     for (c = 256; c < treect; c++)   {
  72.         int lf = ht[c].left;
  73.         int rt = ht[c].right;
  74.         fwrite(&lf, sizeof lf, 1, fo);
  75.         fwrite(&rt, sizeof rt, 1, fo);
  76.     }
  77.  
  78.     /* ------ compress the file ------ */
  79.     fseek(fi, 0L, 0);
  80.     while ((c = fgetcx(fi)) != EOF)
  81.         compress(fo, (c & 255), 0);
  82.     outbit(fo, -1);
  83.     fclose(fi);
  84.     fclose(fo);
  85.     free(ht);
  86.     exit(0);
  87. }
  88.  
  89. /* ---- compress a character value into a bit stream ---- */
  90. static void compress(FILE *fo, int h, int child)
  91. {
  92.     if (ht[h].parent != -1)
  93.         compress(fo, ht[h].parent, h);
  94.     if (child)  {
  95.         if (child == ht[h].right)
  96.             outbit(fo, 0);
  97.         else if (child == ht[h].left)
  98.             outbit(fo, 1);
  99.     }
  100. }
  101.  
  102. static char out8;
  103. static int ct8;
  104.  
  105. /* -- collect and write bits to the compressed output file -- */
  106. static void outbit(FILE *fo, int bit)
  107. {
  108.     if (ct8 == 8 || bit == -1)  {
  109.         while (ct8 < 8)    {
  110.             out8 <<= 1;
  111.             ct8++;
  112.         }
  113.         fputc(out8, fo);
  114.         ct8 = 0;
  115.     }
  116.     out8 = (out8 << 1) | bit;
  117.     ct8++;
  118. }
  119.