rle.c

Go to the documentation of this file.
00001 
00042 /*#*
00043  *#* $Log$
00044  *#* Revision 1.4  2006/07/19 12:56:28  bernie
00045  *#* Convert to new Doxygen style.
00046  *#*
00047  *#* Revision 1.3  2005/11/04 16:20:02  bernie
00048  *#* Fix reference to README.devlib in header.
00049  *#*
00050  *#* Revision 1.2  2004/08/25 14:12:09  rasky
00051  *#* Aggiornato il comment block dei log RCS
00052  *#*
00053  *#* Revision 1.1  2004/08/04 02:35:54  bernie
00054  *#* Import simple RLE algorithm.
00055  *#*
00056  *#*/
00057 
00058 #include "rle.h"
00059 
00060 
00065 int rle(unsigned char *output, const unsigned char *input, int len)
00066 {
00067     int count, index, i;
00068     unsigned char first;
00069     unsigned char *out;
00070 
00071 
00072     out = output;
00073     count = 0;
00074     while (count < len)
00075     {
00076         index = count;
00077         first = input[index++];
00078 
00079         /* Scan for bytes identical to the first one */
00080         while ((index < len) && (index - count < 127) && (input[index] == first))
00081             index++;
00082 
00083         if (index - count == 1)
00084         {
00085             /* Failed to "replicate" the current byte. See how many to copy.
00086              */
00087             while ((index < len) && (index - count < 127))
00088             {
00089                 /* Avoid a replicate run of only 2-bytes after a literal run.
00090                  * There is no gain in this, and there is a risc of loss if the
00091                  * run after the two identical bytes is another literal run.
00092                  * So search for 3 identical bytes.
00093                  */
00094                 if ((input[index] == input[index - 1]) &&
00095                     ((index > 1) && (input[index] == input[index - 2])))
00096                 {
00097                     /* Reset the index so we can back up these three identical
00098                      * bytes in the next run.
00099                      */
00100                     index -= 2;
00101                     break;
00102                 }
00103 
00104                 index++;
00105             }
00106 
00107             /* Output a run of uncompressed bytes: write length and values */
00108             *out++ = (unsigned char)(count - index);
00109             for (i = count; i < index; i++)
00110                 *out++ = input[i];
00111         }
00112         else
00113         {
00114             /* Output a compressed run: write length and value */
00115             *out++ = (unsigned char)(index - count);
00116             *out++ = first;
00117         }
00118 
00119         count = index;
00120     }
00121 
00122     /* Output EOF marker */
00123     *out++ = 0;
00124 
00125     return (out - output);
00126 }
00127 
00128 
00136 int unrle(unsigned char *output, const unsigned char *input)
00137 {
00138     signed char count;
00139     unsigned char *out;
00140     unsigned char value;
00141 
00142 
00143     out = output;
00144 
00145     for (;;)
00146     {
00147         count = (signed char)*input++;
00148         if (count > 0)
00149         {
00150             /* replicate run */
00151             value = *input++;
00152             while (count--)
00153                 *out++ = value;
00154         }
00155         else if (count < 0)
00156         {
00157             /* literal run */
00158             while (count++)
00159                 *out++ = *input++;
00160         }
00161         else
00162             /* EOF */
00163             break;
00164     }
00165 
00166     return (out - output);
00167 }