/// <summary> /// Decodes the data in the stream with the LZW decoder /// </summary> /// <param name="compressedInput">Stream of compressed data</param> /// <param name="output">Stream of decompressed data</param> public static void Decode(Stream compressedInput, Stream output) { NBitStream input = new NBitStream(compressedInput); //int bitsInChunk = MIN_CHUNK_SIZE; // Min size byte firstByte = 0; long nextCommand = 0; input.BitsInChunk = MIN_CHUNK_SIZE; var dic = new LzwDictionary(DICTIONARY_SIZE); while ((nextCommand = input.Read()) != EOD) { if (nextCommand < 0) { break; } // Do our reset if (nextCommand == CLEAR_TABLE) { input.BitsInChunk = MIN_CHUNK_SIZE; dic = new LzwDictionary(DICTIONARY_SIZE); } else { byte[] data = dic.GetData(nextCommand); if (data == null) { dic.Visit(firstByte); data = dic.GetData(nextCommand); dic.Clearbuffer(); // clear buffer } if (data != null) { dic.Visit(data); if (dic.GetNextCode() >= 2047) { input.BitsInChunk = 12; } else if (dic.GetNextCode() >= 1023) { input.BitsInChunk = 11; } else if (dic.GetNextCode() >= 511) { input.BitsInChunk = 10; } else { input.BitsInChunk = 9; } firstByte = data[0]; output.Write(data, 0, data.Length); } else { //throw new Exception("Error: data is null"); } } output.Flush(); } }
/// <summary> /// Decodes the data in the stream with the LZW decoder /// </summary> /// <param name="compressedInput">Stream of compressed data</param> /// <param name="output">Stream of decompressed data</param> public static void Decode(Stream compressedInput, Stream output) { NBitStream input = new NBitStream(compressedInput); //byte firstByte = 0; long nextCommand = 0; long lastCommand = -1; // CLEAR_TABLE; int earlyChange = 1; LzwTable table = new LzwTable(TABLE_SIZE); // The input needs the bits in chunk set properly to read the data input.BitsInChunk = MIN_CHUNK_SIZE; while ((nextCommand = input.Read()) != EOD) { if (nextCommand < 0) { break; // EOF? } // Do our reset if (nextCommand == CLEAR_TABLE) { input.BitsInChunk = MIN_CHUNK_SIZE; table = new LzwTable(TABLE_SIZE); lastCommand = -1; } else { //if (table[lastCommand] == null) //{ // throw new Exception(String.Format("Corrupted LZW: code {0} (table size: {1})", lastCommand, table.Length)); //} // Check if the command is already in the table // We could use a dictionary here, but I don't think we need the extra overhead of a hash if (nextCommand < table.Count) { table[(int)nextCommand].writeTo(output); if (lastCommand != -1) { table.Add(table[(int)lastCommand].concatenate(table[(int)nextCommand].firstChar)); } } else { LZWString outString = table[(int)lastCommand].concatenate(table[(int)lastCommand].firstChar); outString.writeTo(output); table.Add(outString); } // The input needs the bits in chunk set properly to read the data if (table.GetNextCode() >= 4096 - earlyChange) { input.BitsInChunk = 13; } else if (table.GetNextCode() >= 2048 - earlyChange) { input.BitsInChunk = 12; } else if (table.GetNextCode() >= 1024 - earlyChange) { input.BitsInChunk = 11; } else if (table.GetNextCode() >= 512 - earlyChange) { input.BitsInChunk = 10; } else { input.BitsInChunk = 9; } lastCommand = nextCommand; } } // while end output.Flush(); }