rle.c

Go to the documentation of this file.
00001 
00042 #include "rle.h"
00043 
00044 
00049 int rle(unsigned char *output, const unsigned char *input, int len)
00050 {
00051     int count, index, i;
00052     unsigned char first;
00053     unsigned char *out;
00054 
00055 
00056     out = output;
00057     count = 0;
00058     while (count < len)
00059     {
00060         index = count;
00061         first = input[index++];
00062 
00063         /* Scan for bytes identical to the first one */
00064         while ((index < len) && (index - count < 127) && (input[index] == first))
00065             index++;
00066 
00067         if (index - count == 1)
00068         {
00069             /* Failed to "replicate" the current byte. See how many to copy.
00070              */
00071             while ((index < len) && (index - count < 127))
00072             {
00073                 /* Avoid a replicate run of only 2-bytes after a literal run.
00074                  * There is no gain in this, and there is a risc of loss if the
00075                  * run after the two identical bytes is another literal run.
00076                  * So search for 3 identical bytes.
00077                  */
00078                 if ((input[index] == input[index - 1]) &&
00079                     ((index > 1) && (input[index] == input[index - 2])))
00080                 {
00081                     /* Reset the index so we can back up these three identical
00082                      * bytes in the next run.
00083                      */
00084                     index -= 2;
00085                     break;
00086                 }
00087 
00088                 index++;
00089             }
00090 
00091             /* Output a run of uncompressed bytes: write length and values */
00092             *out++ = (unsigned char)(count - index);
00093             for (i = count; i < index; i++)
00094                 *out++ = input[i];
00095         }
00096         else
00097         {
00098             /* Output a compressed run: write length and value */
00099             *out++ = (unsigned char)(index - count);
00100             *out++ = first;
00101         }
00102 
00103         count = index;
00104     }
00105 
00106     /* Output EOF marker */
00107     *out++ = 0;
00108 
00109     return (out - output);
00110 }
00111 
00112 
00120 int unrle(unsigned char *output, const unsigned char *input)
00121 {
00122     signed char count;
00123     unsigned char *out;
00124     unsigned char value;
00125 
00126 
00127     out = output;
00128 
00129     for (;;)
00130     {
00131         count = (signed char)*input++;
00132         if (count > 0)
00133         {
00134             /* replicate run */
00135             value = *input++;
00136             while (count--)
00137                 *out++ = value;
00138         }
00139         else if (count < 0)
00140         {
00141             /* literal run */
00142             while (count++)
00143                 *out++ = *input++;
00144         }
00145         else
00146             /* EOF */
00147             break;
00148     }
00149 
00150     return (out - output);
00151 }