⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sflcomp.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 3 页
字号:
          }
        else                            /*  Run of 2 or more bytes           */
          {
            switch (cur_byte)
              {
                case 0x00:              /*  Run of non-zero bytes            */
                    length = src [src_scan++];
                    if (length == 0)    /*  Stored as double-byte            */
                      {
                        length   = src [src_scan++];
                        length  += src [src_scan++] << 8;
                      }
                    cur_byte = src [src_scan++];
                    break;
                case 0x80:              /*  256-2^16 zeroes                  */
                    length   = src [src_scan++];
                    length  += src [src_scan++] << 8;
                    cur_byte = 0;
                    break;
                case 0x81:              /*  128 to 255 zeroes                */
                    length   = src [src_scan++];
                    cur_byte = 0;
                    break;
                default:                /*  2 to 127 zeroes                  */
                    length   = cur_byte & 127;
                    cur_byte = 0;
              }
            memset (dst + dst_size, cur_byte, length);
            dst_size += length;
          }
      }
    return (dst_size);                  /*  Return expanded data size        */
}


/*  ---------------------------------------------------------------------[<]-
    Function: compress_bits

    Synopsis: Similar to compress_rle(), but optimised towards compression
    of sparse bitmaps.  Use this when you are playing with large, sparse
    bitmaps.  You must use expand_bits () to decompress a block compressed
    with this function.  Returns the size of the compressed data.  The dst
    buffer should be 10% larger than the src buffer for worst cases.  The
    src buffer must be at least src_size + 1 bytes long.  It may be
    modified.  The compressed data contains these strings:
    <Table>
    [00-07]                 Single byte containing a bit in position 0 to 7.
    [08-7F][data...]        String of uncompressed data, 1 to 120 bytes.
    [82-FF]                 Run of 1 to 126 binary zeroes.
    [81][00-FD]             Run of 127 to 380 binary zeroes.
    [81][FE][len][byte]     Run of 4 to 255 identical bytes.
    [81][FF][lo][hi][byte]  Run of 256 to 2^16 identical bytes.
    [80][lo][hi]            Run of 381 to 2^16 binary zeroes.
    </Table>
    ---------------------------------------------------------------------[>]-*/

word
compress_bits (
    byte *src,
    byte *dst,
    word src_size)
{
    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        */
    static byte
        single_bits [256];              /*  Bytes with one bit set           */
    static Bool
        initialised = FALSE;            /*  First time flag                  */

    /*  The single_bits table provides a fast lookup for bytes with          */
    /*  one bit set.  The 'interesting' bytes are non-zero in the table      */
    /*  where their value is the output code value (0-7) + 1.                */
    if (!initialised)                   /*  First time?  Initialise          */
      {
        memset (single_bits, 0, 256);
        single_bits [1]   = 1;
        single_bits [2]   = 2;
        single_bits [4]   = 3;
        single_bits [8]   = 4;
        single_bits [16]  = 5;
        single_bits [32]  = 6;
        single_bits [64]  = 7;
        single_bits [128] = 8;
      }

    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++];

        /*- Look for 1 or more binary zeroes, and compress into a run -------*/

        if (cur_byte == 0)
          {
            src [src_size] = 0xff;      /*  Stop with a sentinel             */
            run_end = src_scan;         /*  src_scan <= src_size             */
            while (src [run_end] == 0)
                run_end++;

            if (header)                 /*  If we have a previous unpacked   */
              {                         /*    string, close it               */
                *header = (byte) length + 7;
                header  = NULL;
              }
            length = run_end - src_scan + 1;
            src_scan = run_end;
            if (length < 127)           /*  1-126 binary zeroes              */
                dst [dst_size++] = (byte) (++length | 0x80);
            else
            if (length < 381)           /*  127-380 binary zeroes            */
              {
                dst [dst_size++] = 0x81;
                dst [dst_size++] = (byte) length - 127;
              }
            else                        /*  381-2^16 binary zeroes           */
              {
                dst [dst_size++] = 0x80;
                dst [dst_size++] = (byte) (length & 0xff);
                dst [dst_size++] = (byte) (length >> 8);
              }
          }
        else

        /*- Next, look for bytes with 1 bit set; we encode these as 1 byte --*/

        if (single_bits [cur_byte])     /*  Single bit value?                */
          {
            dst [dst_size++] = single_bits [cur_byte] - 1;
            if (header)                 /*  If we have a previous unpacked   */
              {                         /*    string, close it               */
                *header = (byte) length + 7;
                header  = NULL;
              }
          }
        else

        /*- Next, look for a run of 4 or more identical (non-zero) bytes ----*/

        if (cur_byte == src [src_scan]
        &&  cur_byte == src [src_scan + 1]
        &&  cur_byte == src [src_scan + 2]
        && (src_scan < src_size - 2))
          {
            src [src_size] = !cur_byte; /*  Stick in a sentinel byte         */
            run_end = src_scan;         /*  src_scan <= src_size             */
            while (src [run_end] == cur_byte)
                run_end++;

            if (header)                 /*  If we have a previous unpacked   */
              {                         /*    string, close it               */
                *header = (byte) length + 7;
                header  = NULL;
              }
            length = run_end - src_scan + 1;
            src_scan = run_end;

            if (length < 256)           /*  Short run 4-255 bytes            */
              {
                dst [dst_size++] = 0x81;
                dst [dst_size++] = 0xFE;
                dst [dst_size++] = (byte) length;
                dst [dst_size++] = cur_byte;
              }
            else                        /*  Long run 256-2^16 bytes          */
              {
                dst [dst_size++] = 0x81;
                dst [dst_size++] = 0xFF;
                dst [dst_size++] = (byte) (length & 0xff);
                dst [dst_size++] = (byte) (length >> 8);
                dst [dst_size++] = cur_byte;
              }
          }
        else

        /*- Lastly, compress unpackable strings into chunks of 120 bytes ----*/

          {
            if (!header)                /*  Start new unpacked string if     */
              {                         /*    necessary                      */
                header = &dst [dst_size++];
                length = 0;
              }
            dst [dst_size++] = cur_byte;
            if (++length == 120)        /*  Each string can be up to 120     */
              {                         /*    bytes long (high bit cleared)  */
                *header = (byte) length + 7;
                header  = NULL;
              }
          }
      }
    if (header)                         /*  If we have a previous unpacked   */
      {                                 /*    string, close it               */
        *header = (byte) length + 7;
        header  = NULL;
      }
    return (dst_size);                  /*  Return compressed data size      */
}


