// Create the template images from the full textures. // Uses extracted 'Medal_Ranked_X.dds' textures from // 'textures0.unity3d' and 'shared0.unity3d' public static void Create(string inDir, string outDir) { if (Directory.Exists(inDir) == false) { return; } if (Directory.Exists(outDir) == false) { Directory.CreateDirectory(outDir); } var files = Directory.GetFiles(inDir); foreach (var f in files) { // texture files are named 'Medal_Ranked_X.dds' Regex re = new Regex(@"Ranked_(\d+)\.dds"); Match m = re.Match(f); if (m.Success) { var rank = m.Groups[1].Captures[0].Value; byte[] data = File.ReadAllBytes(f); // convert the dds file to bitmap Bitmap bmp = DDSReader.LoadImage(data); // need flip HS textures bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); // resize to 70x70 Bitmap scaled = new Bitmap(bmp, new System.Drawing.Size(70, 70)); // crop at (23,23) size 24x24 Rectangle cropRect = new Rectangle(23, 23, 24, 24); // set output bitmap to 24bpp (for Aforge) Bitmap target = new Bitmap(cropRect.Width, cropRect.Height, PixelFormat.Format24bppRgb); using (Graphics g = Graphics.FromImage(target)) { // set graphic quality settings g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.SmoothingMode = SmoothingMode.HighQuality; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.CompositingQuality = CompositingQuality.HighQuality; g.DrawImage(scaled, new Rectangle(0, 0, target.Width, target.Height), cropRect, GraphicsUnit.Pixel); } // save template to output directory as bitmap target.Save(Path.Combine(outDir, rank + ".bmp")); } } }
/* Replace an existing file in the TexturePAK archive */ public override PAKReturnType ReplaceFile(string PathToNewFile, string FileName) { try { //Get the texture entry & parse new DDS int EntryIndex = GetFileIndex(FileName); if (EntryIndex == -1) { return(PAKReturnType.FAIL_GENERAL_LOGIC_ERROR); //CHANGED FOR OPENCAGE } TEX4 TextureEntry = TextureEntries[EntryIndex]; DDSReader NewTexture = new DDSReader(PathToNewFile); //Currently we only apply the new texture to the "biggest", some have lower mips that we don't edit (TODO) TEX4_Part BiggestPart = TextureEntry.Texture_V2; if (BiggestPart.HeaderPos == -1 || !BiggestPart.Saved) { BiggestPart = TextureEntry.Texture_V1; } if (BiggestPart.HeaderPos == -1 || !BiggestPart.Saved) { return(PAKReturnType.FAIL_REQUEST_IS_UNSUPPORTED); //Shouldn't reach this. } //CATHODE seems to ignore texture header information regarding size, so as default, resize any imported textures to the original size. //An option is provided in the toolkit to write size information to the header (done above) however, so don't resize if that's the case. //More work needs to be done to figure out why CATHODE doesn't honour the header's size value. int OriginalLength = BiggestPart.Length; Array.Resize(ref NewTexture.DataBlock, OriginalLength); //Update our internal knowledge of the textures BiggestPart.Length = (int)NewTexture.DataBlock.Length; BiggestPart.Width = (Int16)NewTexture.Width; BiggestPart.Height = (Int16)NewTexture.Height; TextureEntry.Format = NewTexture.Format; //TODO: Update smallest here too if it exists! //Will need to be written into the PAK at "Pull PAK sections before/after V2" too - headers are handled already. //Load the BIN and write out updated BIN texture header BinaryWriter ArchiveFileBinWriter = new BinaryWriter(File.OpenWrite(FilePathBIN)); ExtraBinaryUtils BinaryUtils = new ExtraBinaryUtils(); ArchiveFileBinWriter.BaseStream.Position = TextureEntry.HeaderPos; BinaryUtils.WriteString(TextureEntry.Magic, ArchiveFileBinWriter); ArchiveFileBinWriter.Write(BitConverter.GetBytes((int)TextureEntry.Format)); ArchiveFileBinWriter.Write((TextureEntry.Texture_V2.Length == -1) ? 0 : TextureEntry.Texture_V2.Length); ArchiveFileBinWriter.Write(TextureEntry.Texture_V1.Length); ArchiveFileBinWriter.Write(TextureEntry.Texture_V1.Width); ArchiveFileBinWriter.Write(TextureEntry.Texture_V1.Height); ArchiveFileBinWriter.Write(TextureEntry.Unk_V1); ArchiveFileBinWriter.Write(TextureEntry.Texture_V2.Width); ArchiveFileBinWriter.Write(TextureEntry.Texture_V2.Height); ArchiveFileBinWriter.Write(TextureEntry.Unk_V2); ArchiveFileBinWriter.Write(TextureEntry.UnknownHeaderBytes); ArchiveFileBinWriter.Close(); //Update headers for V1+2 in PAK if they exist BinaryWriter ArchiveFileWriter = new BinaryWriter(File.OpenWrite(FilePathPAK)); BigEndianUtils BigEndian = new BigEndianUtils(); if (TextureEntry.Texture_V1.HeaderPos != -1) { ArchiveFileWriter.BaseStream.Position = TextureEntry.Texture_V1.HeaderPos; ArchiveFileWriter.Write(TextureEntry.Texture_V1.UnknownHeaderLead); ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V1.Length))); ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V1.Length))); ArchiveFileWriter.Write(TextureEntry.Texture_V1.UnknownHeaderTrail_1); ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes((Int16)EntryIndex))); ArchiveFileWriter.Write(TextureEntry.Texture_V1.UnknownHeaderTrail_2); } if (TextureEntry.Texture_V2.HeaderPos != -1) { ArchiveFileWriter.BaseStream.Position = TextureEntry.Texture_V2.HeaderPos; ArchiveFileWriter.Write(TextureEntry.Texture_V2.UnknownHeaderLead); ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V2.Length))); ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V2.Length))); ArchiveFileWriter.Write(TextureEntry.Texture_V2.UnknownHeaderTrail_1); ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes((Int16)EntryIndex))); ArchiveFileWriter.Write(TextureEntry.Texture_V2.UnknownHeaderTrail_2); } ArchiveFileWriter.Close(); //Pull PAK sections before/after V2 BinaryReader ArchiveFile = new BinaryReader(File.OpenRead(FilePathPAK)); byte[] PAK_Pt1 = ArchiveFile.ReadBytes(BiggestPart.StartPos); ArchiveFile.BaseStream.Position += OriginalLength; byte[] PAK_Pt2 = ArchiveFile.ReadBytes((int)ArchiveFile.BaseStream.Length - (int)ArchiveFile.BaseStream.Position); ArchiveFile.Close(); //Write the PAK back out with new content ArchiveFileWriter = new BinaryWriter(File.OpenWrite(FilePathPAK)); ArchiveFileWriter.BaseStream.SetLength(0); ArchiveFileWriter.Write(PAK_Pt1); ArchiveFileWriter.Write(NewTexture.DataBlock); ArchiveFileWriter.Write(PAK_Pt2); ArchiveFileWriter.Close(); return(PAKReturnType.SUCCESS); } catch (IOException) { return(PAKReturnType.FAIL_COULD_NOT_ACCESS_FILE); } catch (Exception) { return(PAKReturnType.FAIL_UNKNOWN); } }
/// <summary> /// Load texture from RAF. /// </summary> /// <param name="file">The file entry of the texture.</param> /// <param name="target">Only supports 2D.</param> /// <returns></returns> public bool Create(IFileEntry file, TextureTarget target, SupportedImageEncodings encoding, Logger logger) { bool result = true; this.target = target; // Hacky sanity check if (target != TextureTarget.Texture2D) { return(false); } GL.Enable(EnableCap.Texture2D); GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest); // Create a System.Drawing.Bitmap. Bitmap bitmap = null; if (encoding == SupportedImageEncodings.DDS) { // Special case. result = DDSReader.Read(file, ref bitmap, logger); } else { // Normal case. result = CreateBitmap(file.GetContent(), ref bitmap); } // Pass the Bitmap into OpenGL. if (result == true && bitmap != null) { result = CreateTexture(bitmap, target); } if (result == true) { // Set up texture parameters. GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (Int32)TextureEnvModeCombine.Modulate); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (Int32)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (Int32)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (Int32)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (Int32)TextureWrapMode.Repeat); } return(result); }