public WTPFile(string filename, ChunkyStructureCollection col) : base(filename, col) { ChunkyFolder folder = (ChunkyFolder)col[0].RootChunks[0]; int children = folder.Children.Count; ChunkyChunk chunk = null; ChunkyDataINFOTPAT info = null; for (int i = 0; i < children; i++) { chunk = folder.Children[i]; if (chunk is ChunkyDataINFOTPAT) { info = (ChunkyDataINFOTPAT)chunk; width = info.Width; height = info.Height; } } }
public ChunkyFolder(string ID_in, int version_in, string name_in, byte[] innerData) : base(ChunkyChunkType.Folder, ID_in, version_in, name_in) { children = new ChunkyCollection(this); MemoryStream ms = new MemoryStream(innerData, false); BinaryReader br = new BinaryReader(ms); ChunkyChunk chunk = null; ChunkyDataATTR attr = null; ChunkyDataINFOTPAT info = null; int pos = 0; while (pos < innerData.Length) { br.BaseStream.Seek(pos, SeekOrigin.Begin); chunk = RelicChunkReader.ReadChunkyChunk(br.ReadBytes(innerData.Length - pos), ID_in); children.Add(chunk); if (chunk is ChunkyDataATTR) { attr = (ChunkyDataATTR)chunk; } else if (chunk is ChunkyDataINFOTPAT) { info = (ChunkyDataINFOTPAT)chunk; } else if (attr != null && chunk is ChunkyDataDATA) { ((ChunkyDataDATA)chunk).Attributes = attr; } else if (info != null && chunk is ChunkyDataLayer) { ((ChunkyDataLayer)chunk).Info = info; } pos += chunk.Length; } }
public byte[] CreateCompositeTGABytes(LayerCollection colours, string badgePath, string bannerPath) { if (colours[PTLD_Layers.Dirt].Length != 3) { throw new InvalidOperationException("LayerCollection 'colours' must contain RGB colour data in a 3-byte array"); } FileInfo file = null; BinaryReader br = null; byte[] badge = new byte[64 * 64 * 4]; byte[] banner = new byte[64 * 96 * 4]; byte[] temp; CompilationEvent("Loading badge"); if (File.Exists(badgePath)) { file = new FileInfo(badgePath); br = new BinaryReader(file.OpenRead()); temp = br.ReadBytes((int)file.Length); br.Close(); if ((temp[12] + (temp[13] << 8)) != 64 || (temp[14] + (temp[15] << 8)) != 64) { CompilationEvent("Invalid badge image - badge must be a 64x64 pixel 24/32-bit TGA image", true); } else if (!((temp[16] == 32 || temp[16] == 24) && temp[2] == 2)) { CompilationEvent("Invalid badge image - badge must be a 64x64 pixel 24/32-bit TGA image", true); } else { Buffer.BlockCopy(ImageConverter.TGAto32bitTGA(temp), 18, badge, 0, badge.Length); } } else { CompilationEvent("Invalid badge path - file must exist. Using blank badge.", true); } CompilationEvent("Loading banner"); if (File.Exists(bannerPath)) { file = new FileInfo(bannerPath); br = new BinaryReader(file.OpenRead()); temp = br.ReadBytes((int)file.Length); br.Close(); if ((temp[12] + (temp[13] << 8)) != 64 || (temp[14] + (temp[15] << 8)) != 96) { CompilationEvent("Invalid banner image - banner must be a 64x96 pixel 24/32-bit TGA image", true); } else if (!((temp[16] == 32 || temp[16] == 24) && temp[2] == 2)) { CompilationEvent("Invalid banner image - banner must be a 64x64 pixel 24/32-bit TGA image", true); } else { Buffer.BlockCopy(ImageConverter.TGAto32bitTGA(temp), 18, banner, 0, banner.Length); } } else { CompilationEvent("Invalid banner path - file must exist. Using blank badge.", true); } ChunkyFolder root = (ChunkyFolder)this.ChunkyStructures[0].RootChunks[0]; ChunkyChunk chunk = null; ChunkyDataPTLD ptld = null; ChunkyDataPTBN bannerLayer = null; ChunkyDataPTBD badgeLayer = null; ChunkyDataINFOTPAT info = (ChunkyDataINFOTPAT)root.Children[0]; LayerCollection layers = new LayerCollection(info.Width * info.Height); byte[] mainImage = new byte[info.Width * info.Height]; int badge_bottom = int.MaxValue; int badge_top = int.MaxValue; int badge_left = int.MaxValue; int badge_right = int.MaxValue; int banner_bottom = int.MaxValue; int banner_top = int.MaxValue; int banner_left = int.MaxValue; int banner_right = int.MaxValue; CompilationEvent("Loading colour layers"); for (int i = 0; i < root.Children.Count; i++) { chunk = root.Children[i]; if (chunk is ChunkyDataPTLD) { ptld = (ChunkyDataPTLD)root.Children[i]; layers[(int)ptld.Layer] = ptld.GetColourBytes(); } else if (chunk is ChunkyDataPTBD) { badgeLayer = (ChunkyDataPTBD)chunk; badge_bottom = (int)badgeLayer.Pos_y; badge_top = badge_bottom + (int)badgeLayer.Height; badge_left = (int)badgeLayer.Pos_x; badge_right = badge_left + (int)badgeLayer.Width; } else if (chunk is ChunkyDataPTBN) { bannerLayer = (ChunkyDataPTBN)chunk; banner_bottom = (int)bannerLayer.Pos_y; banner_top = banner_bottom + (int)bannerLayer.Height; banner_left = (int)bannerLayer.Pos_x; banner_right = banner_left + (int)bannerLayer.Width; } else if (chunk is ChunkyFolder) { mainImage = ((ChunkyData)((ChunkyFolder)chunk).Children[1]).GetDataBytes(); } } int bytePos = 0; int bytePos32bit = 0; int bytePosBadge = 0; int bytePosBanner = 0; byte[] badgeByte; byte[] bannerByte; double ratio; double ratio2; double ratio3; double ratioTC; double tempByte = 0; double extra = 0; int badge_width = 0; if (badgeLayer != null) { badge_width = (int)badgeLayer.Width; } int banner_width = 0; if (bannerLayer != null) { banner_width = (int)bannerLayer.Width; } CompilationEvent("Compiling TGA"); for (int i = 0; i < info.Height; i++) { for (int j = 0; j < info.Width; j++) { bytePos = (i * info.Width) + j; bytePos32bit = bytePos * 4; ratio = layers[PTLD_Layers.Dirt][bytePos] / 255.0; if (badge_left <= j && badge_right > j && badge_bottom <= i && badge_top > i) { bytePosBadge = ((i - badge_bottom) * badge_width + (j - badge_left)) * 4; ratio2 = (badge[bytePosBadge + 3] / 255.0); badgeByte = new byte[] { badge[bytePosBadge], badge[bytePosBadge + 1], badge[bytePosBadge + 2] }; } else { ratio2 = 0; badgeByte = new byte[3]; } if (banner_left <= j && banner_right > j && banner_bottom <= i && banner_top > i) { bytePosBanner = ((i - banner_bottom) * banner_width + (j - banner_left)) * 4; ratio3 = (banner[bytePosBanner + 3] / 255.0); bannerByte = new byte[] { banner[bytePosBanner], banner[bytePosBanner + 1], banner[bytePosBanner + 2] }; } else { ratio3 = 0; bannerByte = new byte[3]; } ratioTC = 1 - ratio; ratio2 = ratioTC * ratio2; ratio3 = ratioTC * ratio3; ratioTC = (ratioTC - ratio2 - ratio3) * 2; extra = 0; //TGA files run in reverse - little-endian ARGB, which ends up as BGRA in the file //red tempByte = (ratio * mainImage[bytePos32bit + 2]) + (ratioTC) * ((colours[PTLD_Layers.Primary][0] * layers[PTLD_Layers.Primary][bytePos] / 255.0) + (colours[PTLD_Layers.Secondary][0] * layers[PTLD_Layers.Secondary][bytePos] / 255.0) + (colours[PTLD_Layers.Weapon][0] * layers[PTLD_Layers.Weapon][bytePos] / 255.0) + (colours[PTLD_Layers.Trim][0] * layers[PTLD_Layers.Trim][bytePos] / 255.0) + (colours[PTLD_Layers.Eyes][0] * layers[PTLD_Layers.Eyes][bytePos] / 255.0)) + ratio2 * badgeByte[2] + ratio3 * bannerByte[2]; if (tempByte > byte.MaxValue) { //CompilationEvent("Colour overflow at X:"+j.ToString()+", Y:"+i.ToString()+". Colour will show as Magenta or other bright colour with some colour schemes.", true); mainImage[bytePos32bit + 2] = byte.MaxValue; extra = (tempByte - byte.MaxValue); } else { mainImage[bytePos32bit + 2] = (byte)tempByte; } //green tempByte = (ratio * mainImage[bytePos32bit + 1]) + (ratioTC) * ((colours[PTLD_Layers.Primary][1] * layers[PTLD_Layers.Primary][bytePos] / 255.0) + (colours[PTLD_Layers.Secondary][1] * layers[PTLD_Layers.Secondary][bytePos] / 255.0) + (colours[PTLD_Layers.Weapon][1] * layers[PTLD_Layers.Weapon][bytePos] / 255.0) + (colours[PTLD_Layers.Trim][1] * layers[PTLD_Layers.Trim][bytePos] / 255.0) + (colours[PTLD_Layers.Eyes][1] * layers[PTLD_Layers.Eyes][bytePos] / 255.0)) + extra + ratio2 * badgeByte[1] + ratio3 * bannerByte[1]; if (tempByte > byte.MaxValue) { //CompilationEvent("Colour overflow at X:"+j.ToString()+", Y:"+i.ToString()+". Colour will show as Magenta or other bright colour with some colour schemes.", true); mainImage[bytePos32bit + 1] = byte.MaxValue; extra = extra + tempByte - byte.MaxValue; tempByte = mainImage[bytePos32bit + 2] + extra; if (tempByte > byte.MaxValue) { tempByte = byte.MaxValue; } mainImage[bytePos32bit + 2] = (byte)tempByte; } else { mainImage[bytePos32bit + 1] = (byte)tempByte; } //blue tempByte = (ratio * mainImage[bytePos32bit]) + (ratioTC) * ((colours[PTLD_Layers.Primary][2] * layers[PTLD_Layers.Primary][bytePos] / 255.0) + (colours[PTLD_Layers.Secondary][2] * layers[PTLD_Layers.Secondary][bytePos] / 255.0) + (colours[PTLD_Layers.Weapon][2] * layers[PTLD_Layers.Weapon][bytePos] / 255.0) + (colours[PTLD_Layers.Trim][2] * layers[PTLD_Layers.Trim][bytePos] / 255.0) + (colours[PTLD_Layers.Eyes][2] * layers[PTLD_Layers.Eyes][bytePos] / 255.0)) + extra + ratio2 * badgeByte[0] + ratio3 * bannerByte[0]; if (tempByte > byte.MaxValue) { //CompilationEvent("Colour overflow at X:"+j.ToString()+", Y:"+i.ToString()+". Colour will show as Magenta or other bright colour with some colour schemes.", true); mainImage[bytePos32bit] = byte.MaxValue; extra = extra + tempByte - byte.MaxValue; tempByte = mainImage[bytePos32bit + 2] + extra; if (tempByte > byte.MaxValue) { tempByte = byte.MaxValue; } mainImage[bytePos32bit + 2] = (byte)tempByte; tempByte = mainImage[bytePos32bit + 1] + extra; if (tempByte > byte.MaxValue) { tempByte = byte.MaxValue; } mainImage[bytePos32bit + 1] = (byte)tempByte; } else { mainImage[bytePos32bit] = (byte)tempByte; } } } return(mainImage); }