/*  ---------------------------------------------------------------------[<]-
    Function: expand_bits

    Synopsis: Expands a block of data previously compressed using the
    compress_bits() function. The compressed block is passed in src; the
    expanded result in dst.  Dst must be large enough to accomodate the
    largest possible decompressed block.  Returns the size of the expanded
    data.
    ---------------------------------------------------------------------[>]-*/

word
expand_bits (
    const byte *src,
    byte *dst,
    word src_size)
{
    word
        dst_size,                       /*  Size of expanded data            */
        src_scan,                       /*  Scan through source data         */
        length;                         /*  Size of the run or string        */
    byte
        cur_byte;                       /*  Next byte to process             */

    src_scan = 0;
    dst_size = 0;
    while (src_scan < src_size)
      {
        cur_byte = src [src_scan++];

        if (cur_byte < 8)               /*  Single bit in position 0 to 7    */
            dst [dst_size++] = 1 << cur_byte;
        else
        if (cur_byte < 128)             /*  String of 1 to 120 bytes         */
          {
            length = (word) cur_byte - 7;
            memcpy (dst + dst_size, src + src_scan, length);
            src_scan += length;
            dst_size += length;
          }
        else                            /*  Run of 1 or more bytes           */
          {
            switch (cur_byte)
              {
                case 0x80:              /*  381-2^16 binary zeroes           */
                    length   = src [src_scan++];
                    length  += src [src_scan++] << 8;
                    cur_byte = 0;
                    break;
                case 0x81:
                    length = src [src_scan++];
                    if (length == 0xFE) /*  4-255 non-zero bytes             */
                      {
                        length   = src [src_scan++];
                        cur_byte = src [src_scan++];
                      }
                    else
                    if (length == 0xFF) /*  Run of 256-2^15 non-zero bytes   */
                      {
                        length   = src [src_scan++];
                        length  += src [src_scan++] << 8;
                        cur_byte = src [src_scan++];
                      }
                    else
                      {
                        length  += 127;
                        cur_byte = 0;   /*  127 to 380 zeroes                */
                      }
                    break;
                default:                /*  1 to 126 zeroes                  */
                    length   = (cur_byte - 1) & 127;
                    cur_byte = 0;
              }
            memset (dst + dst_size, cur_byte, length);
            dst_size += length;
          }
      }
    return (dst_size);                  /*  Return expanded data size        */
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -