Exemple #1
0
    static public ulong Comp(ulong _maxVal, float _t, CompFunc _func)
    {
        if (_t > 1.0)
        {
            _t = 1.0f;
        }

        if (_t < 0)
        {
            _t = 0;
        }

        double val = (double)_func(_t) * (double)_maxVal;

        return((ulong)val);
    }
    static public int Comp(int _maxVal, float _t, CompFunc _func)
    {
        if (_t > 1.0)
        {
            _t = 1.0f;
        }

        if (_t < 0)
        {
            _t = 0;
        }

        float val = _func(_t) * (float)_maxVal;

        return((int)val);
    }
        /// <summary>
        /// Compress the block buffer when it is full
        /// The block buffer is made of literals and distance length pairs
        /// </summary>
        /// <param name="lastBlock">if set to <c>true</c> [last block].</param>
        private void CompressBlockBuf(bool lastBlock)
        {
            // add end of block to code frequency array
            _literalTree.CodeFreq[EndOfBlockSymbol]++;

            // Build trees
            _literalTree.BuildTree();
            _distanceTree.BuildTree();

            // Calculate bitlen frequency
            int bitLengthExtraBits = _literalTree.CalcBLFreq(_bitLengthTree);
            bitLengthExtraBits += _distanceTree.CalcBLFreq(_bitLengthTree);

            // Build bitlen tree
            _bitLengthTree.BuildTree();

            // calculate length in bits of bit length tree
            int blTreeCodes = _bitLengthTree.MaxUsedCodesBitLength();

            // calculate total block length for dynamic coding
            // The 17 is made of: 3 bits block header, 5 bits literal codes, 5 bits distance codes, 4 bits bit-length codes
            int compressedLen = 17 + blTreeCodes * 3 + _bitLengthTree.GetEncodedLength() + bitLengthExtraBits +
                    _literalTree.GetEncodedLength() + _distanceTree.GetEncodedLength() + _blockBufExtraBits;

            // compressed block length in bytes for dynamic coding
            compressedLen = (compressedLen + 7) / 8;

            // calculate total block length for static coding
            int staticLen = 3 + _blockBufExtraBits;
            for (int i = 0; i < MaxLiteralCodes; i++) staticLen += _literalTree.CodeFreq[i] * StaticLiteralLength[i];
            for (int i = 0; i < MaxDistanceCodes; i++) staticLen += _distanceTree.CodeFreq[i] * StaticDistanceLength[i];

            // static block length in bytes
            staticLen = (staticLen + 7) / 8;

            // static trees look better
            if (staticLen <= compressedLen) compressedLen = staticLen;

            // uncompressed read block length in bytes
            int storedBlockLen = _readPtr - _readBlockStart;

            // This is the last compressed block
            if (lastBlock)
            {
                // If this this is the first block and the last block at the same time (relatively small file)
                // and the uncompressed block is better than compressed block, change compression function from deflate to stored
                if (_writeFirstBlock && storedBlockLen <= compressedLen)
                {
                    CompFunction = CompFunc.Stored;
                    _readAvailableBytes = storedBlockLen;
                    DeflateStored();
                    return;
                }

                // Test compressed overall file length.
                // If overall compressed length is more than the original uncompressed size
                // the derived class will rewind the read and write stream.
                if (WriteTotal + _writePtr + (_bitCount + 7) / 8 + Math.Min(compressedLen, storedBlockLen + 5) > ReadTotal)
                {
                    // rewind both read and write streams
                    RewindStreams();

                    // read first block (the derived class will supply this routine)
                    _readAvailableBytes = ReadBytes(_readBuffer, 0, ReadBufSize, out _readEndOfFile);

                    // reset uncompressed and compressed totals
                    ReadTotal = (uint)_readAvailableBytes;
                    WriteTotal = 0;

                    // reset write ptr
                    _writePtr = 0;
                    _bitCount = 0;

                    // change compress function from deflate to stored
                    CompFunction = CompFunc.Stored;

                    // move input stream to output stream
                    DeflateStored();
                    return;
                }
            }

            // Uncompressed block length is better than compressed length.
            // Uncompressed block has 5 bytes overhead.
            // Stored block header plus 2 bytes length and 2 bytes length complament.
            if (storedBlockLen + 5 < compressedLen)
            {
                // loop in case block length is larger tan max allowed
                while (storedBlockLen > 0)
                {
                    // block length (max 65535)
                    int len = Math.Min(storedBlockLen, 0xffff);

                    // adjust remaing length
                    storedBlockLen -= len;

                    // Write the block on even byte boundry, Signal if this is the last block of the file
                    WriteStoredBlock(len, lastBlock && storedBlockLen == 0);

                    // adjust block start pointer
                    _readBlockStart += len;
                }
            }

            // Encode with static tree
            else if (compressedLen == staticLen)
            {
                // write static block header to output file
                WriteBits(((int)BlockType.StaticTrees << 1) + (lastBlock ? 1 : 0), 3);

                // replace the dynamic codes with static codes
                _literalTree.SetStaticCodes(StaticLiteralCodes, StaticLiteralLength);
                _distanceTree.SetStaticCodes(StaticDistanceCodes, StaticDistanceLength);

                // Compress the block and send it to the output buffer
                // This process converts the block buffer values into variable length sequence of bits.
                CompressBlock();

                // adjust block pointer
                _readBlockStart += storedBlockLen;
            }

            // Encode with dynamic tree
            else
            {
                // write dynamic block header to output file
                WriteBits(((int)BlockType.DynamicTrees << 1) + (lastBlock ? 1 : 0), 3);

                // write the dynamic tree to the output stream
                SendAllTrees(blTreeCodes);

                // Compress the block and send it to the output buffer
                // This process converts the block buffer values into variable length sequence of bits.
                CompressBlock();

                // adjust block pointer
                _readBlockStart += storedBlockLen;
            }

            // Set block buffer to empty
            BlockReset();

            // Reset write first block
            _writeFirstBlock = false;
        }
        /// <summary>
        /// Compress read stream to write stream
        /// This is the main function of the DefaultMethod class
        /// </summary>
        protected void Compress()
        {
            // define compression control values based on the user compression level 0 to 9
            CompFunction = CompFuncTable[_compLevel];
            _goodLength = GoodLengthTable[_compLevel];
            _maxLazyLength = MaxLazyTable[_compLevel];
            _niceLength = NiceLengthTable[_compLevel];
            _maxChainLength = MaxChainTable[_compLevel];

            // read process initialization
            _readBufferFilePosition = 0;
            _readBlockStart = 0;
            _readPtr = 0;
            _readEndOfFile = false;
            _matchStart = 0;
            _matchLen = MinMatch - 1;

            // read first block (the derived class will supply this routine)
            _readBufEnd = ReadBytes(_readBuffer, 0, ReadBufSize, out _readEndOfFile);

            ReadTotal = (uint)_readBufEnd;

            // available bytes in the buffer
            _readAvailableBytes = _readBufEnd;

            // if file is less than 8 bytes, just store it
            if (_readAvailableBytes < 8) CompFunction = CompFunc.Stored;

            // write process initialization
            WriteTotal = 0;
            _writePtr = 0;
            _bitBuffer = 0;
            _bitCount = 0;
            _writeFirstBlock = true;

            // hash tables initialization
            for (int hashPtr = _hashTable.Length - 1; hashPtr >= 0; hashPtr--) _hashTable[hashPtr] = -1;
            for (int hashPtr = _hashPrevious.Length - 1; hashPtr >= 0; hashPtr--) _hashPrevious[hashPtr] = -1;

            // switch based on the type of compression
            switch (CompFunction)
            {
                case CompFunc.Stored:
                    DeflateStored();
                    break;

                case CompFunc.Fast:
                    DeflateFast();
                    break;

                case CompFunc.Slow:
                    DeflateSlow();
                    break;
            }

            // flush any left over bits in bit buffer
            WriteAlignToByte();
            if (_writePtr != 0)
            {
                WriteBytes(_writeBuffer, 0, _writePtr);
                WriteTotal += (uint)_writePtr;
            }
        }