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

📄 lz.c

📁 Basic Compression Library by Marcus Geelnard Release 1.2.0 2006-07-22 Introduction The Ba
💻 C
📖 第 1 页 / 共 2 页
字号:
        /* Was there a good enough match? */        if( (bestlength >= 8) ||            ((bestlength == 4) && (bestoffset <= 0x0000007f)) ||            ((bestlength == 5) && (bestoffset <= 0x00003fff)) ||            ((bestlength == 6) && (bestoffset <= 0x001fffff)) ||            ((bestlength == 7) && (bestoffset <= 0x0fffffff)) )        {            out[ outpos ++ ] = (unsigned char) marker;            outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] );            outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] );            inpos += bestlength;            bytesleft -= bestlength;        }        else        {            /* Output single byte (or two bytes if marker byte) */            symbol = in[ inpos ++ ];            out[ outpos ++ ] = symbol;            if( symbol == marker )            {                out[ outpos ++ ] = 0;            }            -- bytesleft;        }    }    while( bytesleft > 3 );    /* Dump remaining bytes, if any */    while( inpos < insize )    {        if( in[ inpos ] == marker )        {            out[ outpos ++ ] = marker;            out[ outpos ++ ] = 0;        }        else        {            out[ outpos ++ ] = in[ inpos ];        }        ++ inpos;    }    return outpos;}/************************************************************************** LZ_CompressFast() - Compress a block of data using an LZ77 coder.*  in     - Input (uncompressed) buffer.*  out    - Output (compressed) buffer. This buffer must be 0.4% larger*           than the input buffer, plus one byte.*  insize - Number of input bytes.*  work   - Pointer to a temporary buffer (internal working buffer), which*           must be able to hold (insize+65536) unsigned integers.* The function returns the size of the compressed data.*************************************************************************/int LZ_CompressFast( unsigned char *in, unsigned char *out,    unsigned int insize, unsigned int *work ){    unsigned char marker, symbol;    unsigned int  inpos, outpos, bytesleft, i, index, symbols;    unsigned int  offset, bestoffset;    unsigned int  maxlength, length, bestlength;    unsigned int  histogram[ 256 ], *lastindex, *jumptable;    unsigned char *ptr1, *ptr2;    /* Do we have anything to compress? */    if( insize < 1 )    {        return 0;    }    /* Assign arrays to the working area */    lastindex = work;    jumptable = &work[ 65536 ];    /* Build a "jump table". Here is how the jump table works:       jumptable[i] points to the nearest previous occurrence of the same       symbol pair as in[i]:in[i+1], so in[i] == in[jumptable[i]] and       in[i+1] == in[jumptable[i]+1], and so on... Following the jump table       gives a dramatic boost for the string search'n'match loop compared       to doing a brute force search. The jump table is built in O(n) time,       so it is a cheap operation in terms of time, but it is expensice in       terms of memory consumption. */    for( i = 0; i < 65536; ++ i )    {        lastindex[ i ] = 0xffffffff;    }    for( i = 0; i < insize-1; ++ i )    {        symbols = (((unsigned int)in[i]) << 8) | ((unsigned int)in[i+1]);        index = lastindex[ symbols ];        lastindex[ symbols ] = i;        jumptable[ i ] = index;    }    jumptable[ insize-1 ] = 0xffffffff;    /* Create histogram */    for( i = 0; i < 256; ++ i )    {        histogram[ i ] = 0;    }    for( i = 0; i < insize; ++ i )    {        ++ histogram[ in[ i ] ];    }    /* Find the least common byte, and use it as the marker symbol */    marker = 0;    for( i = 1; i < 256; ++ i )    {        if( histogram[ i ] < histogram[ marker ] )        {            marker = i;        }    }    /* Remember the marker symbol for the decoder */    out[ 0 ] = marker;    /* Start of compression */    inpos = 0;    outpos = 1;    /* Main compression loop */    bytesleft = insize;    do    {        /* Get pointer to current position */        ptr1 = &in[ inpos ];        /* Search history window for maximum length string match */        bestlength = 3;        bestoffset = 0;        index = jumptable[ inpos ];        while( (index != 0xffffffff) && ((inpos - index) < LZ_MAX_OFFSET) )        {            /* Get pointer to candidate string */            ptr2 = &in[ index ];            /* Quickly determine if this is a candidate (for speed) */            if( ptr2[ bestlength ] == ptr1[ bestlength ] )            {                /* Determine maximum length for this offset */                offset = inpos - index;                maxlength = (bytesleft < offset ? bytesleft : offset);                /* Count maximum length match at this offset */                length = _LZ_StringCompare( ptr1, ptr2, 2, maxlength );                /* Better match than any previous match? */                if( length > bestlength )                {                    bestlength = length;                    bestoffset = offset;                }            }            /* Get next possible index from jump table */            index = jumptable[ index ];        }        /* Was there a good enough match? */        if( (bestlength >= 8) ||            ((bestlength == 4) && (bestoffset <= 0x0000007f)) ||            ((bestlength == 5) && (bestoffset <= 0x00003fff)) ||            ((bestlength == 6) && (bestoffset <= 0x001fffff)) ||            ((bestlength == 7) && (bestoffset <= 0x0fffffff)) )        {            out[ outpos ++ ] = (unsigned char) marker;            outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] );            outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] );            inpos += bestlength;            bytesleft -= bestlength;        }        else        {            /* Output single byte (or two bytes if marker byte) */            symbol = in[ inpos ++ ];            out[ outpos ++ ] = symbol;            if( symbol == marker )            {                out[ outpos ++ ] = 0;            }            -- bytesleft;        }    }    while( bytesleft > 3 );    /* Dump remaining bytes, if any */    while( inpos < insize )    {        if( in[ inpos ] == marker )        {            out[ outpos ++ ] = marker;            out[ outpos ++ ] = 0;        }        else        {            out[ outpos ++ ] = in[ inpos ];        }        ++ inpos;    }    return outpos;}/************************************************************************** LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder.*  in      - Input (compressed) buffer.*  out     - Output (uncompressed) buffer. This buffer must be large*            enough to hold the uncompressed data.*  insize  - Number of input bytes.*************************************************************************/void LZ_Uncompress( unsigned char *in, unsigned char *out,    unsigned int insize ){    unsigned char marker, symbol;    unsigned int  i, inpos, outpos, length, offset;    /* Do we have anything to uncompress? */    if( insize < 1 )    {        return;    }    /* Get marker symbol from input stream */    marker = in[ 0 ];    inpos = 1;    /* Main decompression loop */    outpos = 0;    do    {        symbol = in[ inpos ++ ];        if( symbol == marker )        {            /* We had a marker byte */            if( in[ inpos ] == 0 )            {                /* It was a single occurrence of the marker byte */                out[ outpos ++ ] = marker;                ++ inpos;            }            else            {                /* Extract true length and offset */                inpos += _LZ_ReadVarSize( &length, &in[ inpos ] );                inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] );                /* Copy corresponding data from history window */                for( i = 0; i < length; ++ i )                {                    out[ outpos ] = out[ outpos - offset ];                    ++ outpos;                }            }        }        else        {            /* No marker, plain copy */            out[ outpos ++ ] = symbol;        }    }    while( inpos < insize );}

⌨️ 快捷键说明

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