Пример #1
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 writen 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);
        }
Пример #2
0
        public void Encode(Stream internalStream)
        {
            #region Validation

            if (internalStream == null)
                throw new ArgumentNullException("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 add.
            bitEncoder.Add(clearFlag);

            int suffix = Nullcode;

            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 the output 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 writen 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

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