private void WriteColorTable(ColorTable table) { int entries = 1 << table.BitSize(); int n; for (n = 0; n < table.Table.Length; ++n) { WriteByte(table.Table[n].R); WriteByte(table.Table[n].G); WriteByte(table.Table[n].B); } for (; n < entries; ++n) { WriteByte(0); WriteByte(0); WriteByte(0); } }
private void WriteImageData(Image image) { // Figure out which color table is in use and deduce the code size ColorTable colorTable = image.LocalColorTable ?? GlobalColorTable; int colorTableBitSize = colorTable.BitSize(); int codeSize = (colorTableBitSize == 1 ? 2 : colorTableBitSize); if (Debug) { Console.Error.WriteLine("Writing code size {0} bits", codeSize); } WriteByte(codeSize); // Initial code length is one more than code size, to accomodate the // Clear and End codes. BitWriter writer = new BitWriter() { Output = Output, CodeLength = 1 + codeSize, Debug = this.Debug, }; // Initialize the prefix table with matches for all single-unit codes PrefixTable prefixes = new PrefixTable(); for (int n = 0; n < (1 << codeSize); ++n) { prefixes.Add(n, -1, (byte)n); } int minCode = (1 << codeSize) + 2; int nextCode = minCode; // Start with a Clear. (Pointless - the decoder knows perfectly well what // the initial state is.) if (Debug) { Console.Error.WriteLine("Bit-writing clear marker {0}", 1 << codeSize); } writer.WriteBits(1 << codeSize); int pos = 0; if (Debug) { Console.Error.WriteLine("Bit-writing {0} pixels of image data", image.ImageData.Length); } while (pos < image.ImageData.Length) { // Find the longest known prefix that matches this point in the image data int bestLength; int bestCode = prefixes.Find(image.ImageData, pos, out bestLength); // Output the best code we found writer.WriteBits(bestCode); // Add a new dictionary entry if (nextCode < 4096 && pos + bestLength < image.ImageData.Length) { if (Debug) { Console.Error.WriteLine("Define code {0:X} as code {1:X} + byte {2:X2}", nextCode, bestCode, image.ImageData[pos + bestLength]); } prefixes.Add(nextCode, bestCode, image.ImageData[pos + bestLength]); // Update the output bit size if (nextCode >= (1 << writer.CodeLength)) { ++writer.CodeLength; } ++nextCode; } pos += bestLength; } // Finish with an End. (Also pointless - the decoder knows what size the image data should be.) if (Debug) { Console.Error.WriteLine("Bit-writing end marker {0}", (1 << codeSize) + 1); } writer.WriteBits((1 << codeSize) + 1); if (Debug) { Console.Error.WriteLine("Flushing bits"); } writer.FlushBits(); if (Debug) { Console.Error.WriteLine("Flushing bytes"); } writer.FlushBytes(); // A zero-sized sub-block terminates. if (Debug) { Console.Error.WriteLine("Writing image terminator"); } WriteByte(0); }