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);
+		}
+	}
+}