/* -- 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);
}