311 lines
6.6 KiB
C#
311 lines
6.6 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace Gif.Components
|
|
{
|
|
// Token: 0x02000008 RID: 8
|
|
public class LZWEncoder
|
|
{
|
|
// Token: 0x0600003F RID: 63 RVA: 0x00003DDC File Offset: 0x000021DC
|
|
public LZWEncoder(int width, int height, byte[] pixels, int color_depth)
|
|
{
|
|
this.imgW = width;
|
|
this.imgH = height;
|
|
this.pixAry = pixels;
|
|
this.initCodeSize = Math.Max(2, color_depth);
|
|
}
|
|
|
|
// Token: 0x06000040 RID: 64 RVA: 0x00003EA0 File Offset: 0x000022A0
|
|
private void Add(byte c, Stream outs)
|
|
{
|
|
this.accum[this.a_count++] = c;
|
|
if (this.a_count >= 254)
|
|
{
|
|
this.Flush(outs);
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000041 RID: 65 RVA: 0x00003EDE File Offset: 0x000022DE
|
|
private void ClearTable(Stream outs)
|
|
{
|
|
this.ResetCodeTable(this.hsize);
|
|
this.free_ent = this.ClearCode + 2;
|
|
this.clear_flg = true;
|
|
this.Output(this.ClearCode, outs);
|
|
}
|
|
|
|
// Token: 0x06000042 RID: 66 RVA: 0x00003F10 File Offset: 0x00002310
|
|
private void ResetCodeTable(int hsize)
|
|
{
|
|
for (int i = 0; i < hsize; i++)
|
|
{
|
|
this.htab[i] = -1;
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000043 RID: 67 RVA: 0x00003F3C File Offset: 0x0000233C
|
|
private void Compress(int init_bits, Stream outs)
|
|
{
|
|
this.g_init_bits = init_bits;
|
|
this.clear_flg = false;
|
|
this.n_bits = this.g_init_bits;
|
|
this.maxcode = this.MaxCode(this.n_bits);
|
|
this.ClearCode = 1 << init_bits - 1;
|
|
this.EOFCode = this.ClearCode + 1;
|
|
this.free_ent = this.ClearCode + 2;
|
|
this.a_count = 0;
|
|
int num = this.NextPixel();
|
|
int num2 = 0;
|
|
for (int i = this.hsize; i < 65536; i *= 2)
|
|
{
|
|
num2++;
|
|
}
|
|
num2 = 8 - num2;
|
|
int num3 = this.hsize;
|
|
this.ResetCodeTable(num3);
|
|
this.Output(this.ClearCode, outs);
|
|
for (;;)
|
|
{
|
|
int num4;
|
|
while ((num4 = this.NextPixel()) != LZWEncoder.EOF)
|
|
{
|
|
int i = (num4 << this.maxbits) + num;
|
|
int num5 = (num4 << num2) ^ num;
|
|
if (this.htab[num5] == i)
|
|
{
|
|
num = this.codetab[num5];
|
|
}
|
|
else
|
|
{
|
|
if (this.htab[num5] >= 0)
|
|
{
|
|
int num6 = num3 - num5;
|
|
if (num5 == 0)
|
|
{
|
|
num6 = 1;
|
|
}
|
|
for (;;)
|
|
{
|
|
if ((num5 -= num6) < 0)
|
|
{
|
|
num5 += num3;
|
|
}
|
|
if (this.htab[num5] == i)
|
|
{
|
|
break;
|
|
}
|
|
if (this.htab[num5] < 0)
|
|
{
|
|
goto IL_144;
|
|
}
|
|
}
|
|
num = this.codetab[num5];
|
|
continue;
|
|
}
|
|
IL_144:
|
|
this.Output(num, outs);
|
|
num = num4;
|
|
if (this.free_ent < this.maxmaxcode)
|
|
{
|
|
this.codetab[num5] = this.free_ent++;
|
|
this.htab[num5] = i;
|
|
}
|
|
else
|
|
{
|
|
this.ClearTable(outs);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
this.Output(num, outs);
|
|
this.Output(this.EOFCode, outs);
|
|
}
|
|
|
|
// Token: 0x06000044 RID: 68 RVA: 0x00004104 File Offset: 0x00002504
|
|
public void Encode(Stream os)
|
|
{
|
|
os.WriteByte(Convert.ToByte(this.initCodeSize));
|
|
this.remaining = this.imgW * this.imgH;
|
|
this.curPixel = 0;
|
|
this.Compress(this.initCodeSize + 1, os);
|
|
os.WriteByte(0);
|
|
}
|
|
|
|
// Token: 0x06000045 RID: 69 RVA: 0x00004153 File Offset: 0x00002553
|
|
private void Flush(Stream outs)
|
|
{
|
|
if (this.a_count > 0)
|
|
{
|
|
outs.WriteByte(Convert.ToByte(this.a_count));
|
|
outs.Write(this.accum, 0, this.a_count);
|
|
this.a_count = 0;
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000046 RID: 70 RVA: 0x00004190 File Offset: 0x00002590
|
|
private int MaxCode(int n_bits)
|
|
{
|
|
return (1 << n_bits) - 1;
|
|
}
|
|
|
|
// Token: 0x06000047 RID: 71 RVA: 0x000041B0 File Offset: 0x000025B0
|
|
private int NextPixel()
|
|
{
|
|
int num;
|
|
if (this.remaining == 0)
|
|
{
|
|
num = LZWEncoder.EOF;
|
|
}
|
|
else
|
|
{
|
|
this.remaining--;
|
|
int num2 = this.curPixel + 1;
|
|
if (num2 < this.pixAry.GetUpperBound(0))
|
|
{
|
|
byte b = this.pixAry[this.curPixel++];
|
|
num = (int)(b & byte.MaxValue);
|
|
}
|
|
else
|
|
{
|
|
num = 255;
|
|
}
|
|
}
|
|
return num;
|
|
}
|
|
|
|
// Token: 0x06000048 RID: 72 RVA: 0x00004230 File Offset: 0x00002630
|
|
private void Output(int code, Stream outs)
|
|
{
|
|
this.cur_accum &= this.masks[this.cur_bits];
|
|
if (this.cur_bits > 0)
|
|
{
|
|
this.cur_accum |= code << this.cur_bits;
|
|
}
|
|
else
|
|
{
|
|
this.cur_accum = code;
|
|
}
|
|
this.cur_bits += this.n_bits;
|
|
while (this.cur_bits >= 8)
|
|
{
|
|
this.Add((byte)(this.cur_accum & 255), outs);
|
|
this.cur_accum >>= 8;
|
|
this.cur_bits -= 8;
|
|
}
|
|
if (this.free_ent > this.maxcode || this.clear_flg)
|
|
{
|
|
if (this.clear_flg)
|
|
{
|
|
this.maxcode = this.MaxCode(this.n_bits = this.g_init_bits);
|
|
this.clear_flg = false;
|
|
}
|
|
else
|
|
{
|
|
this.n_bits++;
|
|
if (this.n_bits == this.maxbits)
|
|
{
|
|
this.maxcode = this.maxmaxcode;
|
|
}
|
|
else
|
|
{
|
|
this.maxcode = this.MaxCode(this.n_bits);
|
|
}
|
|
}
|
|
}
|
|
if (code == this.EOFCode)
|
|
{
|
|
while (this.cur_bits > 0)
|
|
{
|
|
this.Add((byte)(this.cur_accum & 255), outs);
|
|
this.cur_accum >>= 8;
|
|
this.cur_bits -= 8;
|
|
}
|
|
this.Flush(outs);
|
|
}
|
|
}
|
|
|
|
// Token: 0x04000051 RID: 81
|
|
private static readonly int EOF = -1;
|
|
|
|
// Token: 0x04000052 RID: 82
|
|
private int imgW;
|
|
|
|
// Token: 0x04000053 RID: 83
|
|
private int imgH;
|
|
|
|
// Token: 0x04000054 RID: 84
|
|
private byte[] pixAry;
|
|
|
|
// Token: 0x04000055 RID: 85
|
|
private int initCodeSize;
|
|
|
|
// Token: 0x04000056 RID: 86
|
|
private int remaining;
|
|
|
|
// Token: 0x04000057 RID: 87
|
|
private int curPixel;
|
|
|
|
// Token: 0x04000058 RID: 88
|
|
private static readonly int BITS = 12;
|
|
|
|
// Token: 0x04000059 RID: 89
|
|
private static readonly int HSIZE = 5003;
|
|
|
|
// Token: 0x0400005A RID: 90
|
|
private int n_bits;
|
|
|
|
// Token: 0x0400005B RID: 91
|
|
private int maxbits = LZWEncoder.BITS;
|
|
|
|
// Token: 0x0400005C RID: 92
|
|
private int maxcode;
|
|
|
|
// Token: 0x0400005D RID: 93
|
|
private int maxmaxcode = 1 << LZWEncoder.BITS;
|
|
|
|
// Token: 0x0400005E RID: 94
|
|
private int[] htab = new int[LZWEncoder.HSIZE];
|
|
|
|
// Token: 0x0400005F RID: 95
|
|
private int[] codetab = new int[LZWEncoder.HSIZE];
|
|
|
|
// Token: 0x04000060 RID: 96
|
|
private int hsize = LZWEncoder.HSIZE;
|
|
|
|
// Token: 0x04000061 RID: 97
|
|
private int free_ent = 0;
|
|
|
|
// Token: 0x04000062 RID: 98
|
|
private bool clear_flg = false;
|
|
|
|
// Token: 0x04000063 RID: 99
|
|
private int g_init_bits;
|
|
|
|
// Token: 0x04000064 RID: 100
|
|
private int ClearCode;
|
|
|
|
// Token: 0x04000065 RID: 101
|
|
private int EOFCode;
|
|
|
|
// Token: 0x04000066 RID: 102
|
|
private int cur_accum = 0;
|
|
|
|
// Token: 0x04000067 RID: 103
|
|
private int cur_bits = 0;
|
|
|
|
// Token: 0x04000068 RID: 104
|
|
private int[] masks = new int[]
|
|
{
|
|
0, 1, 3, 7, 15, 31, 63, 127, 255, 511,
|
|
1023, 2047, 4095, 8191, 16383, 32767, 65535
|
|
};
|
|
|
|
// Token: 0x04000069 RID: 105
|
|
private int a_count;
|
|
|
|
// Token: 0x0400006A RID: 106
|
|
private byte[] accum = new byte[256];
|
|
}
|
|
}
|