Mercurial > repos > IBBoard.Graphics
diff DDSFile.cs @ 0:712d9d93c863
Initial commit of IBBoard libraries
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Fri, 19 Dec 2008 11:13:48 +0000 |
parents | |
children | 1c89affbdd64 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DDSFile.cs Fri Dec 19 11:13:48 2008 +0000 @@ -0,0 +1,550 @@ +using System; +using System.Drawing; +using IBBoard.Graphics.SquishWrapper; + +namespace IBBoard.Graphics +{ + /// <summary> + /// Summary description for DDSFile. + /// </summary> + public class DDSFile + { + public enum DXTType { None, DXT1, DXT3, DXT5 } + + byte[] data; + DXTType type; + int width, height; + byte blockwidth; + byte alphawidth; + + public static readonly byte[] DXT1_Header = new byte[]{0x44, 0x44, 0x53, 0x20,//"DDS " + 0x7C, 0x00, 0x00, 0x00,//size - fixed to 124 + 0x07, 0x10, 0x0A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//leave space for width and height + 0x00, 0x00, 0x00, 0x00,//and data length + 0x00, 0x00, 0x00, 0x00,//zero the volume depths + 0x00, 0x00, 0x00, 0x00,//and leave space for the mip maps + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//11 DWords of unspecified 'reserved' + 0x20, 0x00, 0x00, 0x00, //size - apparently fixed to 32 + 0x04, 0x00, 0x00, 0x00,//DDPF_FOURCC + 0x44, 0x58, 0x54, 0x31,//DTX1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //RGB and Alpha bit masks - not used in DoW DDS files + 0x08, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, //DDS Caps - always the same in DoW + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//two more reserved DWords + 0x00, 0x00, 0x00, 0x00};//and a final reserved DWord for good measure! + + public static readonly byte[] DXT5_Header = new byte[]{0x44, 0x44, 0x53, 0x20,//"DDS " + 0x7C, 0x00, 0x00, 0x00,//size - fixed to 124 + 0x07, 0x10, 0x0A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//leave space for width and height + 0x00, 0x00, 0x00, 0x00,//and data length + 0x00, 0x00, 0x00, 0x00,//zero the volume depths + 0x00, 0x00, 0x00, 0x00,//and leave space for the mip maps + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//11 DWords of unspecified 'reserved' + 0x20, 0x00, 0x00, 0x00, //size - apparently fixed to 32 + 0x04, 0x00, 0x00, 0x00,//DDPF_FOURCC + 0x44, 0x58, 0x54, 0x35,//DTX5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //RGB and Alpha bit masks - not used in DoW DDS files + 0x08, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, //DDS Caps - always the same in DoW + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//two more reserved DWords + 0x00, 0x00, 0x00, 0x00};//and a final reserved DWord for good measure! + + public static readonly byte[] DXT3_Header = new byte[]{0x44, 0x44, 0x53, 0x20,//"DDS " + 0x7C, 0x00, 0x00, 0x00,//size - fixed to 124 + 0x07, 0x10, 0x0A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//leave space for width and height + 0x00, 0x00, 0x00, 0x00,//and data length + 0x00, 0x00, 0x00, 0x00,//zero the volume depths + 0x00, 0x00, 0x00, 0x00,//and leave space for the mip maps + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//11 DWords of unspecified 'reserved' + 0x20, 0x00, 0x00, 0x00, //size - apparently fixed to 32 + 0x04, 0x00, 0x00, 0x00,//DDPF_FOURCC + 0x44, 0x58, 0x54, 0x33,//DTX5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //RGB and Alpha bit masks - not used in DoW DDS files + 0x08, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, //DDS Caps - always the same in DoW + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//two more reserved DWords + 0x00, 0x00, 0x00, 0x00};//and a final reserved DWord for good measure! + + public DDSFile(byte[] file) + { + data = file; + height = data[12]+(data[13]<<8)+(data[14]<<16)+(data[15]<<24); + width = data[16]+(data[17]<<8)+(data[18]<<16)+(data[19]<<24); + + switch(data[87]) + { + case 0x31: + type = DXTType.DXT1; + blockwidth=8; + alphawidth = 0; + break; + case 0x33: + type = DXTType.DXT3; + blockwidth = 16; + alphawidth = 8; + break; + case 0x35: + type = DXTType.DXT5; + blockwidth = 16; + alphawidth = 8; + break; + default: + throw new InvalidOperationException("Unsupported DDS type - only DXT1, DXT3 and DXT5 are currently supported"); + } + } + + private DDSFile(byte[] ddsData, int imgWidth, int imgHeight, DXTType compression) + { + data = new byte[128+ddsData.Length]; + type = compression; + width = imgWidth; + height= imgHeight; + + switch(type) + { + case DXTType.DXT1: + blockwidth=8; + alphawidth = 0; + DXT1_Header.CopyTo(data, 0); + break; + case DXTType.DXT3: + blockwidth = 16; + alphawidth = 8; + DXT3_Header.CopyTo(data, 0); + break; + case DXTType.DXT5: + blockwidth = 16; + alphawidth = 8; + DXT5_Header.CopyTo(data, 0); + break; + default: + throw new InvalidOperationException("Unsupported DDS type - only DXT1, DXT3 and DXT5 are currently supported"); + } + + data[12] = (byte)height; + data[13] = (byte)(height >> 8); + data[14] = (byte)(height >> 16); + data[15] = (byte)(height >> 24); + data[16] = (byte)width; + data[17] = (byte)(width >> 8); + data[18] = (byte)(width >> 16); + data[19] = (byte)(width >> 24); + + int mips = CalcMips(width, height); + data[28] = (byte)mips; + data[29] = (byte)(mips >> 8); + data[30] = (byte)(mips >> 16); + data[31] = (byte)(mips >> 24); + + ddsData.CopyTo(data, 128); + } + + public int Width + { + get{return width;} + } + + public int Height + { + get{return height;} + } + + public DXTType Type + { + get{ return type;} + } + + private static int CalcMips(int width, int height) + { + return (int)Math.Ceiling(Math.Log(Math.Max(width, height))/Math.Log(2))+1; + } + + private static int CalcDataSize(DXTType type, int width, int height, int mipmaps) + { + int val = 0; + byte bytes = (byte)BlockSize(type); + + width = width/4; + height = height/4; + + for (int i = 0; i<mipmaps; i++) + { + val+= width*height*bytes; + width = (width>1)?width/2:1; + height = (height>1)?height/2:1; + } + + return val; + } + + private static int BlockSize(DXTType type) + { + if (type==DXTType.DXT1) + { + return 8; + } + else if (type == DXTType.DXT5 || type == DXTType.DXT3) + { + return 16; + } + else + { + throw new InvalidOperationException("Unsupported DDS type - only DXT1, DXT3 and DXT5 are currently supported"); + } + } + + private ushort GetColour0(int pos) + { + int start = 128+(pos*blockwidth) + alphawidth; + return (ushort)(data[start]+((ushort)data[start+1]<<8)); + } + + private ushort GetColour1(int pos) + { + int start = 128+(pos*blockwidth) + alphawidth; + return (ushort)(data[start+2]+((ushort)data[start+3]<<8)); + } + + private byte GetPixelColour(int pos, byte pixel) + { + int start = 128+(pos*blockwidth) + alphawidth; + return data[start+4+pixel]; + } + + private byte[] GetInterpolatedAlpha(int pos) + { + int start = 128+(pos*blockwidth); + return new byte[]{data[start], data[start+1], data[start+2], data[start+3], data[start+4], data[start+5], data[start+6], data[start+7]}; + } + + private ushort[] GetLinearAlpha(int pos) + { + int start = 128+(pos*blockwidth); + return new ushort[]{(ushort)(data[start]+ (data[start+1]<<8)), (ushort)(data[start+2]+ (ushort)(data[start+3]<<8)), (ushort)(data[start+4] + (data[start+5]<<8)), (ushort)(data[start+6] + (data[start+7]<<8))}; + } + + public byte[] Bytes + { + get{return data;} + } + + public byte[] GetTGAData() + { + byte[] tgaFile = new byte[width*height*4+18]; + + IBBoard.Graphics.Converter.TGA_Colour_Header.CopyTo(tgaFile, 0); + tgaFile[12] = (byte)width; + tgaFile[13] = (byte)(width>>8); + tgaFile[14] = (byte)height; + tgaFile[15] = (byte)(height>>8); + + int i, j; + int texels_per_row = Math.Max(width >> 2, 1); + int texel_rows = Math.Max(height >> 2, 1); + int stride = width; + + byte[] interpolated_alpha; + ushort[] linear_alpha; + uint[] color_map = new uint[4]; + byte[] alpha_map = new byte[8]; + uint[,] alphadata = new uint[4,4]; + uint rgba; + int k, l; + uint pixel_alpha_01, pixel_alpha_23; + ushort colour0, colour1; + int texelnum, tgacounter, pixelColour; + byte index; + + if (this.Type == DXTType.DXT1) + { + for (i = 0; i < texel_rows; i++) + { + for (j = 0; j < texels_per_row; j++) + { + for (k=0; k<4; k++) + { + for (l=0; l<4; l++) + { + alphadata[k,l] = 0xffffffff; + } + } + + texelnum = i*texels_per_row + j; + + colour0 = GetColour0(texelnum); + colour1 = GetColour1(texelnum); + + color_map[0] = Converter.rgb565_to_rgba(colour0); + color_map[1] = Converter.rgb565_to_rgba(colour1); + + if (colour0 <= colour1) + { + color_map[2] = (uint)(((byte)color_map[1] + (byte)color_map[0]) / 2) + + ((uint)(((byte)(color_map[1]>>8) + (byte)(color_map[0]>>8)) / 2)<<8) + + ((uint)(((byte)(color_map[1]>>16) + (byte)(color_map[0]>>16)) / 2)<<16) + + ((uint)(((byte)(color_map[1]>>24) + (byte)(color_map[0]>>24)) / 2)<<24); + color_map[3] = 0x00000000;//colour map3 = transparent + + for (k=0; k<4; k++) + { + pixelColour = GetPixelColour(texelnum, (byte)k); + tgacounter = (i*4*texels_per_row + j + (k * texels_per_row))*4; + + for (l=0; l<4; l++) + { + index = (byte)((pixelColour >> (l*2)) & 0x03); + rgba = color_map[index]; + tgaFile[(tgacounter + l)*4 + 18] = (byte)rgba; + tgaFile[(tgacounter + l)*4 + 19] = (byte)(rgba>>8); + tgaFile[(tgacounter + l)*4 + 20] = (byte)(rgba>>16); + tgaFile[(tgacounter + l)*4 + 21] = (byte)((index==3)?0x00:0xff); + } + } + } + else + { + color_map[2] = (uint)((2 * (byte)color_map[0] + (byte)color_map[1] + 1) / 3) + + ((uint)((2 * (byte)(color_map[0]>>8) + (byte)(color_map[1]>>8) + 1) / 3)<<8) + + ((uint)((2 * (byte)(color_map[0]>>16) + (byte)(color_map[1]>>16) + 1) / 3)<<16) + + ((uint)((2 * (byte)(color_map[0]>>24) + (byte)(color_map[1]>>24) + 1) / 3)<<24); + color_map[3] = (uint)((2 * (byte)color_map[1] + (byte)color_map[0] + 1) / 3) + + ((uint)((2 * (byte)(color_map[1]>>8) + (byte)(color_map[0]>>8) + 1) / 3)<<8) + + ((uint)((2 * (byte)(color_map[1]>>16) + (byte)(color_map[0]>>16) + 1) / 3)<<16) + + ((uint)((2 * (byte)(color_map[1]>>24) + (byte)(color_map[0]>>24) + 1) / 3)<<24); + + for (k=0; k<4; k++) + { + pixelColour = GetPixelColour(texelnum, (byte)k); + tgacounter = (i*4*texels_per_row + j + (k * texels_per_row))*4; + + for (l=0; l<4; l++) + { + index = (byte)((pixelColour >> (l*2)) & 0x03); + rgba = color_map[index] & alphadata[k,l]; + tgaFile[(tgacounter + l)*4 + 18] = (byte)rgba; + tgaFile[(tgacounter + l)*4 + 19] = (byte)(rgba>>8); + tgaFile[(tgacounter + l)*4 + 20] = (byte)(rgba>>16); + tgaFile[(tgacounter + l)*4 + 21] = 0xff; + } + } + } + } + } + } + else if (this.Type == DXTType.DXT5) + { + for (i = 0; i < texel_rows; i++) + { + for (j = 0; j < texels_per_row; j++) + { + interpolated_alpha = GetInterpolatedAlpha(i*texels_per_row + j); + alpha_map[0] = interpolated_alpha[0]; + alpha_map[1] = interpolated_alpha[1]; + if (alpha_map[0] <= alpha_map[1]) + { + alpha_map[2] = (byte)((4*alpha_map[0] + 1*alpha_map[1] + 2) / 5); // Bit code 010 + alpha_map[3] = (byte)((3*alpha_map[0] + 2*alpha_map[1] + 2) / 5); // Bit code 011 + alpha_map[4] = (byte)((2*alpha_map[0] + 3*alpha_map[1] + 2) / 5); // Bit code 100 + alpha_map[5] = (byte)((1*alpha_map[0] + 4*alpha_map[1] + 2) / 5); // Bit code 101 + alpha_map[6] = 0; // Bit code 110 + alpha_map[7] = 255; // Bit code 111 + } + else + { + alpha_map[2] = (byte)((6*alpha_map[0] + 1*alpha_map[1] + 3) / 7); // bit code 010 + alpha_map[3] = (byte)((5*alpha_map[0] + 2*alpha_map[1] + 3) / 7); // bit code 011 + alpha_map[4] = (byte)((4*alpha_map[0] + 3*alpha_map[1] + 3) / 7); // bit code 100 + alpha_map[5] = (byte)((3*alpha_map[0] + 4*alpha_map[1] + 3) / 7); // bit code 101 + alpha_map[6] = (byte)((2*alpha_map[0] + 5*alpha_map[1] + 3) / 7); // bit code 110 + alpha_map[7] = (byte)((1*alpha_map[0] + 6*alpha_map[1] + 3) / 7); // bit code 111 + } + + pixel_alpha_01 = (uint)(((uint)interpolated_alpha[4] << 16) | + ((uint)interpolated_alpha[3] << 8) | + ((uint)interpolated_alpha[2])); + pixel_alpha_23 = (uint)(((uint)interpolated_alpha[7] << 16) | + ((uint)interpolated_alpha[6] << 8) | + ((uint)interpolated_alpha[5])); + + alphadata[0,0] = (uint)(alpha_map[(pixel_alpha_01 >> 0) & 0x07] << 24) | 0x00ffffff; + alphadata[0,1] = (uint)(alpha_map[(pixel_alpha_01 >> 3) & 0x07] << 24) | 0x00ffffff; + alphadata[0,2] = (uint)(alpha_map[(pixel_alpha_01 >> 6) & 0x07] << 24) | 0x00ffffff; + alphadata[0,3] = (uint)(alpha_map[(pixel_alpha_01 >> 9) & 0x07] << 24) | 0x00ffffff; + alphadata[1,0] = (uint)(alpha_map[(pixel_alpha_01 >> 12) & 0x07] << 24) | 0x00ffffff; + alphadata[1,1] = (uint)(alpha_map[(pixel_alpha_01 >> 15) & 0x07] << 24) | 0x00ffffff; + alphadata[1,2] = (uint)(alpha_map[(pixel_alpha_01 >> 18) & 0x07] << 24) | 0x00ffffff; + alphadata[1,3] = (uint)(alpha_map[(pixel_alpha_01 >> 21) & 0x07] << 24) | 0x00ffffff; + alphadata[2,0] = (uint)(alpha_map[(pixel_alpha_23 >> 0) & 0x07] << 24) | 0x00ffffff; + alphadata[2,1] = (uint)(alpha_map[(pixel_alpha_23 >> 3) & 0x07] << 24) | 0x00ffffff; + alphadata[2,2] = (uint)(alpha_map[(pixel_alpha_23 >> 6) & 0x07] << 24) | 0x00ffffff; + alphadata[2,3] = (uint)(alpha_map[(pixel_alpha_23 >> 9) & 0x07] << 24) | 0x00ffffff; + alphadata[3,0] = (uint)(alpha_map[(pixel_alpha_23 >> 12) & 0x07] << 24) | 0x00ffffff; + alphadata[3,1] = (uint)(alpha_map[(pixel_alpha_23 >> 15) & 0x07] << 24) | 0x00ffffff; + alphadata[3,2] = (uint)(alpha_map[(pixel_alpha_23 >> 18) & 0x07] << 24) | 0x00ffffff; + alphadata[3,3] = (uint)(alpha_map[(pixel_alpha_23 >> 21) & 0x07] << 24) | 0x00ffffff; + + texelnum = i*texels_per_row + j; + + color_map[0] = Converter.rgb565_to_rgba(GetColour0(texelnum)); + color_map[1] = Converter.rgb565_to_rgba(GetColour1(texelnum)); + + color_map[2] = (uint)((2 * (byte)color_map[0] + (byte)color_map[1] + 1) / 3) + + ((uint)((2 * (byte)(color_map[0]>>8) + (byte)(color_map[1]>>8) + 1) / 3)<<8) + + ((uint)((2 * (byte)(color_map[0]>>16) + (byte)(color_map[1]>>16) + 1) / 3)<<16) + + ((uint)((2 * (byte)(color_map[0]>>24) + (byte)(color_map[1]>>24) + 1) / 3)<<24); + color_map[3] = (uint)((2 * (byte)color_map[1] + (byte)color_map[0] + 1) / 3) + + ((uint)((2 * (byte)(color_map[1]>>8) + (byte)(color_map[0]>>8) + 1) / 3)<<8) + + ((uint)((2 * (byte)(color_map[1]>>16) + (byte)(color_map[0]>>16) + 1) / 3)<<16) + + ((uint)((2 * (byte)(color_map[1]>>24) + (byte)(color_map[0]>>24) + 1) / 3)<<24); + + for (k=0; k<4; k++) + { + pixelColour = GetPixelColour(texelnum, (byte)k); + tgacounter = (i*4*texels_per_row + j + (k * texels_per_row))*4; + + for (l=0; l<4; l++) + { + index = (byte)((pixelColour >> (l*2)) & 0x03); + rgba = color_map[index] & alphadata[k,l]; + tgaFile[(tgacounter + l)*4 + 18] = (byte)rgba; + tgaFile[(tgacounter + l)*4 + 19] = (byte)(rgba>>8); + tgaFile[(tgacounter + l)*4 + 20] = (byte)(rgba>>16); + tgaFile[(tgacounter + l)*4 + 21] = (byte)(rgba>>24); + } + } + } + } + } + else if (this.Type == DXTType.DXT3) + { + for (i = 0; i < texel_rows; i++) + { + for (j = 0; j < texels_per_row; j++) + { + linear_alpha = GetLinearAlpha(i*texels_per_row + j); + + for (k=0; k<4; k++) + { + alphadata[k,0] = (uint)((((uint)linear_alpha[k] << 4) & 0xf0) << 24) | 0x00ffffff; + alphadata[k,1] = (uint)((((uint)linear_alpha[k] << 0) & 0xf0) << 24) | 0x00ffffff; + alphadata[k,2] = (uint)((((uint)linear_alpha[k] >> 4) & 0xf0) << 24) | 0x00ffffff; + alphadata[k,3] = (uint)((((uint)linear_alpha[k] >> 8) & 0xf0) << 24) | 0x00ffffff; + } + + texelnum = i*texels_per_row + j; + + color_map[0] = Converter.rgb565_to_rgba(GetColour0(texelnum)); + color_map[1] = Converter.rgb565_to_rgba(GetColour1(texelnum)); + + color_map[2] = (uint)((2 * (byte)color_map[0] + (byte)color_map[1] + 1) / 3) + + ((uint)((2 * (byte)(color_map[0]>>8) + (byte)(color_map[1]>>8) + 1) / 3)<<8) + + ((uint)((2 * (byte)(color_map[0]>>16) + (byte)(color_map[1]>>16) + 1) / 3)<<16) + + ((uint)((2 * (byte)(color_map[0]>>24) + (byte)(color_map[1]>>24) + 1) / 3)<<24); + color_map[3] = (uint)((2 * (byte)color_map[1] + (byte)color_map[0] + 1) / 3) + + ((uint)((2 * (byte)(color_map[1]>>8) + (byte)(color_map[0]>>8) + 1) / 3)<<8) + + ((uint)((2 * (byte)(color_map[1]>>16) + (byte)(color_map[0]>>16) + 1) / 3)<<16) + + ((uint)((2 * (byte)(color_map[1]>>24) + (byte)(color_map[0]>>24) + 1) / 3)<<24); + + for (k=0; k<4; k++) + { + pixelColour = GetPixelColour(texelnum, (byte)k); + tgacounter = (i*4*texels_per_row + j + (k * texels_per_row))*4; + + for (l=0; l<4; l++) + { + index = (byte)((pixelColour >> (l*2)) & 0x03); + rgba = color_map[index] & alphadata[k,l]; + tgaFile[(tgacounter + l)*4 + 18] = (byte)rgba; + tgaFile[(tgacounter + l)*4 + 19] = (byte)(rgba>>8); + tgaFile[(tgacounter + l)*4 + 20] = (byte)(rgba>>16); + tgaFile[(tgacounter + l)*4 + 21] = (byte)(rgba>>24); + } + } + } + } + } + else + { + throw new InvalidOperationException("DDS file was not a DXT1, DXT3 or DXT5 file"); + } + + return tgaFile; + } + + public static DDSFile MakeFrom32bitBGRA(byte[] rawData, DXTType DXTCFormat, int width, int height) + { + byte[] data = new byte[rawData.Length]; + rawData.CopyTo(data, 0); + + for (int i = 0; i < data.Length; i+= 4) + { + byte temp = data[i]; + data[i] = data[i+2]; + data[i+2] = temp; + } + + return MakeFrom32bitRGBA(data, DXTCFormat, width, height); + } + + public static DDSFile MakeFrom32bitRGBA(byte[] rawData, DXTType DXTCFormat, int width, int height) + { + SquishFlags format; + + switch(DXTCFormat) + { + case DXTType.DXT1: format = SquishFlags.kDxt1; + break; + case DXTType.DXT3: format = SquishFlags.kDxt3; + break; + case DXTType.DXT5: format = SquishFlags.kDxt5; + break; + default: throw new InvalidOperationException("Invalid DXT Type supplied: "+DXTCFormat.ToString()); + } + + return MakeWithMipMapsFrom32bitRGBA(rawData, DXTCFormat, width, height, format); + } + + private static DDSFile MakeWithMipMapsFrom32bitRGBA(byte[] rawData, DXTType DXTCFormat, int width, int height, SquishFlags format) + { + int mips = CalcMips(width, height); + byte[] data = new byte[CalcDataSize(DXTCFormat, width, height, mips)]; + int lastLocation = 0; + byte[] temp; + + byte[] map = SquishWrapper.SquishWrapper.CompressImage(rawData, width, height, (int)format); + map.CopyTo(data, 0); + lastLocation+= map.Length; + + if (mips > 0) + { + for (int i = 1; i < mips; i++) + { + double reduction = (double)Math.Pow(2, i); + int redWidth = (int)Math.Round(width / reduction); + int redHeight = (int)Math.Round(height / reduction); + map = new byte[redWidth * redHeight * 4]; + OpenILPort.Converter.Zoom(map, rawData, width, height, redWidth, redHeight, OpenILPort.Converter.Filter.Triangle, 1.0); + temp = SquishWrapper.SquishWrapper.CompressImage(map, redWidth, redHeight, (int)format); + temp.CopyTo(data, lastLocation); + lastLocation+= temp.Length; + } + } + + return MakeFromDDSCompressedImage(data, DXTCFormat, width, height); + } + + public static DDSFile MakeFromDDSCompressedImage(byte[] rawData, DXTType DXTCFormat, int width, int height) + { + return new DDSFile(rawData, width, height, DXTCFormat); + } + } +}