示例#1
0
        // =============================================================
        //  Code
        // =============================================================

        public byte[] Compress(byte[] input)
        {
            Output  = new BitEncoder();
            Matcher = new HashChain8(input, 26, 32);
            for (int i = 0; i < SymbolProbabilities.Length; i++)
            {
                SymbolProbabilities[i].Init();
            }
            for (int i = 0; i < DistanceScaleProbabilities.Length; i++)
            {
                DistanceScaleProbabilities[i].Init();
            }

            int inputSize   = input.Length;
            int inputOffset = 1;

            EncodeSymbol(input[0], 0); // Emit the first byte as a literal with no context.

            while (inputOffset <= inputSize)
            {
                var  match          = FindBestMatch(inputOffset);
                bool matchAvailable = match.Benefit > 0;

                if (matchAvailable)
                {
                    var nextMatch = PeekNextMatch(inputOffset + 1);
                    if (nextMatch.Benefit > match.Benefit)
                    {
                        matchAvailable = false;
                    }
                }

                if (matchAvailable)
                {
                    if (matchAvailable)
                    {
                        if (match.Length > 255)
                        {
                            match.Length = 255;
                        }
                        EncodeSymbol(256 + match.Length, input[inputOffset - 1]);
                        EncodeDistance(match.Distance);
                        inputOffset += match.Length;
                    }
                }
                else
                {
                    EncodeSymbol(input[inputOffset], input[inputOffset - 1]);
                    inputOffset++;
                }
                if (inputOffset == inputSize)
                {
                    break;
                }
            }
            return(Output.GetBytes());
        }
示例#2
0
 private static StringBuilder DoCompress(string input, DataEncoding encoding)
 {
     if (input == "")
     {
         return(null);
     }
     else
     {
         var result = new StringBuilder();
         if (null == input)
         {
             return(result);
         }
         else
         {
             var encoder    = new BitEncoder(result, encoding);
             var compressor = new Compressor(encoder);
             compressor.Compress(input);
             compressor.MarkEndOfStream();
             return(result);
         }
     }
 }
