Mercurial > repos > IBBoard.Graphics
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
--- /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 ); + } +} +