(???) / Very simple Deflater for educational purposes
(???) /
(???) / Limits:
(???) /
(???) / - ASCII characters only.
(???) / - Maximum back reference is 4 characters, maximum length is 10 characters.
(???) / - Buggy due to misunderstanding^Wlaziness of LSB/MSB on my part.
(???) /
(???) / Still, a string like 'BANANABANANABANANABANANABANANA' compresses 20%
(PNG) ublic class Deflater(Stream stream)
(???)
(???) private const int MinLength = 3;
(???) private const int MaxLength = 4;
(???) private const int MaxBackReference = 4;
(???) public void Write(byte[] input)
(???) {
(???) var writer = new BitWriter(stream);
(???) // begin of block 0b011 (LSB first)
(???) writer.WriteBits(0b110, 3);
(???) var position = 0;
(???) while (position < input.Length)
(???) {
(???) // find a match
(???) var (bestIndex, bestLength) = FindMatch(input, position);
(???) if (bestLength >= MinLength)
(???) {
(???) // (length, distance)
(???) var (length, distance) = (bestLength - MinLength + 1, position - bestIndex - 1);
(???) // distance
(???) writer.WriteBits((uint)length, 7);
(???) writer.WriteBits((uint)distance, 5);
(???) position += bestLength;
(???) }
(???) else
(???) {
(???) // literal
(???) var literal = input[position] | 0b00110000; // Fixed Huffman
(???) writer.WriteBits((uint)literal, 8);
(???) position++;
(???) }
(???) }
(???) // end of block
(???) writer.WriteBits(0b0000000, 7);
(???) writer.Flush();
(???) }
(???) private static (int BestIndex, int BestLength) FindMatch(byte[] input, int position)
(???) {
(???) var bestIndex = -1;
(???) var bestLength = 0;
(???) for (var i = Math.Max(0, position - MaxBackReference); i < position; i++)
(???) {
(???) var len = 0;
(???) while (position + len < input.Length &&
(???) input[i + len] == input[position + len] &&
(???) len < MaxLength)
(???) {
(???) len++;
(???) }
(???) if (len <= bestLength)
(???) {
(???) continue;
(???) }
(???) bestLength = len;
(???) bestIndex = i;
(???) }
(???) return (bestIndex, bestLength);
(???) }
(???)