示例#3
0
    public void Encode(Stream internalStream)
    {
        #region Validation

        if (internalStream == null)
        {
            throw new ArgumentNullException(nameof(internalStream), "You need to provide a stream.");
        }

        #endregion

        //If it's the first step.
        var isFirst = true;

        var clearFlag     = (1 << ColorDepth);
        var endOfFileFlag = clearFlag + 1;

        var codeTable = new Dictionary <string, int>();

        //Number of indexes of the currently processed bytes.
        var releaseCount = 0;

        var codeSize      = (byte)(ColorDepth + 1);
        var availableCode = endOfFileFlag + 1;
        var maskCode      = (1 << codeSize) - 1;

        var bitEncoder = new BitEncoder(codeSize);

        //Initial code size.
        internalStream.WriteByte((byte)ColorDepth);

        //First thing being added.
        bitEncoder.Add(clearFlag);

        int suffix = 0;

        while (releaseCount < IndexedPixels.Length)
        {
            #region If it's the first byte

            if (isFirst)
            {
                //The first time, the suffix is set to the first index bytes.
                suffix = IndexedPixels[releaseCount++];

                //If it's the last one.
                if (releaseCount == IndexedPixels.Length)
                {
                    bitEncoder.Add(suffix);
                    bitEncoder.Add(endOfFileFlag);
                    bitEncoder.End();

                    internalStream.WriteByte((byte)(bitEncoder.Length));
                    internalStream.Write(bitEncoder.OutList.ToArray(), 0, bitEncoder.Length);

                    bitEncoder.OutList.Clear();

                    break;
                }

                isFirst = false;
                continue;
            }

            #endregion

            #region Before and after the change, and the constituent entities

            var prefix = suffix;
            suffix = IndexedPixels[releaseCount++];
            string entry = $"{prefix},{suffix}";

            #endregion

            #region If you do not know the current entity, entities encoded, and output the prefix

            if (!codeTable.ContainsKey(entry))
            {
                //If the current entity is not encoded, then output the prefix
                bitEncoder.Add(prefix);

                //And the current entity is encoded. Inserts and after that adds the availableCode count.
                codeTable.Add(entry, availableCode++);

                if (availableCode > (MaxStackSize - 3))
                {
                    //Insert the clear tag, reinvent
                    codeTable.Clear();
                    ColorDepth    = InitDataSize;
                    codeSize      = (byte)(ColorDepth + 1);
                    availableCode = endOfFileFlag + 1;
                    maskCode      = (1 << codeSize) - 1;

                    bitEncoder.Add(clearFlag);
                    bitEncoder.InBit = codeSize;
                }
                else if (availableCode > (1 << codeSize))
                {
                    //If the current code is greater than the current code available to represent values
                    ColorDepth++;
                    codeSize         = (byte)(ColorDepth + 1);
                    bitEncoder.InBit = codeSize;
                    maskCode         = (1 << codeSize) - 1;
                }

                //Divides into more blocks.
                if (bitEncoder.Length >= 255)
                {
                    //Size of the block.
                    internalStream.WriteByte(255);
                    //Writes the 255 sized block.
                    internalStream.Write(bitEncoder.OutList.ToArray(), 0, 255);

                    if (bitEncoder.Length > 255)
                    {
                        var leftBuffer = new byte[bitEncoder.Length - 255];

                        //Removes the last written 255 bytes.
                        bitEncoder.OutList.CopyTo(255, leftBuffer, 0, leftBuffer.Length);
                        bitEncoder.OutList.Clear();
                        bitEncoder.OutList.AddRange(leftBuffer);
                    }
                    else
                    {
                        bitEncoder.OutList.Clear();
                    }
                }
            }

            #endregion

            #region If you know the current entity, set the suffixes to the current index value of an entity

            else
            {
                //Set the suffix to the current entity encoding
                suffix = codeTable[entry];
            }

            #endregion

            //if (releaseCount == 40240)
            //    suffix = suffix;

            #region To the end of an image, writes over identity, and outputs the current codes left in the data stream

            if (releaseCount == IndexedPixels.Length)
            {
                bitEncoder.Add(suffix);        //Adds the last sufix.
                bitEncoder.Add(endOfFileFlag); //End of the LZW
                bitEncoder.End();

                //If the block size if greater than 255, divides into two.
                if (bitEncoder.Length > 255)
                {
                    var leftBuffer = new byte[bitEncoder.Length - 255];

                    bitEncoder.OutList.CopyTo(255, leftBuffer, 0, leftBuffer.Length);
                    bitEncoder.OutList.Clear();
                    bitEncoder.OutList.AddRange(leftBuffer);

                    internalStream.WriteByte((byte)leftBuffer.Length);
                    internalStream.Write(leftBuffer, 0, leftBuffer.Length);
                }
                else
                {
                    internalStream.WriteByte((byte)(bitEncoder.Length));
                    internalStream.Write(bitEncoder.OutList.ToArray(), 0, bitEncoder.Length);

                    bitEncoder.OutList.Clear();
                }

                break;
            }

            #endregion
        }

        //For 3 weeks I forgot to add this little piece of sh*t, my gifs were always corrupted...
        //Signals the end of the list of blocks.
        internalStream.WriteByte(0);
    }
示例#4
0
 public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
     Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
 {
     UInt32 m = 1;
     for (int i = 0; i < NumBitLevels; i++)
     {
         UInt32 bit = symbol & 1;
         Models[startIndex + m].Encode(rangeEncoder, bit);
         m = (m << 1) | bit;
         symbol >>= 1;
     }
 }
示例#5
0
 public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
     int NumBitLevels, UInt32 symbol)
 {
     UInt32 price = 0;
     UInt32 m = 1;
     for (int i = NumBitLevels; i > 0; i--)
     {
         UInt32 bit = symbol & 1;
         symbol >>= 1;
         price += Models[startIndex + m].GetPrice(bit);
         m = (m << 1) | bit;
     }
     return price;
 }
示例#6
0
 public static void ReverseEncode(BitEncoder[] models, uint startIndex,
                                  Encoder rangeEncoder, int numBitLevels, uint symbol)
 {
     uint m = 1;
     for (var i = 0; i < numBitLevels; i++)
     {
         var bit = symbol & 1;
         models[startIndex + m].Encode(rangeEncoder, bit);
         m = (m << 1) | bit;
         symbol >>= 1;
     }
 }
示例#7
0
 public static uint ReverseGetPrice(BitEncoder[] models, uint startIndex,
                                    int numBitLevels, uint symbol)
 {
     uint price = 0;
     uint m = 1;
     for (var i = numBitLevels; i > 0; i--)
     {
         var bit = symbol & 1;
         symbol >>= 1;
         price += models[startIndex + m].GetPrice(bit);
         m = (m << 1) | bit;
     }
     return price;
 }
