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; } }