2021-05-07 22:05:11 -04:00

181 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using UniversalEditor.Compression.LZW.Internal;
namespace UniversalEditor.Compression.LZW
{
public class LZWStream
{
private const int MAX_CODES = 4096;
private const int BYTE_SIZE = 8;
private const int EXCESS = 4;
private const int ALPHA = 256;
private const int MASK1 = 255;
private const int MASK2 = 15;
private static int c_leftOver;
private static bool c_bitsLeftOver;
private static int[] s;
private static int size;
private static int d_leftOver;
private static bool d_bitsLeftOver;
private static int d_size = 0;
private static Element[] h;
private static void COutput(int pcode, MemoryStream out_Renamed)
{
if (LZWStream.c_bitsLeftOver)
{
int d = pcode & 255;
int c = (LZWStream.c_leftOver << 4) + (pcode >> 8);
out_Renamed.WriteByte((byte)c);
out_Renamed.WriteByte((byte)d);
LZWStream.c_bitsLeftOver = false;
}
else
{
LZWStream.c_leftOver = (pcode & 15);
int c = pcode >> 4;
out_Renamed.WriteByte((byte)c);
LZWStream.c_bitsLeftOver = true;
}
}
public static byte[] Compress(string input)
{
return LZWStream.Compress(input, Encoding.Default);
}
public static byte[] Compress(string input, Encoding encoding)
{
return LZWStream.Compress(encoding.GetBytes(input));
}
public static byte[] Compress(byte[] input)
{
Hashtable table = new Hashtable();
for (int i = 0; i < 256; i++)
{
table.Add(i, i);
}
int codeUsed = 256;
MemoryStream in_Renamed = new MemoryStream(input);
MemoryStream out_Renamed = new MemoryStream();
int c = in_Renamed.ReadByte();
if (c != -1)
{
int pcode = c;
c = in_Renamed.ReadByte();
while (in_Renamed.Position < in_Renamed.Length)
{
int j = (pcode << 8) + c;
if (!table.ContainsKey(j))
{
LZWStream.COutput(pcode, out_Renamed);
if (codeUsed < 4096)
{
table.Add((pcode << 8) + c, codeUsed++);
}
pcode = c;
}
else
{
int e = (int)table[j];
pcode = e;
}
c = in_Renamed.ReadByte();
}
LZWStream.COutput(pcode, out_Renamed);
if (LZWStream.c_bitsLeftOver)
{
out_Renamed.WriteByte((byte)(LZWStream.c_leftOver << 4));
}
}
in_Renamed.Close();
out_Renamed.Flush();
out_Renamed.Close();
return out_Renamed.ToArray();
}
public static byte[] Decompress(byte[] input)
{
MemoryStream in_Renamed = new MemoryStream(input);
MemoryStream out_Renamed = new MemoryStream();
int codeUsed = 256;
LZWStream.s = new int[4096];
LZWStream.h = new Element[4096];
int pcode = LZWStream.DGetCode(in_Renamed);
if (pcode >= 0)
{
LZWStream.s[0] = pcode;
out_Renamed.WriteByte((byte)LZWStream.s[0]);
LZWStream.size = 0;
while (true)
{
int ccode = LZWStream.DGetCode(in_Renamed);
if (ccode < 0)
{
break;
}
if (ccode < codeUsed)
{
LZWStream.DOutput(ccode, out_Renamed);
if (codeUsed < 4096)
{
LZWStream.h[codeUsed++] = new Element(pcode, LZWStream.s[LZWStream.size]);
}
}
else
{
LZWStream.h[codeUsed++] = new Element(pcode, LZWStream.s[LZWStream.size]);
LZWStream.DOutput(ccode, out_Renamed);
}
pcode = ccode;
}
}
out_Renamed.Flush();
out_Renamed.Close();
in_Renamed.Close();
return out_Renamed.ToArray();
}
private static void DOutput(int code, MemoryStream out_Renamed)
{
LZWStream.d_size = -1;
while (code >= 256)
{
LZWStream.s[++LZWStream.d_size] = LZWStream.h[code].suffix;
code = LZWStream.h[code].prefix;
}
LZWStream.s[++LZWStream.d_size] = code;
for (int i = LZWStream.d_size; i >= 0; i--)
{
out_Renamed.WriteByte((byte)LZWStream.s[i]);
}
}
private static int DGetCode(MemoryStream in_Renamed)
{
int c = in_Renamed.ReadByte();
int result;
if (c == -1)
{
result = -1;
}
else
{
int code;
if (LZWStream.d_bitsLeftOver)
{
code = (LZWStream.d_leftOver << 8) + c;
}
else
{
int d = in_Renamed.ReadByte();
code = (c << 4) + (d >> 4);
LZWStream.d_leftOver = (d & 15);
}
LZWStream.d_bitsLeftOver = !LZWStream.d_bitsLeftOver;
result = code;
}
return result;
}
}
}