using System; using System.IO; namespace Lumpio.Gif { public class BitPacker { private Stream stream; private byte[] buffer; private int pos; private ushort need; private ulong bytesWritten; public ulong BytesWritten { get { return bytesWritten; } } private int addCodeToBuffer(ulong code, short n) { ulong mask; if (n < 0) { if (need < 8) { pos++; buffer[pos] = 0x00; } need = 8; return pos; } while (n >= need) { mask = (ulong)(1 << need) - 1; buffer[pos] |= (byte)((mask & code) << (8 - need)); pos++; buffer[pos] = 0x00; code = code >> need; n -= (short)need; need = 8; } if (n > 0) { mask = (ulong)(1 << n) - 1; buffer[pos] |= (byte)((mask & code) << (8 - need)); need -= (ushort)n; } return pos; } public BitPacker(Stream stream) { this.stream = stream; need = 8; buffer = new byte[260]; bytesWritten = 0; pos = 0; buffer[0] = 0x00; } public int Submit(ulong code, ushort n) { addCodeToBuffer(code, (short)n); if (pos >= 255) { stream.WriteByte(255); stream.Write(buffer, 0, 255); buffer[0] = buffer[255]; buffer[1] = buffer[256]; buffer[2] = buffer[257]; buffer[3] = buffer[258]; pos -= 255; bytesWritten += 256; } return pos; } public void WriteFlush() { addCodeToBuffer(0, -1); if (pos <= 0) { return; } stream.WriteByte((byte)pos); stream.Write(buffer, 0, pos); bytesWritten += (ulong)pos + 1; pos = 0; buffer[0] = 0x00; need = 8; } } }