libWiiSharp/ColorIndexConverter.cs

280 lines
10 KiB
C#
Raw Normal View History

// Decompiled with JetBrains decompiler
// Type: libWiiSharp.ColorIndexConverter
// Assembly: libWiiSharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=null
// MVID: FBF36F3D-B5D6-481F-B5F5-1BD3C19E13B2
// Assembly location: C:\Users\theso\Downloads\NCPatcher\pack\libWiiSharp.dll
using System;
using System.Collections.Generic;
namespace libWiiSharp
{
internal class ColorIndexConverter
{
private uint[] rgbaPalette;
private byte[] tplPalette;
private uint[] rgbaData;
private byte[] tplData;
private TPL_TextureFormat tplFormat;
private TPL_PaletteFormat paletteFormat;
private int width;
private int height;
public byte[] Palette => this.tplPalette;
public byte[] Data => this.tplData;
public ColorIndexConverter(
uint[] rgbaData,
int width,
int height,
TPL_TextureFormat tplFormat,
TPL_PaletteFormat paletteFormat)
{
if (tplFormat != TPL_TextureFormat.CI4 && tplFormat != TPL_TextureFormat.CI8)
throw new Exception("Texture format must be either CI4 or CI8");
if (paletteFormat != TPL_PaletteFormat.IA8 && paletteFormat != TPL_PaletteFormat.RGB565 && paletteFormat != TPL_PaletteFormat.RGB5A3)
throw new Exception("Palette format must be either IA8, RGB565 or RGB5A3!");
this.rgbaData = rgbaData;
this.width = width;
this.height = height;
this.tplFormat = tplFormat;
this.paletteFormat = paletteFormat;
this.buildPalette();
if (tplFormat != TPL_TextureFormat.CI4)
{
if (tplFormat == TPL_TextureFormat.CI8)
this.toCI8();
else
this.toCI14X2();
}
else
this.toCI4();
}
private void toCI4()
{
byte[] numArray = new byte[Shared.AddPadding(this.width, 8) * Shared.AddPadding(this.height, 8) / 2];
int num = 0;
for (int index1 = 0; index1 < this.height; index1 += 8)
{
for (int index2 = 0; index2 < this.width; index2 += 8)
{
for (int index3 = index1; index3 < index1 + 8; ++index3)
{
for (int index4 = index2; index4 < index2 + 8; index4 += 2)
{
uint colorIndex1 = this.getColorIndex(index3 >= this.height || index4 >= this.width ? 0U : this.rgbaData[index3 * this.width + index4]);
uint colorIndex2 = this.getColorIndex(index3 >= this.height || index4 >= this.width ? 0U : (index3 * this.width + index4 + 1 < this.rgbaData.Length ? this.rgbaData[index3 * this.width + index4 + 1] : 0U));
numArray[num++] = (byte) ((uint) (byte) colorIndex1 << 4 | (uint) (byte) colorIndex2);
}
}
}
}
this.tplData = numArray;
}
private void toCI8()
{
byte[] numArray = new byte[Shared.AddPadding(this.width, 8) * Shared.AddPadding(this.height, 4)];
int num1 = 0;
for (int index1 = 0; index1 < this.height; index1 += 4)
{
for (int index2 = 0; index2 < this.width; index2 += 8)
{
for (int index3 = index1; index3 < index1 + 4; ++index3)
{
for (int index4 = index2; index4 < index2 + 8; ++index4)
{
uint num2 = index3 >= this.height || index4 >= this.width ? 0U : this.rgbaData[index3 * this.width + index4];
numArray[num1++] = (byte) this.getColorIndex(num2);
}
}
}
}
this.tplData = numArray;
}
private void toCI14X2()
{
byte[] numArray1 = new byte[Shared.AddPadding(this.width, 4) * Shared.AddPadding(this.height, 4) * 2];
int num1 = 0;
for (int index1 = 0; index1 < this.height; index1 += 4)
{
for (int index2 = 0; index2 < this.width; index2 += 4)
{
for (int index3 = index1; index3 < index1 + 4; ++index3)
{
for (int index4 = index2; index4 < index2 + 4; ++index4)
{
byte[] bytes = BitConverter.GetBytes((ushort) this.getColorIndex(index3 >= this.height || index4 >= this.width ? 0U : this.rgbaData[index3 * this.width + index4]));
byte[] numArray2 = numArray1;
int index5 = num1;
int num2 = index5 + 1;
int num3 = (int) bytes[1];
numArray2[index5] = (byte) num3;
byte[] numArray3 = numArray1;
int index6 = num2;
num1 = index6 + 1;
int num4 = (int) bytes[0];
numArray3[index6] = (byte) num4;
}
}
}
}
this.tplData = numArray1;
}
private void buildPalette()
{
int num1 = 256;
if (this.tplFormat == TPL_TextureFormat.CI4)
num1 = 16;
else if (this.tplFormat == TPL_TextureFormat.CI14X2)
num1 = 16384;
List<uint> uintList = new List<uint>();
List<ushort> ushortList = new List<ushort>();
uintList.Add(0U);
ushortList.Add((ushort) 0);
for (int index = 1; index < this.rgbaData.Length && uintList.Count != num1; ++index)
{
if ((long) (this.rgbaData[index] >> 24 & (uint) byte.MaxValue) >= (this.tplFormat == TPL_TextureFormat.CI14X2 ? 1L : 25L))
{
ushort num2 = Shared.Swap(this.convertToPaletteValue((int) this.rgbaData[index]));
if (!uintList.Contains(this.rgbaData[index]) && !ushortList.Contains(num2))
{
uintList.Add(this.rgbaData[index]);
ushortList.Add(num2);
}
}
}
while (uintList.Count % 16 != 0)
{
uintList.Add(uint.MaxValue);
ushortList.Add(ushort.MaxValue);
}
this.tplPalette = Shared.UShortArrayToByteArray(ushortList.ToArray());
this.rgbaPalette = uintList.ToArray();
}
private ushort convertToPaletteValue(int rgba)
{
int num1 = 0;
int num2;
if (this.paletteFormat == TPL_PaletteFormat.IA8)
{
int num3 = ((rgba & (int) byte.MaxValue) + (rgba >> 8 & (int) byte.MaxValue) + (rgba >> 16 & (int) byte.MaxValue)) / 3 & (int) byte.MaxValue;
num2 = (int) (ushort) ((rgba >> 24 & (int) byte.MaxValue) << 8 | num3);
}
else if (this.paletteFormat == TPL_PaletteFormat.RGB565)
{
num2 = (int) (ushort) ((rgba >> 16 & (int) byte.MaxValue) >> 3 << 11 | (rgba >> 8 & (int) byte.MaxValue) >> 2 << 5 | (rgba & (int) byte.MaxValue) >> 3);
}
else
{
int num3 = rgba >> 16 & (int) byte.MaxValue;
int num4 = rgba >> 8 & (int) byte.MaxValue;
int num5 = rgba & (int) byte.MaxValue;
int num6 = rgba >> 24 & (int) byte.MaxValue;
if (num6 <= 218)
{
int num7 = num1 & -32769;
int num8 = num3 * 15 / (int) byte.MaxValue & 15;
int num9 = num4 * 15 / (int) byte.MaxValue & 15;
int num10 = num5 * 15 / (int) byte.MaxValue & 15;
int num11 = num6 * 7 / (int) byte.MaxValue & 7;
num2 = num7 | num11 << 12 | num10 | num9 << 4 | num8 << 8;
}
else
{
int num7 = num1 | 32768;
int num8 = num3 * 31 / (int) byte.MaxValue & 31;
int num9 = num4 * 31 / (int) byte.MaxValue & 31;
int num10 = num5 * 31 / (int) byte.MaxValue & 31;
num2 = num7 | num10 | num9 << 5 | num8 << 10;
}
}
return (ushort) num2;
}
private uint getColorIndex(uint value)
{
uint num1 = (uint) int.MaxValue;
uint num2 = 0;
if ((long) (value >> 24 & (uint) byte.MaxValue) < (this.tplFormat == TPL_TextureFormat.CI14X2 ? 1L : 25L))
return 0;
ushort paletteValue1 = this.convertToPaletteValue((int) value);
for (int index = 0; index < this.rgbaPalette.Length; ++index)
{
ushort paletteValue2 = this.convertToPaletteValue((int) this.rgbaPalette[index]);
if ((int) paletteValue1 == (int) paletteValue2)
return (uint) index;
uint distance = this.getDistance(paletteValue1, paletteValue2);
if (distance < num1)
{
num1 = distance;
num2 = (uint) index;
}
}
return num2;
}
private uint getDistance(ushort color, ushort paletteColor)
{
int rgbaValue1 = (int) this.convertToRgbaValue(color);
uint rgbaValue2 = this.convertToRgbaValue(paletteColor);
uint val1_1 = (uint) rgbaValue1 >> 24 & (uint) byte.MaxValue;
uint val1_2 = (uint) rgbaValue1 >> 16 & (uint) byte.MaxValue;
uint val1_3 = (uint) rgbaValue1 >> 8 & (uint) byte.MaxValue;
uint val1_4 = (uint) (rgbaValue1 & (int) byte.MaxValue);
uint val2_1 = rgbaValue2 >> 24 & (uint) byte.MaxValue;
uint val2_2 = rgbaValue2 >> 16 & (uint) byte.MaxValue;
uint val2_3 = rgbaValue2 >> 8 & (uint) byte.MaxValue;
uint val2_4 = rgbaValue2 & (uint) byte.MaxValue;
int num1 = (int) Math.Max(val1_1, val2_1) - (int) Math.Min(val1_1, val2_1);
uint num2 = Math.Max(val1_2, val2_2) - Math.Min(val1_2, val2_2);
uint num3 = Math.Max(val1_3, val2_3) - Math.Min(val1_3, val2_3);
uint num4 = Math.Max(val1_4, val2_4) - Math.Min(val1_4, val2_4);
int num5 = (int) num2;
return (uint) (num1 + num5) + num3 + num4;
}
private uint convertToRgbaValue(ushort pixel)
{
if (this.paletteFormat == TPL_PaletteFormat.IA8)
{
int num1 = (int) pixel >> 8;
int num2 = (int) pixel & (int) byte.MaxValue;
return (uint) (num1 | num1 << 8 | num1 << 16 | num2 << 24);
}
if (this.paletteFormat == TPL_PaletteFormat.RGB565)
{
int num1 = ((int) pixel >> 11 & 31) << 3 & (int) byte.MaxValue;
int num2 = ((int) pixel >> 5 & 63) << 2 & (int) byte.MaxValue;
int num3 = ((int) pixel & 31) << 3 & (int) byte.MaxValue;
int maxValue = (int) byte.MaxValue;
return (uint) (num3 | num2 << 8 | num1 << 16 | maxValue << 24);
}
int num4;
int num5;
int num6;
int num7;
if (((int) pixel & 32768) != 0)
{
num4 = ((int) pixel >> 10 & 31) * (int) byte.MaxValue / 31;
num5 = ((int) pixel >> 5 & 31) * (int) byte.MaxValue / 31;
num6 = ((int) pixel & 31) * (int) byte.MaxValue / 31;
num7 = (int) byte.MaxValue;
}
else
{
num7 = ((int) pixel >> 12 & 7) * (int) byte.MaxValue / 7;
num4 = ((int) pixel >> 8 & 15) * (int) byte.MaxValue / 15;
num5 = ((int) pixel >> 4 & 15) * (int) byte.MaxValue / 15;
num6 = ((int) pixel & 15) * (int) byte.MaxValue / 15;
}
return (uint) (num6 | num5 << 8 | num4 << 16 | num7 << 24);
}
}
}