예제 #1
0
파일: CJLRVBF.cs 프로젝트: demonzhq/JLR
            /*

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

            * 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();

            }