public byte[] DecodeDXT45(int height, int width, byte[] SourceData)
{
byte[] DestData;
ImageLib.RGBA_COLOR_STRUCT[] Color = new ImageLib.RGBA_COLOR_STRUCT[4];
int i;
ImageLib.RGBA_COLOR_STRUCT CColor;
int CData;
int ChunksPerHLine = width / 4;
//ImageLib.RGBA_COLOR_STRUCT zeroColor = new ImageLib.RGBA_COLOR_STRUCT();
DestData = new byte[(width * height) * 4];
if (ChunksPerHLine == 0)
{
ChunksPerHLine += 1;
}
for (i = 0; i < (width * height); i += 16)
{
Color[0] = il.short_to_rgba(SourceData[i + 8] | (SourceData[i + 9] << 8));
Color[1] = il.short_to_rgba(SourceData[i + 10] | (SourceData[i + 11] << 8));
Color[2] = il.GradientColors(Color[0], Color[1]);
Color[3] = il.GradientColors(Color[1], Color[0]);
CData = (SourceData[i + 12] << 0) | (SourceData[i + 13] << 8) | (SourceData[i + 14] << 16) |
(SourceData[i + 15] << 24);
byte[] Alpha = new byte[8];
Alpha[0] = SourceData[i];
Alpha[1] = SourceData[i + 1];
// Do the alphas
if (Alpha[0] > Alpha[1])
{
// 8-alpha block: derive the other six alphas.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
Alpha[2] = (byte)((6 * Alpha[0] + 1 * Alpha[1] + 3) / 7); // bit code 010
Alpha[3] = (byte)((5 * Alpha[0] + 2 * Alpha[1] + 3) / 7); // bit code 011
Alpha[4] = (byte)((4 * Alpha[0] + 3 * Alpha[1] + 3) / 7); // bit code 100
Alpha[5] = (byte)((3 * Alpha[0] + 4 * Alpha[1] + 3) / 7); // bit code 101
Alpha[6] = (byte)((2 * Alpha[0] + 5 * Alpha[1] + 3) / 7); // bit code 110
Alpha[7] = (byte)((1 * Alpha[0] + 6 * Alpha[1] + 3) / 7); // bit code 111
}
else
{
// 6-alpha block.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
Alpha[2] = (byte)((4 * Alpha[0] + 1 * Alpha[1] + 2) / 5); // Bit code 010
Alpha[3] = (byte)((3 * Alpha[0] + 2 * Alpha[1] + 2) / 5); // Bit code 011
Alpha[4] = (byte)((2 * Alpha[0] + 3 * Alpha[1] + 2) / 5); // Bit code 100
Alpha[5] = (byte)((1 * Alpha[0] + 4 * Alpha[1] + 2) / 5); // Bit code 101
Alpha[6] = 0; // Bit code 110
Alpha[7] = 255; // Bit code 111
}
// Byte Alpha
// 0 Alpha_0
// 1 Alpha_1
// 2 (0)(2) (2 LSBs), (0)(1), (0)(0)
// 3 (1)(1) (1 LSB), (1)(0), (0)(3), (0)(2) (1 MSB)
// 4 (1)(3), (1)(2), (1)(1) (2 MSBs)
// 5 (2)(2) (2 LSBs), (2)(1), (2)(0)
// 6 (3)(1) (1 LSB), (3)(0), (2)(3), (2)(2) (1 MSB)
// 7 (3)(3), (3)(2), (3)(1) (2 MSBs)
// (0
// Read an int and a short
long tmpdword;
int tmpword;
long alphaDat;
tmpword = SourceData[i + 2] | (SourceData[i + 3] << 8);
tmpdword = SourceData[i + 4] | (SourceData[i + 5] << 8) | (SourceData[i + 6] << 16) |
(SourceData[i + 7] << 24);
alphaDat = tmpword | (tmpdword << 16);
int ChunkNum = i / 16;
long XPos = ChunkNum % ChunksPerHLine;
long YPos = (ChunkNum - XPos) / ChunksPerHLine;
long ttmp;
int sizeh = height < 4 ? height : 4;
int sizew = width < 4 ? width : 4;
int x, y;
for (x = 0; x < sizeh; x++)
{
for (y = 0; y < sizew; y++)
{
CColor = Color[CData & 3];
CData >>= 2;
CColor.a = Alpha[alphaDat & 7];
alphaDat >>= 3;
ttmp = ((YPos * 4 + x) * width + XPos * 4 + y) * 4;
if ((CColor.a != 0) |
((CColor.b != 0 | CColor.g != 0 | CColor.r != 0) &
(CColor.b != 255 | CColor.g != 255 | CColor.r != 255)))
{
//int fdfd = 0;
}
DestData[ttmp] = (byte)CColor.b;
DestData[ttmp + 1] = (byte)CColor.g;
DestData[ttmp + 2] = (byte)CColor.r;
DestData[ttmp + 3] = (byte)CColor.a;
}
}
}
return DestData;
}