示例#8
0
        /// <summary>
        /// Encodes the compressed indexed pixel data to the given stream.
        /// </summary>
        /// <param name="stream">The stream to add the data to.</param>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
        public void Encode(Stream stream)
        {
            Guard.NotNull(stream, nameof(stream));

            // Whether it is a first step.
            bool first = true;

            // The initial suffix.
            int suffix = 0;

            // Indicator to reinitialize the code table.
            int clearCode = 1 << this.colorDepth;

            // End of information code
            int endOfInformation = clearCode + 1;

            // The code table for storing encoded colors.
            Dictionary<string, int> codeTable = new Dictionary<string, int>();

            // The current number of index bytes processed.
            int releaseCount = 0;

            // Calculate the code available.
            byte codeSize = (byte)(this.colorDepth + 1);
            int availableCode = endOfInformation + 1;

            // Initialise.
            BitEncoder bitEncoder = new BitEncoder(codeSize);
            stream.WriteByte(this.colorDepth);
            bitEncoder.Add(clearCode);

            while (releaseCount < this.indexedPixels.Length)
            {
                if (first)
                {
                    // If this is the first byte the suffix is set to the first byte index.
                    suffix = this.indexedPixels[releaseCount++];

                    if (releaseCount == this.indexedPixels.Length)
                    {
                        bitEncoder.Add(suffix);
                        bitEncoder.Add(endOfInformation);
                        bitEncoder.End();
                        stream.WriteByte((byte)bitEncoder.Length);
                        stream.Write(bitEncoder.ToArray(), 0, bitEncoder.Length);
                        bitEncoder.Clear();
                        break;
                    }

                    first = false;
                    continue;
                }

                // Switch
                int prefix = suffix;

                // Read the bytes at the index.
                suffix = this.indexedPixels[releaseCount++];

                // Acts as a key for code table entries.
                string key = $"{prefix},{suffix}";

                // Is index buffer + the index in our code table?
                if (!codeTable.ContainsKey(key))
                {
                    // If the current entity is not coded add the prefix.
                    bitEncoder.Add(prefix);

                    // Add the current bytes
                    codeTable.Add(key, availableCode++);

                    if (availableCode > (MaxStackSize - 3))
                    {
                        // Clear out and reset the wheel.
                        codeTable.Clear();
                        this.colorDepth = this.initDataSize;
                        codeSize = (byte)(this.colorDepth + 1);
                        availableCode = endOfInformation + 1;

                        bitEncoder.Add(clearCode);
                        bitEncoder.IntitialBit = codeSize;
                    }
                    else if (availableCode > (1 << codeSize))
                    {
                        // If the currently available coding is greater than the current value.
                        // the coded bits can represent.
                        this.colorDepth++;
                        codeSize = (byte)(this.colorDepth + 1);
                        bitEncoder.IntitialBit = codeSize;
                    }

                    if (bitEncoder.Length >= 255)
                    {
                        stream.WriteByte(255);
                        stream.Write(bitEncoder.ToArray(), 0, 255);
                        if (bitEncoder.Length > 255)
                        {
                            byte[] leftBuffer = new byte[bitEncoder.Length - 255];
                            bitEncoder.CopyTo(255, leftBuffer, 0, leftBuffer.Length);
                            bitEncoder.Clear();
                            bitEncoder.AddRange(leftBuffer);
                        }
                        else
                        {
                            bitEncoder.Clear();
                        }
                    }
                }
                else
                {
                    // Set the suffix to the current byte.
                    suffix = codeTable[key];
                }

                // Output code for contents of index buffer.
                // Output end-of-information code.
                if (releaseCount == this.indexedPixels.Length)
                {
                    bitEncoder.Add(suffix);
                    bitEncoder.Add(endOfInformation);
                    bitEncoder.End();
                    if (bitEncoder.Length > 255)
                    {
                        byte[] leftBuffer = new byte[bitEncoder.Length - 255];
                        bitEncoder.CopyTo(255, leftBuffer, 0, leftBuffer.Length);
                        bitEncoder.Clear();
                        bitEncoder.AddRange(leftBuffer);
                        stream.WriteByte((byte)leftBuffer.Length);
                        stream.Write(leftBuffer, 0, leftBuffer.Length);
                    }
                    else
                    {
                        stream.WriteByte((byte)bitEncoder.Length);
                        stream.Write(bitEncoder.ToArray(), 0, bitEncoder.Length);
                        bitEncoder.Clear();
                    }

                    break;
                }
            }
        }