512 lines
12 KiB
C#
512 lines
12 KiB
C#
using System;
|
|
|
|
namespace Gif.Components
|
|
{
|
|
// Token: 0x02000009 RID: 9
|
|
public class NeuQuant
|
|
{
|
|
// Token: 0x0600004A RID: 74 RVA: 0x000043E8 File Offset: 0x000027E8
|
|
public NeuQuant(byte[] thepic, int len, int sample, int paletteSize = 256)
|
|
{
|
|
this.netsize = paletteSize;
|
|
this.initrad = this.netsize >> 3;
|
|
this.maxnetpos = this.netsize - 1;
|
|
this.initradius = this.initrad * NeuQuant.radiusbias;
|
|
this.bias = new int[this.netsize];
|
|
this.freq = new int[this.netsize];
|
|
this.radpower = new int[this.initrad];
|
|
this.thepicture = thepic;
|
|
this.lengthcount = len;
|
|
this.samplefac = sample;
|
|
this.network = new int[this.netsize][];
|
|
for (int i = 0; i < this.netsize; i++)
|
|
{
|
|
this.network[i] = new int[4];
|
|
int[] array = this.network[i];
|
|
array[0] = (array[1] = (array[2] = (i << NeuQuant.netbiasshift + 8) / this.netsize));
|
|
this.freq[i] = NeuQuant.intbias / this.netsize;
|
|
this.bias[i] = 0;
|
|
}
|
|
}
|
|
|
|
// Token: 0x0600004B RID: 75 RVA: 0x0000450C File Offset: 0x0000290C
|
|
public byte[] ColorMap()
|
|
{
|
|
byte[] array = new byte[3 * this.netsize];
|
|
int[] array2 = new int[this.netsize];
|
|
for (int i = 0; i < this.netsize; i++)
|
|
{
|
|
array2[this.network[i][3]] = i;
|
|
}
|
|
int num = 0;
|
|
for (int j = 0; j < this.netsize; j++)
|
|
{
|
|
int num2 = array2[j];
|
|
array[num++] = (byte)this.network[num2][0];
|
|
array[num++] = (byte)this.network[num2][1];
|
|
array[num++] = (byte)this.network[num2][2];
|
|
}
|
|
return array;
|
|
}
|
|
|
|
// Token: 0x0600004C RID: 76 RVA: 0x000045C0 File Offset: 0x000029C0
|
|
public void Inxbuild()
|
|
{
|
|
int num = 0;
|
|
int num2 = 0;
|
|
for (int i = 0; i < this.netsize; i++)
|
|
{
|
|
int[] array = this.network[i];
|
|
int num3 = i;
|
|
int num4 = array[1];
|
|
int[] array2;
|
|
for (int j = i + 1; j < this.netsize; j++)
|
|
{
|
|
array2 = this.network[j];
|
|
if (array2[1] < num4)
|
|
{
|
|
num3 = j;
|
|
num4 = array2[1];
|
|
}
|
|
}
|
|
array2 = this.network[num3];
|
|
if (i != num3)
|
|
{
|
|
int j = array2[0];
|
|
array2[0] = array[0];
|
|
array[0] = j;
|
|
j = array2[1];
|
|
array2[1] = array[1];
|
|
array[1] = j;
|
|
j = array2[2];
|
|
array2[2] = array[2];
|
|
array[2] = j;
|
|
j = array2[3];
|
|
array2[3] = array[3];
|
|
array[3] = j;
|
|
}
|
|
if (num4 != num)
|
|
{
|
|
this.netindex[num] = num2 + i >> 1;
|
|
for (int j = num + 1; j < num4; j++)
|
|
{
|
|
this.netindex[j] = i;
|
|
}
|
|
num = num4;
|
|
num2 = i;
|
|
}
|
|
}
|
|
this.netindex[num] = num2 + this.maxnetpos >> 1;
|
|
for (int j = num + 1; j < 256; j++)
|
|
{
|
|
this.netindex[j] = this.maxnetpos;
|
|
}
|
|
}
|
|
|
|
// Token: 0x0600004D RID: 77 RVA: 0x0000470C File Offset: 0x00002B0C
|
|
public void Learn()
|
|
{
|
|
if (this.lengthcount < NeuQuant.minpicturebytes)
|
|
{
|
|
this.samplefac = 1;
|
|
}
|
|
this.alphadec = 30 + (this.samplefac - 1) / 3;
|
|
byte[] array = this.thepicture;
|
|
int num = 0;
|
|
int num2 = this.lengthcount;
|
|
int num3 = this.lengthcount / (3 * this.samplefac);
|
|
int num4 = num3 / NeuQuant.ncycles;
|
|
int num5 = NeuQuant.initalpha;
|
|
int num6 = this.initradius;
|
|
int num7 = num6 >> NeuQuant.radiusbiasshift;
|
|
if (num7 <= 1)
|
|
{
|
|
num7 = 0;
|
|
}
|
|
int i;
|
|
for (i = 0; i < num7; i++)
|
|
{
|
|
this.radpower[i] = num5 * ((num7 * num7 - i * i) * NeuQuant.radbias / (num7 * num7));
|
|
}
|
|
int num8;
|
|
if (this.lengthcount < NeuQuant.minpicturebytes)
|
|
{
|
|
num8 = 3;
|
|
}
|
|
else if (this.lengthcount % NeuQuant.prime1 != 0)
|
|
{
|
|
num8 = 3 * NeuQuant.prime1;
|
|
}
|
|
else if (this.lengthcount % NeuQuant.prime2 != 0)
|
|
{
|
|
num8 = 3 * NeuQuant.prime2;
|
|
}
|
|
else if (this.lengthcount % NeuQuant.prime3 != 0)
|
|
{
|
|
num8 = 3 * NeuQuant.prime3;
|
|
}
|
|
else
|
|
{
|
|
num8 = 3 * NeuQuant.prime4;
|
|
}
|
|
i = 0;
|
|
while (i < num3)
|
|
{
|
|
int num9 = (int)(array[num] & byte.MaxValue) << NeuQuant.netbiasshift;
|
|
int num10 = (int)(array[num + 1] & byte.MaxValue) << NeuQuant.netbiasshift;
|
|
int num11 = (int)(array[num + 2] & byte.MaxValue) << NeuQuant.netbiasshift;
|
|
int j = this.Contest(num9, num10, num11);
|
|
this.Altersingle(num5, j, num9, num10, num11);
|
|
if (num7 != 0)
|
|
{
|
|
this.Alterneigh(num7, j, num9, num10, num11);
|
|
}
|
|
num += num8;
|
|
if (num >= num2)
|
|
{
|
|
num -= this.lengthcount;
|
|
}
|
|
i++;
|
|
if (num4 == 0)
|
|
{
|
|
num4 = 1;
|
|
}
|
|
if (i % num4 == 0)
|
|
{
|
|
num5 -= num5 / this.alphadec;
|
|
num6 -= num6 / NeuQuant.radiusdec;
|
|
num7 = num6 >> NeuQuant.radiusbiasshift;
|
|
if (num7 <= 1)
|
|
{
|
|
num7 = 0;
|
|
}
|
|
for (j = 0; j < num7; j++)
|
|
{
|
|
this.radpower[j] = num5 * ((num7 * num7 - j * j) * NeuQuant.radbias / (num7 * num7));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Token: 0x0600004E RID: 78 RVA: 0x0000496C File Offset: 0x00002D6C
|
|
public int Map(int b, int g, int r)
|
|
{
|
|
int num = 1000;
|
|
int num2 = -1;
|
|
int num3 = this.netindex[g];
|
|
int num4 = num3 - 1;
|
|
while (num3 < this.netsize || num4 >= 0)
|
|
{
|
|
if (num3 < this.netsize)
|
|
{
|
|
int[] array = this.network[num3];
|
|
int num5 = array[1] - g;
|
|
if (num5 >= num)
|
|
{
|
|
num3 = this.netsize;
|
|
}
|
|
else
|
|
{
|
|
num3++;
|
|
if (num5 < 0)
|
|
{
|
|
num5 = -num5;
|
|
}
|
|
int num6 = array[0] - b;
|
|
if (num6 < 0)
|
|
{
|
|
num6 = -num6;
|
|
}
|
|
num5 += num6;
|
|
if (num5 < num)
|
|
{
|
|
num6 = array[2] - r;
|
|
if (num6 < 0)
|
|
{
|
|
num6 = -num6;
|
|
}
|
|
num5 += num6;
|
|
if (num5 < num)
|
|
{
|
|
num = num5;
|
|
num2 = array[3];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (num4 >= 0)
|
|
{
|
|
int[] array = this.network[num4];
|
|
int num5 = g - array[1];
|
|
if (num5 >= num)
|
|
{
|
|
num4 = -1;
|
|
}
|
|
else
|
|
{
|
|
num4--;
|
|
if (num5 < 0)
|
|
{
|
|
num5 = -num5;
|
|
}
|
|
int num6 = array[0] - b;
|
|
if (num6 < 0)
|
|
{
|
|
num6 = -num6;
|
|
}
|
|
num5 += num6;
|
|
if (num5 < num)
|
|
{
|
|
num6 = array[2] - r;
|
|
if (num6 < 0)
|
|
{
|
|
num6 = -num6;
|
|
}
|
|
num5 += num6;
|
|
if (num5 < num)
|
|
{
|
|
num = num5;
|
|
num2 = array[3];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return num2;
|
|
}
|
|
|
|
// Token: 0x0600004F RID: 79 RVA: 0x00004AC0 File Offset: 0x00002EC0
|
|
public byte[] Process()
|
|
{
|
|
this.Learn();
|
|
this.Unbiasnet();
|
|
this.Inxbuild();
|
|
return this.ColorMap();
|
|
}
|
|
|
|
// Token: 0x06000050 RID: 80 RVA: 0x00004AF0 File Offset: 0x00002EF0
|
|
public void Unbiasnet()
|
|
{
|
|
for (int i = 0; i < this.netsize; i++)
|
|
{
|
|
this.network[i][0] >>= NeuQuant.netbiasshift;
|
|
this.network[i][1] >>= NeuQuant.netbiasshift;
|
|
this.network[i][2] >>= NeuQuant.netbiasshift;
|
|
this.network[i][3] = i;
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000051 RID: 81 RVA: 0x00004B70 File Offset: 0x00002F70
|
|
protected void Alterneigh(int rad, int i, int b, int g, int r)
|
|
{
|
|
int num = i - rad;
|
|
if (num < -1)
|
|
{
|
|
num = -1;
|
|
}
|
|
int num2 = i + rad;
|
|
if (num2 > this.netsize)
|
|
{
|
|
num2 = this.netsize;
|
|
}
|
|
int num3 = i + 1;
|
|
int num4 = i - 1;
|
|
int num5 = 1;
|
|
while (num3 < num2 || num4 > num)
|
|
{
|
|
int num6 = this.radpower[num5++];
|
|
if (num3 < num2)
|
|
{
|
|
int[] array = this.network[num3++];
|
|
try
|
|
{
|
|
array[0] -= num6 * (array[0] - b) / NeuQuant.alpharadbias;
|
|
array[1] -= num6 * (array[1] - g) / NeuQuant.alpharadbias;
|
|
array[2] -= num6 * (array[2] - r) / NeuQuant.alpharadbias;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
}
|
|
}
|
|
if (num4 > num)
|
|
{
|
|
int[] array = this.network[num4--];
|
|
try
|
|
{
|
|
array[0] -= num6 * (array[0] - b) / NeuQuant.alpharadbias;
|
|
array[1] -= num6 * (array[1] - g) / NeuQuant.alpharadbias;
|
|
array[2] -= num6 * (array[2] - r) / NeuQuant.alpharadbias;
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000052 RID: 82 RVA: 0x00004CE4 File Offset: 0x000030E4
|
|
protected void Altersingle(int alpha, int i, int b, int g, int r)
|
|
{
|
|
int[] array = this.network[i];
|
|
array[0] -= alpha * (array[0] - b) / NeuQuant.initalpha;
|
|
array[1] -= alpha * (array[1] - g) / NeuQuant.initalpha;
|
|
array[2] -= alpha * (array[2] - r) / NeuQuant.initalpha;
|
|
}
|
|
|
|
// Token: 0x06000053 RID: 83 RVA: 0x00004D48 File Offset: 0x00003148
|
|
protected int Contest(int b, int g, int r)
|
|
{
|
|
int num = int.MaxValue;
|
|
int num2 = num;
|
|
int num3 = -1;
|
|
int num4 = num3;
|
|
for (int i = 0; i < this.netsize; i++)
|
|
{
|
|
int[] array = this.network[i];
|
|
int num5 = array[0] - b;
|
|
if (num5 < 0)
|
|
{
|
|
num5 = -num5;
|
|
}
|
|
int num6 = array[1] - g;
|
|
if (num6 < 0)
|
|
{
|
|
num6 = -num6;
|
|
}
|
|
num5 += num6;
|
|
num6 = array[2] - r;
|
|
if (num6 < 0)
|
|
{
|
|
num6 = -num6;
|
|
}
|
|
num5 += num6;
|
|
if (num5 < num)
|
|
{
|
|
num = num5;
|
|
num3 = i;
|
|
}
|
|
int num7 = num5 - (this.bias[i] >> NeuQuant.intbiasshift - NeuQuant.netbiasshift);
|
|
if (num7 < num2)
|
|
{
|
|
num2 = num7;
|
|
num4 = i;
|
|
}
|
|
int num8 = this.freq[i] >> NeuQuant.betashift;
|
|
this.freq[i] -= num8;
|
|
this.bias[i] += num8 << NeuQuant.gammashift;
|
|
}
|
|
this.freq[num3] += NeuQuant.beta;
|
|
this.bias[num3] -= NeuQuant.betagamma;
|
|
return num4;
|
|
}
|
|
|
|
// Token: 0x0400006B RID: 107
|
|
protected int netsize;
|
|
|
|
// Token: 0x0400006C RID: 108
|
|
protected static readonly int prime1 = 499;
|
|
|
|
// Token: 0x0400006D RID: 109
|
|
protected static readonly int prime2 = 491;
|
|
|
|
// Token: 0x0400006E RID: 110
|
|
protected static readonly int prime3 = 487;
|
|
|
|
// Token: 0x0400006F RID: 111
|
|
protected static readonly int prime4 = 503;
|
|
|
|
// Token: 0x04000070 RID: 112
|
|
protected static readonly int minpicturebytes = 3 * NeuQuant.prime4;
|
|
|
|
// Token: 0x04000071 RID: 113
|
|
protected int maxnetpos;
|
|
|
|
// Token: 0x04000072 RID: 114
|
|
protected static readonly int netbiasshift = 4;
|
|
|
|
// Token: 0x04000073 RID: 115
|
|
protected static readonly int ncycles = 100;
|
|
|
|
// Token: 0x04000074 RID: 116
|
|
protected static readonly int intbiasshift = 16;
|
|
|
|
// Token: 0x04000075 RID: 117
|
|
protected static readonly int intbias = 1 << NeuQuant.intbiasshift;
|
|
|
|
// Token: 0x04000076 RID: 118
|
|
protected static readonly int gammashift = 10;
|
|
|
|
// Token: 0x04000077 RID: 119
|
|
protected static readonly int gamma = 1 << NeuQuant.gammashift;
|
|
|
|
// Token: 0x04000078 RID: 120
|
|
protected static readonly int betashift = 10;
|
|
|
|
// Token: 0x04000079 RID: 121
|
|
protected static readonly int beta = NeuQuant.intbias >> NeuQuant.betashift;
|
|
|
|
// Token: 0x0400007A RID: 122
|
|
protected static readonly int betagamma = NeuQuant.intbias << NeuQuant.gammashift - NeuQuant.betashift;
|
|
|
|
// Token: 0x0400007B RID: 123
|
|
protected int initrad;
|
|
|
|
// Token: 0x0400007C RID: 124
|
|
protected static readonly int radiusbiasshift = 6;
|
|
|
|
// Token: 0x0400007D RID: 125
|
|
protected static readonly int radiusbias = 1 << NeuQuant.radiusbiasshift;
|
|
|
|
// Token: 0x0400007E RID: 126
|
|
protected int initradius;
|
|
|
|
// Token: 0x0400007F RID: 127
|
|
protected static readonly int radiusdec = 30;
|
|
|
|
// Token: 0x04000080 RID: 128
|
|
protected static readonly int alphabiasshift = 10;
|
|
|
|
// Token: 0x04000081 RID: 129
|
|
protected static readonly int initalpha = 1 << NeuQuant.alphabiasshift;
|
|
|
|
// Token: 0x04000082 RID: 130
|
|
protected int alphadec;
|
|
|
|
// Token: 0x04000083 RID: 131
|
|
protected static readonly int radbiasshift = 8;
|
|
|
|
// Token: 0x04000084 RID: 132
|
|
protected static readonly int radbias = 1 << NeuQuant.radbiasshift;
|
|
|
|
// Token: 0x04000085 RID: 133
|
|
protected static readonly int alpharadbshift = NeuQuant.alphabiasshift + NeuQuant.radbiasshift;
|
|
|
|
// Token: 0x04000086 RID: 134
|
|
protected static readonly int alpharadbias = 1 << NeuQuant.alpharadbshift;
|
|
|
|
// Token: 0x04000087 RID: 135
|
|
protected byte[] thepicture;
|
|
|
|
// Token: 0x04000088 RID: 136
|
|
protected int lengthcount;
|
|
|
|
// Token: 0x04000089 RID: 137
|
|
protected int samplefac;
|
|
|
|
// Token: 0x0400008A RID: 138
|
|
protected int[][] network;
|
|
|
|
// Token: 0x0400008B RID: 139
|
|
protected int[] netindex = new int[256];
|
|
|
|
// Token: 0x0400008C RID: 140
|
|
protected int[] bias;
|
|
|
|
// Token: 0x0400008D RID: 141
|
|
protected int[] freq;
|
|
|
|
// Token: 0x0400008E RID: 142
|
|
protected int[] radpower;
|
|
}
|
|
}
|