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