Пример #1
0
            /*

            *-------------------------------------------------------------------------------

            * 4.1 LZSS_CompressData

            *-------------------------------------------------------------------------------

            *

            * LZSS compress data

            *

            * This routine compress data from an in buffer using the LZSS algorithm. LZSS is

            * a dictionary compression method where the dictionary is a sliding window. The

            * routine uses a look-ahead buffer and finds matches in previously read bytes

            * stored in a sliding window.

            * If a match is found an index/length pair is written to the output buffer

            * (index is the position in the sliding window). If no match is found the read

            * byte is just bypassed to the out buffer. To indicate if the data is an

            * index/length pair or a plain text byte a single bit is used as indicator flag

            * and is written to the out buffer.

            * To speed up the compression a binary tree is used for storing previously

            * compressed data.

            *

            * param inBuf Input data buffer with byte access

            * param outBuf output data buffer with bit access

            *

            * return void

            *

            */

            public static byte[] LZSS_CompressData(byte[] inBuf)

            {

                

                /** Index var. for loop */

                int i = 0;

                /** Byte read from input stream */

                int inByte = 0;

                /** Number of bytes in the look head buffer */

                int aheadBytes = 0;

                /** Current position in the window */

                int winPos = 1;

                /** Number of bytes to replace in the window */

                int replCnt = 0;

                /** Length of the data match found in the window */

                int matchLen = 0;

                /** Position in the window of the data match */

                int matchPos = 0;

                /** Indicator of End Of Stream reached */

                bool eosReached = false;


                BitQuery Result = new BitQuery();
                BitQuery BQ = new BitQuery(inBuf);

                /* Start with filling up the look-ahead buffer */

                while ((aheadBytes < LZSS_LOOK_AHEAD_SIZE) && (!eosReached))

                {

                    /* Get next input byte */

                    inByte = BQ.GetByte();



                    /* If input stream is finished, exit */

                    if (inByte == LZSS_END_OF_INPUT_STREAM)

                    {

                        eosReached = true;

                    }

                    else

                    {

                        /* Add byte to wondow */

                        LZSS_window[winPos + aheadBytes] = inByte;

                        /* Increase look-ahead bytes*/

                        aheadBytes = (aheadBytes + 1) & 0xFF;

                    }

                }
                /* Initialize the tree */

                LZSS_InitTree(winPos);

                /* While there still are bytes in the look ahead buffer, loop */

                while (aheadBytes > 0)

                {

                    /* If previously match length greater than look ahead bytes it's

                    * not possible to code correctly */

                    if (matchLen > aheadBytes)

                    {

                        /* Set matched length to look-ahead buffer length */

                        matchLen = aheadBytes;

                    }

                    /* If the match is smaller than the compressed data (position/length-

                    * pair) there will be negative compression so just output the byte */

                    if (matchLen <= LZSS_BREAK_EVEN)

                    {

                        /* Set consumed bytes in input stream to 1 */

                        replCnt = 1;

                        /* Indicate that next byte in output stream is uncompressed

                        * by output a '1' */

                        Result.PutBit(1);

                        /* Output uncompressed byte */

                        Result.PutBits(LZSS_window[winPos], 8);

                    }

                    /* The match is larger than a position/length pair, compression can be

                    * done */

                    else

                    {

                        /* Indicate that the following bits are compressed data by output a

                        * '0' */

                        Result.PutBit(0);

                        /* Output position in the window */

                       Result.PutBits(matchPos, LZSS_INDEX_BIT_COUNT);

                        /* Output the length of the match, (length is the number of bytes

                        * that is greater than LZSS_BREAK_EVEN) */

                        Result.PutBits((matchLen - (LZSS_BREAK_EVEN + 1)),

                            LZSS_LENGTH_BIT_COUNT);

                        /* Set consumed bytes in input stream to the length of the match */

                        replCnt = matchLen;

                    }
                    /* Delete consumed bytes and add new bytes in the window */

                    for (i = 0; i < replCnt; i++)

                    {

                        /* Remove consumed byte from the window */

                        LZSS_DeleteNode(LZSS_MOD_WINDOW(winPos +

                            (UInt16)LZSS_LOOK_AHEAD_SIZE));

                        /* Get next input byte */

                        inByte = BQ.GetByte();

                        /* If input stream is finished */

                        if (inByte == LZSS_END_OF_INPUT_STREAM)

                        {

                            /* Decrease the look-ahead bytes */

                            aheadBytes = (aheadBytes - 1) & 0xFF;

                        }

                        else

                        {

                            /* Add the new byte from the input stream to the window */

                            LZSS_window[LZSS_MOD_WINDOW(winPos + LZSS_LOOK_AHEAD_SIZE)] = inByte;

                        }

                        /* Increase the position in the window */

                        winPos = LZSS_MOD_WINDOW(winPos + 1);

                        /* If there still are bytes in the look-ahead buffer */

                        if (aheadBytes != 0)

                        {

                            /* Add byte position to the tree and get the length of the

                            * match */

                            matchLen = LZSS_AddNode(winPos, ref matchPos);

                        }

                    }

                }

                /* Input stream finished, write end of stream to the output buffer

                * uncompressed */

                //OutputBit(outBuf, (Uint8_T)0);
                Result.PutBit(0);

                //OutputBits(outBuf, (Uint32_T)LZSS_END_OF_STREAM, LZSS_INDEX_BIT_COUNT);
                Result.PutBits(LZSS_END_OF_STREAM, LZSS_INDEX_BIT_COUNT);

                return Result.Export();

            }
