📄 sflcomp.c
字号:
}
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 + -