| iMatix home page
| << | < | > | >>
SFL Logo SFL
Version 2.11

 

compress_rle

#include "sflcomp.h"
word
compress_rle (
    byte *src,
    byte *dst,
    word src_size)

Synopsis

Takes a block of uncompressed data in src, compresses it using a RLE algorithm and places the result in dst. To decompress the data, use the expand rle () function. Returns the size of the compressed data. The dst buffer should be 10% larger than the src buffer. The src buffer must be at least src_size + 1 bytes long. It may be modified. The compressed data contains these strings:
[01-7F][data...] String of uncompressed data, 1 to 127 bytes.
[83-FF][byte] Run of 3 to 127 identical bytes.
[80][len][byte] Run of 128 to 255 identical bytes.
[81][lo][hi][byte] Run of 256 to 2^16 identical bytes.
[82][len] Run of 3 to 255 spaces.
[00][len] Run of 3 to 255 binary zeroes.

Source Code - (sflcomp.c)

{
    word
        dst_size,                       /*  Size of compressed data          */
        src_scan,                       /*  Scan through source data         */
        run_end,                        /*  Points to end of run of bytes    */
        length = 0;                     /*  Size of the run or string        */
    byte
        cur_byte,                       /*  Next byte to process             */
        *header;                        /*  Header of unpacked string        */
    Bool
        have_run;                       /*  TRUE when we have a run          */

    src_scan = 0;                       /*  Start at beginning of source     */
    dst_size = 0;                       /*  No output yet                    */
    header   = NULL;                    /*  No open unpacked string          */
    while (src_scan < src_size)
      {
        cur_byte = src [src_scan++];
        have_run = FALSE;               /*  Unless we find a run             */

        /*  Three identical bytes signals the start of a run                 */
        if (cur_byte == src [src_scan]
        &&  cur_byte == src [src_scan + 1]
        && (src_scan + 1 < src_size))
          {
            /*  Stick-in a sentinel character to ensure that the run ends    */
            src [src_size] = !cur_byte;
            run_end = src_scan;         /*  src_scan <= src_size             */
            while (src [run_end] == cur_byte)
                run_end++;

            have_run = TRUE;
            if (header)                 /*  If we have a previous unpacked   */
              {                         /*    string, close it               */
                *header = (byte) length;
                header  = NULL;
              }
            length = run_end - src_scan + 1;
            src_scan = run_end;
          }
        if (have_run)
          {
            /*  We compress short runs of spaces and nulls separately        */
            if (length < 256 && cur_byte == 0)
              {
                dst [dst_size++] = 0x00;
                dst [dst_size++] = (byte) length;
              }
            else
            if (length < 256 && cur_byte == ' ')
              {
                dst [dst_size++] = 0x82;
                dst [dst_size++] = (byte) length;
              }
            else
            if (length < 128)
              {
                dst [dst_size++] = (byte) length | 0x80;
                dst [dst_size++] = cur_byte;
              }
            else
            if (length < 256)           /*  Short run 128-255 bytes          */
              {
                dst [dst_size++] = 0x80;
                dst [dst_size++] = (byte) length;
                dst [dst_size++] = cur_byte;
              }
            else                        /*  Long run 256-2^16 bytes          */
              {
                dst [dst_size++] = 0x81;
                dst [dst_size++] = (byte) (length & 0xff);
                dst [dst_size++] = (byte) (length >> 8);
                dst [dst_size++] = cur_byte;
              }
          }
        else
          {
            if (!header)                /*  Start new unpacked string if     */
              {                         /*    necessary                      */
                header = &dst [dst_size++];
                length = 0;
              }
            dst [dst_size++] = cur_byte;
            if (++length == 127)        /*  Each string can be up to 127     */
              {                         /*    bytes long (high bit cleared)  */
                *header = (byte) length;
                header  = NULL;
              }
          }
      }
    if (header)                         /*  If we have a previous unpacked   */
      {                                 /*    string, close it               */
        *header = (byte) length;
        header  = NULL;
      }
    return (dst_size);                  /*  Return compressed data size      */
}

| << | < | > | >> iMatix Copyright © 1996-2000 iMatix Corporation