Пример #2
0
            public static byte[] LZSS_ExpandData(byte[] mInput)
            {

                /** Current window position */

                int winPos = 1;

                /** Byte to write to output buffer */

                byte outByte = 0;

                /** Length of the data match found */

                int matchLen = 0;

                /** Position in the window of the data match */

                int matchPos = 0;

                /** Indicator of End Of Stream reached */

                bool eosReached = false;



                //Private Virable

                BitQuery BQ = new BitQuery(mInput);

                List<byte> Result = new List<byte>();

                byte[] LZSS_window = new byte[LZSS_WINDOW_SIZE];

                try
                {
                    while (!eosReached)

                    {

                        /* If next bit is 1, next byte is uncompressed*/

                        if (BQ.GetBit() == 1)

                        {

                            /* Get uncompressed byte */

                            outByte = Convert.ToByte(BQ.GetByte());

                            /* Output byte*/

                            Result.Add(outByte);

                            /* Add byte in window */

                            LZSS_window[winPos] = outByte;

                            /* Increase window position */

                            winPos = (winPos + 1) & (LZSS_WINDOW_SIZE - 1);

                        }

                        /* If next bit is 0, compressed data follows */

                        else

                        {

                            /* Get compressed data as window position of match*/

                            matchPos = BQ.GetBit(LZSS_INDEX_BIT_COUNT);

                            /* If end of stream, exit */

                            if (matchPos == LZSS_END_OF_STREAM)

                            {

                                eosReached = true;

                            }

                            else

                            {

                                /* Get length of string match */

                                matchLen = BQ.GetBit(LZSS_LENGTH_BIT_COUNT);

                                /* Add break even + 1 to get the correct length. Length zero and

                                * the break even value are subtracted from the length during

                                * compression to save space. */

                                matchLen = matchLen + (LZSS_BREAK_EVEN + 1);

                                /* For every byte in match */

                                for (int i = 0; i < matchLen; i++)

                                {

                                    /* Get matching byte from window */

                                    outByte = LZSS_window[(matchPos + i) & (LZSS_WINDOW_SIZE - 1)];

                                    /* Output byte */

                                    Result.Add(outByte);

                                    /* Add matched byte to current window position */

                                    LZSS_window[winPos] = outByte;

                                    /* Increase window position */

                                    winPos = (winPos + 1) & (LZSS_WINDOW_SIZE - 1);

                                }

                            }

                        }

                    }
                }
                catch
                {
                    return null;
                }


                return Result.ToArray<byte>();

            }