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