changeset 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
files AssemblyInfo.cs Converter.cs DDSFile.cs IBBoard.Graphics.csproj IBBoard.Graphics.csproj.user IBBoard.Graphics.mdp IBBoard.Graphics.pidb IconLoader.cs test.rb
diffstat 9 files changed, 1347 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AssemblyInfo.cs	Fri Dec 19 11:13:48 2008 +0000
@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Converter.cs	Fri Dec 19 11:13:48 2008 +0000
@@ -0,0 +1,281 @@
+using System;
+using System.Drawing;
+using System.IO;
+using System.Collections;
+using IBBoard.IO;
+
+namespace IBBoard.Graphics
+{
+	/// <summary>
+	/// Summary description for Converter.
+	/// </summary>
+	public class Converter
+	{
+		public struct MapEncStruct
+		{
+			public bool isMapped, isEncoded;
+			public string formatType;
+
+			public MapEncStruct(string type, bool mapped, bool encoded)
+			{
+				formatType = type;
+				isMapped = mapped;
+				isEncoded = encoded;
+			}
+		}
+
+		private static ArrayList mapEncStructs;
+
+		static Converter()
+		{
+			mapEncStructs = new ArrayList(12);
+			mapEncStructs.Insert(0, new MapEncStruct("No Image", false, false));
+			mapEncStructs.Insert(1, new MapEncStruct("Colourmapped", true, false));
+			mapEncStructs.Insert(2, new MapEncStruct("Truecolour", false, false));
+			mapEncStructs.Insert(3, new MapEncStruct("Monochrome", false, false));
+			mapEncStructs.Insert(4, null);
+			mapEncStructs.Insert(5, null);
+			mapEncStructs.Insert(6, null);
+			mapEncStructs.Insert(7, null);
+			mapEncStructs.Insert(8, null);
+			mapEncStructs.Insert(9, new MapEncStruct("Colourmapped", true, true));
+			mapEncStructs.Insert(10, new MapEncStruct("Truecolour", false, true));
+			mapEncStructs.Insert(11, new MapEncStruct("Monochrome", false, true));
+		}
+
+		public static MapEncStruct getMapEncStruct(byte id)
+		{
+			return (MapEncStruct)mapEncStructs[id];
+		}
+		
+		public static readonly byte[] TGA_Colour_Header = new byte[]{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08};
+		public static readonly byte[] TGA_Greyscale_Header = new byte[]{0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08};
+
+		public static uint rgb565_to_rgba(ushort color) 
+		{
+			uint red, green, blue;
+			red = ((uint)(color & 0xf800))>>11;
+			red = ((red * 255) / 31)<<16;
+			green = ((uint)(color & 0x07e0))>>5;
+			green = ((green * 255) / 63)<<8;
+			blue = ((uint)(color & 0x001f) * 255) / 31;
+
+			return red | green | blue | (uint)0xff000000;
+		}
+
+
+		public static void TGAtoDDS(IntPtr handle, byte[] tgaFile, string filename)
+		{
+			FlipTGAbytes(ref tgaFile);
+
+			//DirectXWrapper.ImageConverter.TGAtoDDS(handle, tgaFile, filename);
+		}
+
+		public static Bitmap TGAtoBMP(string tgaPath, Color colour)
+		{
+			FileStream fs = null;
+			try
+			{
+				fs = new FileStream(tgaPath, FileMode.Open);
+				byte[] tgaFile = new byte[fs.Length];
+				fs.Read(tgaFile, 0, (int)fs.Length);
+
+				if (tgaFile[2]!=0x02)
+				{
+					throw new InvalidOperationException("Image must be a 32-bit TGA");
+				}
+
+				bool hasAlpha = true;
+
+				if (tgaFile[16]!=0x20)
+				{
+					if (tgaFile[16]==0x18)
+					{
+						hasAlpha = false;
+					}
+					else
+					{
+						throw new InvalidOperationException("Image must be a 32-bit TGA");
+					}
+				}
+
+				FlipTGAbytes(ref tgaFile);
+				byte[] data;
+				int last = 0;
+				
+				if (hasAlpha)
+				{
+					data = new byte[(((tgaFile.Length-18-tgaFile[0])/4)*3)+54];
+					last = tgaFile.Length-4;
+				}
+				else
+				{
+					data = new byte[tgaFile.Length-18-tgaFile[0]+54];
+					last = tgaFile.Length;
+				}
+
+				byte[] bmpHeader = new byte[]{0x42, 0x4D, (byte)data.Length, (byte)(data.Length>>8), (byte)(data.Length>>16), (byte)(data.Length>>24), 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, tgaFile[12], tgaFile[13], 0x00, 0x00, tgaFile[14], tgaFile[15], 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+				bmpHeader.CopyTo(data, 0);
+
+				int pos = 54;
+				double alpha;
+
+				if (hasAlpha)
+				{
+					for (int i = 18+tgaFile[0]; i<last; i=i+4)
+					{
+						alpha = tgaFile[i+3]/255.0;
+						data[pos] = (byte)((tgaFile[i] * alpha) + (colour.B * (1-alpha)));
+						pos++;
+						data[pos] = (byte)((tgaFile[i+1] * alpha) + (colour.G * (1-alpha)));
+						pos++;
+						data[pos] = (byte)((tgaFile[i+2] * alpha) + (colour.R * (1-alpha)));
+						pos++;
+					}
+				}
+				else
+				{
+					for (int i = 18+tgaFile[0]; i<last; i++)
+					{
+						data[pos++] = tgaFile[i];
+					}
+				}
+
+				MemoryStream stream = new MemoryStream(data);
+
+				return new Bitmap(stream);
+			}
+			finally
+			{
+				if (fs!=null)
+				{
+					fs.Close();
+				}
+			}
+		}
+
+		public static void FlipTGAbytes(ref byte[] file)
+		{
+			int idLength, width, height, byteWidth, halfHeight, topIndex, bottomIndex;
+			byte temp;
+
+			idLength = file[0];
+			width = file[12]+(file[13]<<8);
+			height = file[14]+(file[15]<<8);
+			
+			byteWidth = width*(file[16]/8);
+			halfHeight = height/2;
+
+			for (int row = height-1; row>=halfHeight; row--)
+			{
+				for (int col = 0; col<byteWidth; col++)
+				{
+					topIndex = (height - row -1)*byteWidth + col + 18 + idLength;
+					bottomIndex = row*byteWidth + col + 18 + idLength;
+					temp = file[topIndex];
+					file[topIndex] = file[bottomIndex];
+					file[bottomIndex] = temp;
+				}
+			}
+		}
+
+		public static byte[] ColourMapToGreyscale(byte[] file)
+		{
+			int idLength, width, height, cmapLength, cmapStart, dataLength, offset, pos;
+			byte colourBytes, cmapDepth;
+			byte[] colourMap;
+			byte[] data;
+
+			idLength = file[0];
+			width = file[12]+(file[13]<<8);
+			height = file[14]+(file[15]<<8);
+
+			cmapStart = file[3]+(file[4]<<8);
+			cmapLength = file[5]+(file[6]<<8);
+			cmapDepth = file[7];
+			colourBytes = (byte)(cmapDepth/8);
+
+			colourMap = new byte[cmapLength];
+
+			dataLength = height*width;
+
+			data = new byte[18+dataLength];
+
+			offset = idLength+cmapLength*colourBytes;
+
+			TGA_Greyscale_Header.CopyTo(data, 0);
+
+			data[12] = file[12];
+			data[13] = file[13];
+			data[14] = file[14];
+			data[15] = file[15];
+
+			pos = idLength+18;
+
+			for (int i = 0; i<cmapLength; i++)
+			{
+				for (int j = 1; j<colourBytes; j++)
+				{
+					if (file[pos]!=file[pos+j])
+					{
+						throw new InvalidOperationException("Conversion to greyscale failed - image must use a greyscale colour map.");
+					}
+				}
+
+				colourMap[i] = file[pos];
+				pos+=colourBytes;
+			}
+			
+			for (int i = 18; i<dataLength; i++)
+			{
+				data[i] = colourMap[file[i+offset]];
+			}
+
+			return data;
+		}
+
+		public static byte[] TGAto32bitTGA(byte[] file)
+		{
+			if (file[2]!=2)
+			{
+				throw new UnsupportedFileTypeException("non-true colour, unencoded, unmapped TGA", "TGAto32BitTGA");
+			}
+
+			if (file[16]==32)
+			{
+				return file;
+			}
+			else if (file[16]==24)
+			{
+				int imagesize = (file[12]+(file[13]<<8))*(file[14]+(file[15]<<8));
+				int imagebytes = imagesize*3;
+				byte[] converted = new byte[imagesize*4+18];
+
+				//leave index 0 as 0 so it has 0 length ID
+				for (int i = 1; i<18; i++)
+				{
+					converted[i] = file[i];
+				}
+
+				converted[16] = 32;
+
+				int idLength = file[0];
+				int lastIndex = imagebytes+18;
+
+				for (int i = 18, pos = 18; i<lastIndex; i+=3, pos+=4)
+				{
+					converted[pos] = file[i+idLength];
+					converted[pos+1] = file[i+1+idLength];
+					converted[pos+2] = file[i+2+idLength];
+					converted[pos+3] = byte.MaxValue;
+				}
+
+				return converted;
+			}
+			else
+			{
+				throw new UnsupportedFileTypeException("true colour, encoded or mapped TGA", "TGAto32BitTGA");
+			}
+		}
+	}
+}
--- /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);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IBBoard.Graphics.csproj	Fri Dec 19 11:13:48 2008 +0000
@@ -0,0 +1,126 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ProjectType>Local</ProjectType>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{7CCF5C77-6038-45DE-BFA7-1A5378B3E08B}</ProjectGuid>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ApplicationIcon>
+    </ApplicationIcon>
+    <AssemblyKeyContainerName>
+    </AssemblyKeyContainerName>
+    <AssemblyName>IBBoard.Graphics</AssemblyName>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+    <DefaultClientScript>JScript</DefaultClientScript>
+    <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
+    <DefaultTargetSchema>IE50</DefaultTargetSchema>
+    <DelaySign>false</DelaySign>
+    <OutputType>Library</OutputType>
+    <RootNamespace>IBBoard.Graphics</RootNamespace>
+    <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
+    <StartupObject>
+    </StartupObject>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <OutputPath>C:\Documents and Settings\ibboard\My Documents\Visual Studio 2005\Projects\IBBoardGraphics\bin\Debug\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile>
+    </ConfigurationOverrideFile>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <DebugSymbols>true</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>
+    </NoWarn>
+    <Optimize>false</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>full</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <OutputPath>bin\Release\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile>
+    </ConfigurationOverrideFile>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <DebugSymbols>false</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>
+    </NoWarn>
+    <Optimize>true</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>none</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System">
+      <Name>System</Name>
+    </Reference>
+    <Reference Include="System.Data">
+      <Name>System.Data</Name>
+    </Reference>
+    <Reference Include="System.Drawing">
+      <Name>System.Drawing</Name>
+    </Reference>
+    <Reference Include="System.XML">
+      <Name>System.XML</Name>
+    </Reference>
+    <ProjectReference Include="..\IBBoard.Graphics.OpenILPort\IBBoard.Graphics.OpenILPort.csproj">
+      <Name>IBBoard.Graphics.OpenILPort</Name>
+      <Project>{DC228FE8-B0D1-4CE8-869D-404B9173AA58}</Project>
+      <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
+    </ProjectReference>
+    <ProjectReference Include="..\IBBoard\IBBoard.csproj">
+      <Name>IBBoard</Name>
+      <Project>{5DFD64F6-FC2B-4B4F-B92E-483BAC468105}</Project>
+      <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
+    </ProjectReference>
+    <ProjectReference Include="..\SquishWrapper\SquishWrapper.csproj">
+      <Name>SquishWrapper</Name>
+      <Project>{92658179-ABF8-4BEA-AF6A-DF4F7F64945E}</Project>
+      <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Converter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="DDSFile.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="IconLoader.cs">
+      <SubType>Code</SubType>
+    </Compile>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IBBoard.Graphics.csproj.user	Fri Dec 19 11:13:48 2008 +0000
@@ -0,0 +1,58 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <LastOpenVersion>7.10.3077</LastOpenVersion>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ReferencePath>
+    </ReferencePath>
+    <CopyProjectDestinationFolder>
+    </CopyProjectDestinationFolder>
+    <CopyProjectUncPath>
+    </CopyProjectUncPath>
+    <CopyProjectOption>0</CopyProjectOption>
+    <ProjectView>ProjectFiles</ProjectView>
+    <ProjectTrust>0</ProjectTrust>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <EnableASPDebugging>false</EnableASPDebugging>
+    <EnableASPXDebugging>false</EnableASPXDebugging>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>
+    <RemoteDebugEnabled>false</RemoteDebugEnabled>
+    <RemoteDebugMachine>
+    </RemoteDebugMachine>
+    <StartAction>Project</StartAction>
+    <StartArguments>
+    </StartArguments>
+    <StartPage>
+    </StartPage>
+    <StartProgram>
+    </StartProgram>
+    <StartURL>
+    </StartURL>
+    <StartWorkingDirectory>
+    </StartWorkingDirectory>
+    <StartWithIE>true</StartWithIE>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <EnableASPDebugging>false</EnableASPDebugging>
+    <EnableASPXDebugging>false</EnableASPXDebugging>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>
+    <RemoteDebugEnabled>false</RemoteDebugEnabled>
+    <RemoteDebugMachine>
+    </RemoteDebugMachine>
+    <StartAction>Project</StartAction>
+    <StartArguments>
+    </StartArguments>
+    <StartPage>
+    </StartPage>
+    <StartProgram>
+    </StartProgram>
+    <StartURL>
+    </StartURL>
+    <StartWorkingDirectory>
+    </StartWorkingDirectory>
+    <StartWithIE>true</StartWithIE>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IBBoard.Graphics.mdp	Fri Dec 19 11:13:48 2008 +0000
@@ -0,0 +1,31 @@
+<Project name="IBBoard.Graphics" fileversion="2.0" DefaultNamespace="IBBoard.Graphics" language="C#" clr-version="Net_1_1" ctype="DotNetProject">
+  <Configurations active="Debug">
+    <Configuration name="Debug" ctype="DotNetProjectConfiguration">
+      <Output directory="bin/Debug/" assembly="IBBoard.Graphics" />
+      <Build debugmode="True" target="Library" />
+      <Execution runwithwarnings="False" consolepause="True" runtime="MsNet" clr-version="Net_1_1" />
+      <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
+    </Configuration>
+    <Configuration name="Release" ctype="DotNetProjectConfiguration">
+      <Output directory="bin/Release/" assembly="IBBoard.Graphics" />
+      <Build debugmode="False" target="Library" />
+      <Execution runwithwarnings="False" consolepause="True" runtime="MsNet" clr-version="Net_1_1" />
+      <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
+    </Configuration>
+  </Configurations>
+  <Contents>
+    <File name="AssemblyInfo.cs" subtype="Code" buildaction="Compile" />
+    <File name="Converter.cs" subtype="Code" buildaction="Compile" />
+    <File name="DDSFile.cs" subtype="Code" buildaction="Compile" />
+    <File name="IconLoader.cs" subtype="Code" buildaction="Compile" />
+  </Contents>
+  <References>
+    <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+    <ProjectReference type="Gac" localcopy="True" refto="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+    <ProjectReference type="Gac" localcopy="True" refto="System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+    <ProjectReference type="Project" localcopy="True" refto="IBBoard" />
+    <ProjectReference type="Project" localcopy="True" refto="SquishWrapper" />
+    <ProjectReference type="Gac" localcopy="True" refto="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+    <ProjectReference type="Project" localcopy="True" refto="IBBoard.Graphics.OpenILPort" />
+  </References>
+</Project>
\ No newline at end of file
Binary file IBBoard.Graphics.pidb has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IconLoader.cs	Fri Dec 19 11:13:48 2008 +0000
@@ -0,0 +1,242 @@
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Data;
+using System.Runtime.InteropServices;
+
+namespace IBBoard.Graphics
+{
+	/// <summary>
+	/// Provides static methods to read system icons for both folders and files.
+	/// </summary>
+	/// <example>
+	/// <code>IconReader.GetFileIcon("c:\\general.xls");</code>
+	/// </example>
+	public class IconReader
+	{
+		/// <summary>
+		/// Options to specify the size of icons to return.
+		/// </summary>
+		public enum IconSize
+		{
+			/// <summary>
+			/// Specify large icon - 32 pixels by 32 pixels.
+			/// </summary>
+			Large = 0,
+			/// <summary>
+			/// Specify small icon - 16 pixels by 16 pixels.
+			/// </summary>
+			Small = 1
+		}
+        
+		/// <summary>
+		/// Options to specify whether folders should be in the open or closed state.
+		/// </summary>
+		public enum FolderType
+		{
+			/// <summary>
+			/// Specify open folder.
+			/// </summary>
+			Open = 0,
+			/// <summary>
+			/// Specify closed folder.
+			/// </summary>
+			Closed = 1
+		}
+
+		/// <summary>
+		/// Returns an icon for a given file - indicated by the name parameter.
+		/// </summary>
+		/// <param name="name">Pathname for file.</param>
+		/// <param name="size">Large or small</param>
+		/// <param name="linkOverlay">Whether to include the link icon</param>
+		/// <returns>System.Drawing.Icon</returns>
+		public static System.Drawing.Icon GetFileIcon(string name, IconSize size, bool linkOverlay)
+		{
+			Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
+			uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;
+
+			if (true == linkOverlay) flags += Shell32.SHGFI_LINKOVERLAY;
+
+			/* Check the size specified for return. */
+			if (IconSize.Small == size)
+			{
+				flags += Shell32.SHGFI_SMALLICON ;
+			} 
+			else 
+			{
+				flags += Shell32.SHGFI_LARGEICON ;
+			}
+
+			Shell32.SHGetFileInfo(	name, 
+				Shell32.FILE_ATTRIBUTE_NORMAL, 
+				ref shfi, 
+				(uint) System.Runtime.InteropServices.Marshal.SizeOf(shfi), 
+				flags );
+
+			// Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly
+			System.Drawing.Icon icon = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
+			User32.DestroyIcon( shfi.hIcon );		// Cleanup
+			return icon;
+		}
+
+		/// <summary>
+		/// Used to access system folder icons.
+		/// </summary>
+		/// <param name="size">Specify large or small icons.</param>
+		/// <param name="folderType">Specify open or closed FolderType.</param>
+		/// <returns>System.Drawing.Icon</returns>
+		public static System.Drawing.Icon GetFolderIcon( IconSize size, FolderType folderType )
+		{
+			// Need to add size check, although errors generated at present!
+			uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;
+
+			if (FolderType.Open == folderType)
+			{
+				flags += Shell32.SHGFI_OPENICON;
+			}
+			
+			if (IconSize.Small == size)
+			{
+				flags += Shell32.SHGFI_SMALLICON;
+			} 
+			else 
+			{
+				flags += Shell32.SHGFI_LARGEICON;
+			}
+
+			// Get the folder icon
+			Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
+			Shell32.SHGetFileInfo(	null, 
+				Shell32.FILE_ATTRIBUTE_DIRECTORY, 
+				ref shfi, 
+				(uint) System.Runtime.InteropServices.Marshal.SizeOf(shfi), 
+				flags );
+
+			System.Drawing.Icon.FromHandle(shfi.hIcon);	// Load the icon from an HICON handle
+
+			// Now clone the icon, so that it can be successfully stored in an ImageList
+			System.Drawing.Icon icon = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
+
+			User32.DestroyIcon( shfi.hIcon );		// Cleanup
+			return icon;
+		}	
+	}
+
+	/// <summary>
+	/// Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code
+	/// courtesy of MSDN Cold Rooster Consulting case study.
+	/// </summary>
+	/// 
+
+	// This code has been left largely untouched from that in the CRC example. The main changes have been moving
+	// the icon reading code over to the IconReader type.
+	public class Shell32  
+	{
+		
+		public const int 	MAX_PATH = 256;
+		[StructLayout(LayoutKind.Sequential)]
+			public struct SHITEMID
+		{
+			public ushort cb;
+			[MarshalAs(UnmanagedType.LPArray)]
+			public byte[] abID;
+		}
+
+		[StructLayout(LayoutKind.Sequential)]
+			public struct ITEMIDLIST
+		{
+			public SHITEMID mkid;
+		}
+
+		[StructLayout(LayoutKind.Sequential)]
+			public struct BROWSEINFO 
+		{ 
+			public IntPtr		hwndOwner; 
+			public IntPtr		pidlRoot; 
+			public IntPtr 		pszDisplayName;
+			[MarshalAs(UnmanagedType.LPTStr)] 
+			public string 		lpszTitle; 
+			public uint 		ulFlags; 
+			public IntPtr		lpfn; 
+			public int			lParam; 
+			public IntPtr 		iImage; 
+		} 
+
+		// Browsing for directory.
+		public const uint BIF_RETURNONLYFSDIRS   =	0x0001;
+		public const uint BIF_DONTGOBELOWDOMAIN  =	0x0002;
+		public const uint BIF_STATUSTEXT         =	0x0004;
+		public const uint BIF_RETURNFSANCESTORS  =	0x0008;
+		public const uint BIF_EDITBOX            =	0x0010;
+		public const uint BIF_VALIDATE           =	0x0020;
+		public const uint BIF_NEWDIALOGSTYLE     =	0x0040;
+		public const uint BIF_USENEWUI           =	(BIF_NEWDIALOGSTYLE | BIF_EDITBOX);
+		public const uint BIF_BROWSEINCLUDEURLS  =	0x0080;
+		public const uint BIF_BROWSEFORCOMPUTER  =	0x1000;
+		public const uint BIF_BROWSEFORPRINTER   =	0x2000;
+		public const uint BIF_BROWSEINCLUDEFILES =	0x4000;
+		public const uint BIF_SHAREABLE          =	0x8000;
+
+		[StructLayout(LayoutKind.Sequential)]
+			public struct SHFILEINFO
+		{ 
+			public const int NAMESIZE = 80;
+			public IntPtr	hIcon; 
+			public int		iIcon; 
+			public uint	dwAttributes; 
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
+			public string szDisplayName; 
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst=NAMESIZE)]
+			public string szTypeName; 
+		};
+
+		public const uint SHGFI_ICON				= 0x000000100;     // get icon
+		public const uint SHGFI_DISPLAYNAME			= 0x000000200;     // get display name
+		public const uint SHGFI_TYPENAME          	= 0x000000400;     // get type name
+		public const uint SHGFI_ATTRIBUTES        	= 0x000000800;     // get attributes
+		public const uint SHGFI_ICONLOCATION      	= 0x000001000;     // get icon location
+		public const uint SHGFI_EXETYPE           	= 0x000002000;     // return exe type
+		public const uint SHGFI_SYSICONINDEX      	= 0x000004000;     // get system icon index
+		public const uint SHGFI_LINKOVERLAY       	= 0x000008000;     // put a link overlay on icon
+		public const uint SHGFI_SELECTED          	= 0x000010000;     // show icon in selected state
+		public const uint SHGFI_ATTR_SPECIFIED    	= 0x000020000;     // get only specified attributes
+		public const uint SHGFI_LARGEICON         	= 0x000000000;     // get large icon
+		public const uint SHGFI_SMALLICON         	= 0x000000001;     // get small icon
+		public const uint SHGFI_OPENICON          	= 0x000000002;     // get open icon
+		public const uint SHGFI_SHELLICONSIZE     	= 0x000000004;     // get shell size icon
+		public const uint SHGFI_PIDL              	= 0x000000008;     // pszPath is a pidl
+		public const uint SHGFI_USEFILEATTRIBUTES 	= 0x000000010;     // use passed dwFileAttribute
+		public const uint SHGFI_ADDOVERLAYS       	= 0x000000020;     // apply the appropriate overlays
+		public const uint SHGFI_OVERLAYINDEX      	= 0x000000040;     // Get the index of the overlay
+
+		public const uint FILE_ATTRIBUTE_DIRECTORY  = 0x00000010;  
+		public const uint FILE_ATTRIBUTE_NORMAL     = 0x00000080;  
+
+		[DllImport("Shell32.dll")]
+		public static extern IntPtr SHGetFileInfo(
+			string pszPath,
+			uint dwFileAttributes,
+			ref SHFILEINFO psfi,
+			uint cbFileInfo,
+			uint uFlags
+			);
+	}
+
+	/// <summary>
+	/// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example.
+	/// </summary>
+	public class User32
+	{
+		/// <summary>
+		/// Provides access to function required to delete handle. This method is used internally
+		/// and is not required to be called separately.
+		/// </summary>
+		/// <param name="hIcon">Pointer to icon handle.</param>
+		/// <returns>N/A</returns>
+		[DllImport("User32.dll")]
+		public static extern int DestroyIcon( IntPtr hIcon );
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test.rb	Fri Dec 19 11:13:48 2008 +0000
@@ -0,0 +1,1 @@
+/bin/env ruby