next up previous contents index Search
Next: 0.10.1.2 References Up: 0.10.1 Run-Length Encoding Previous: 0.10.1 Run-Length Encoding

0.10.1.1 Source Code



/* -- rle_encode.c -- */



#include 
 #include 
 
 #include "global.h"
 #include "debug.h"
 
 //
 // Modified version of Rex & Binstock's rle1.c, see Practical Algorithms
 // for Programmers pg. 470-472.
 //
 
 
 //
 // This is the byte value that will denote an encoded run sequence
 //
 #define FLAG            (char) 0xF0
 
 //
 // Input buffer size
 //
 #define BUFFER_SIZE     30000
 
 //
 // Macro for writing a three-byte run sequence code to output
 //
 #define WRITE_CODE(a, b, c)                               \
     ASSERT((b) > 3);                                      \
     ASSERT((b) < 260);                                    \
     fprintf(pfOutFile, "%c%c%c", (a), (b - 4), (c));      \
 
 
 //
 // Global file handles
 //
 FILE *pfInFile, *pfOutFile;
 
 int main (int argc, char *argv[])
 {
   char *buf;
   char chPrevChar;
   DWORD dwBytesRead;
   DWORD dwCount;
   DWORD dwI;
   BOOL fEof = FALSE;
   BOOL fFirstTime = TRUE;
 
   if (argc != 3) 
   {
     fprintf(stderr, "Usage: %s infile outfile\n", argv[0]);
     exit(1);
   }
 
   if ((pfInFile = fopen(argv[1], "rb")) == NULL)
   {
     perror(argv[1]);
     exit(1);
   }
 
   if ((pfOutFile = fopen(argv[2], "wb")) == NULL)
   {
     perror(argv[2]);
     exit(1);
   }
  
   //
   // This code writes a header to the output file -- it records what
   // value was used as the FLAG and that this is an RLE encoded file.
   // This header can be omitted if the flag value will always be the
   // same and you don't care about magic numbers idenfitying binary file
   // types.
   //
 
   fprintf(pfOutFile, "%c%c%c%c", 'R', 'L', 'E', FLAG);
 
   //
   // Get memory for the buffer
   //
 
   buf = (char *) malloc(BUFFER_SIZE);
   if (!buf) 
   {
     fclose(pfInFile);
     fclose(pfOutFile);
     fprintf(stderr, "Out of memory, cannot allocate buffer.\n");
     exit(1);
   }
 
   //
   // Process input
   //
   
   while (!fEof)
   {
     dwBytesRead = fread(buf, 1, BUFFER_SIZE, pfInFile);
     if (!dwBytesRead) 
     {
       fEof = TRUE;
       break;
     }
 
 
     for (dwI = 0; dwI < dwBytesRead; dwI++) 
     {
 
       //
       // First time is a special case
       //
 
       if (fFirstTime) 
       {
 	chPrevChar = buf[dwI];
 	dwCount = 1;
 	fFirstTime = FALSE;
 	dwI++;
       }
 
 
       //
       // See if we have a run in the making
       //
       if (buf[dwI] == chPrevChar) 
       {
 	dwCount += 1;
 	if (dwCount == 259)
 	{
 	  WRITE_CODE(FLAG, dwCount, chPrevChar);
 	  dwCount = 0;
 	}
 	continue;
       }
 
       //
       // Else there's a new character... possibly write data,
       // definately reset the count and prevchar...
       //
       else
       {
 
 	// 
 	// Write code
 	//
 	if (dwCount < 3)
 	{
 
 	  //
 	  // Non-adjusted count for flag character.
 	  //
 	  if (chPrevChar == FLAG)
 	  {
 	    fprintf(pfOutFile, "%c%c%c", FLAG, dwCount, FLAG);
 	  }
 	  else
 	  {
 	    do
 	    {
 	      fputc(chPrevChar, pfOutFile);
 	    }
 	    while (--dwCount);
 	  }
 	}
 	else
 	{
 	  WRITE_CODE(FLAG, dwCount, chPrevChar);
 	}
 	
 	chPrevChar = buf[dwI];
 	dwCount = 1;
       }
     }
 
     //
     // End of bytes read... is it eof?
     //
     if (dwBytesRead < BUFFER_SIZE)
     {
       fEof = TRUE;
     }
 
   }
 
   // 
   // At EOF, flush out buffers
   //
   if (dwCount < 3)
   {
     if (chPrevChar == FLAG)
     {
 
       //
       // Encode a flag char with FLAG, count, FLAG -- note that in 
       // this case the count is not adjusted.
       //
       fprintf(pfOutFile, "%c%c%c", FLAG, dwCount, FLAG);
     }
     else
     {
       do
       {
 	fputc(chPrevChar, pfOutFile);
       } 
       while(--dwCount);
     }
   }
   else
   {
     WRITE_CODE(FLAG, dwCount, chPrevChar);
   }
 
   fclose(pfInFile);
   fclose(pfOutFile);
   exit(0);
 }
 




Scott Gasch
1999-07-09