/// <summary> /// Gets the most specific <see cref="GifExtension"/>-derivate from the byte representation starting from the current position in the <see cref="Stream"/>. /// </summary> /// <param name="stream">The <see cref="Stream"/> containing the byte representation of a <see cref="GifExtension"/>.</param> /// <returns>A most specific <see cref="GifExtension"/>-derivate corresponding to the byte representation.</returns> internal static GifExtension FromStream(Stream stream) { if (stream.ReadByte() != header) { throw new FormatException("Stream has to have an Extension coming up!"); } var functionCode = (byte)stream.ReadByte(); var data = GifDataStream.Decode(stream); var extension = getSpecificExtension.ContainsKey(functionCode) ? getSpecificExtension[functionCode](data) : new GenericGifExtension(data); extension.FunctionCode = functionCode; return(extension); }
/// <summary> /// Gets the decompressed Color Data starting from the current position in the <see cref="Stream"/>. /// </summary> /// <param name="stream">The <see cref="Stream"/> containing the compressed Color Data.</param> /// <returns>The decompressed Color Data.</returns> public static byte[] Decode(Stream stream) { var startCodeSize = (byte)stream.ReadByte(); if (startCodeSize < minStartCodeSize || startCodeSize > maxStartCodeSize) { throw new ArgumentOutOfRangeException("startCodeSize", "The encoded start code size has to be between 2 and 8!"); } var indexStream = new List <byte>(); var codeData = GifDataStream.Decode(stream); using (var codeStream = new BitStream.BitStream(new MemoryStream(codeData))) { var codeTable = new List <CodeTableEntry>(); buildCodeTable(codeTable, startCodeSize); var codeSize = startCodeSize + 1u; var indexBuffer = new List <byte>(); CodeTableEntry codeEntry; ushort prevCode = getColorCodeCount(startCodeSize); var first = true; do { var codeBytes = new byte[2]; codeStream.ReadBits(codeBytes, 0, codeSize); var code = BitConverter.ToUInt16(codeBytes, 0); if (code < codeTable.Count) { codeEntry = codeTable[code]; if (codeEntry == CodeTableEntry.Clear) { indexBuffer.Clear(); buildCodeTable(codeTable, startCodeSize); first = true; } else if (codeEntry != CodeTableEntry.EndOfInformation) { indexStream.AddRange(codeTable[code].Colors); if (!first) { indexBuffer.Clear(); indexBuffer.AddRange(codeTable[prevCode].Colors); indexBuffer.Add(codeTable[code].Colors[0]); codeTable.Add(CodeTableEntry.MakeColorEntry(indexBuffer.ToArray())); } first = false; } } else if (code == codeTable.Count) { indexBuffer.Clear(); indexBuffer.AddRange(codeTable[prevCode].Colors); indexBuffer.Add(codeTable[prevCode].Colors[0]); codeEntry = CodeTableEntry.MakeColorEntry(indexBuffer.ToArray()); codeTable.Add(codeEntry); indexStream.AddRange(codeTable[code].Colors); } else { throw new ArgumentOutOfRangeException("code", "Encoded code was too large. Expected: " + codeTable.Count + " or less; got: " + code); } if (Math.Pow(2, codeSize) <= codeTable.Count) { ++codeSize; } prevCode = code; }while (codeEntry != CodeTableEntry.EndOfInformation); } return(indexStream.ToArray()); }