diff --git a/VTFXUtil/App.config b/VTFXUtil/App.config new file mode 100644 index 0000000..391cb86 --- /dev/null +++ b/VTFXUtil/App.config @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/VTFXUtil/Form1.Designer.cs b/VTFXUtil/Form1.Designer.cs new file mode 100644 index 0000000..a742b31 --- /dev/null +++ b/VTFXUtil/Form1.Designer.cs @@ -0,0 +1,286 @@ +namespace VTFXUtil +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); + this.helloWorldLabel = new System.Windows.Forms.Label(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.toolStripDropDownButton1 = new System.Windows.Forms.ToolStripDropDownButton(); + this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripDropDownButton2 = new System.Windows.Forms.ToolStripDropDownButton(); + this.saveVTFXInfoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.MonsieurResizer = new System.Windows.Forms.Panel(); + this.PreviewBox = new System.Windows.Forms.PictureBox(); + this.label1 = new System.Windows.Forms.Label(); + this.TxFmtLb = new System.Windows.Forms.Label(); + this.DimensionLb = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.ResTbl = new System.Windows.Forms.ListView(); + this.ResType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.ResOffset = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.toolStrip1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.MonsieurResizer.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PreviewBox)).BeginInit(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // helloWorldLabel + // + this.helloWorldLabel.AutoSize = true; + this.helloWorldLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 16F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.helloWorldLabel.Location = new System.Drawing.Point(115, 25); + this.helloWorldLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.helloWorldLabel.Name = "helloWorldLabel"; + this.helloWorldLabel.Size = new System.Drawing.Size(422, 26); + this.helloWorldLabel.TabIndex = 3; + this.helloWorldLabel.Text = "hello yes i am a program i convert textures"; + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripDropDownButton1, + this.toolStripDropDownButton2}); + this.toolStrip1.Location = new System.Drawing.Point(0, 0); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(1212, 25); + this.toolStrip1.TabIndex = 4; + this.toolStrip1.Text = "toolStrip1"; + // + // toolStripDropDownButton1 + // + this.toolStripDropDownButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripDropDownButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.openToolStripMenuItem, + this.importToolStripMenuItem, + this.exportToolStripMenuItem, + this.exitToolStripMenuItem}); + this.toolStripDropDownButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripDropDownButton1.Image"))); + this.toolStripDropDownButton1.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripDropDownButton1.Name = "toolStripDropDownButton1"; + this.toolStripDropDownButton1.ShowDropDownArrow = false; + this.toolStripDropDownButton1.Size = new System.Drawing.Size(29, 22); + this.toolStripDropDownButton1.Text = "File"; + // + // openToolStripMenuItem + // + this.openToolStripMenuItem.Name = "openToolStripMenuItem"; + this.openToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.openToolStripMenuItem.Text = "Open"; + this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); + // + // importToolStripMenuItem + // + this.importToolStripMenuItem.Name = "importToolStripMenuItem"; + this.importToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.importToolStripMenuItem.Text = "Import"; + this.importToolStripMenuItem.Click += new System.EventHandler(this.importToolStripMenuItem_Click); + // + // exportToolStripMenuItem + // + this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; + this.exportToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.exportToolStripMenuItem.Text = "Export"; + this.exportToolStripMenuItem.Click += new System.EventHandler(this.exportToolStripMenuItem_Click); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.exitToolStripMenuItem.Text = "Exit"; + // + // toolStripDropDownButton2 + // + this.toolStripDropDownButton2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripDropDownButton2.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.saveVTFXInfoToolStripMenuItem}); + this.toolStripDropDownButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripDropDownButton2.Image"))); + this.toolStripDropDownButton2.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripDropDownButton2.Name = "toolStripDropDownButton2"; + this.toolStripDropDownButton2.ShowDropDownArrow = false; + this.toolStripDropDownButton2.Size = new System.Drawing.Size(38, 22); + this.toolStripDropDownButton2.Text = "Tools"; + // + // saveVTFXInfoToolStripMenuItem + // + this.saveVTFXInfoToolStripMenuItem.Name = "saveVTFXInfoToolStripMenuItem"; + this.saveVTFXInfoToolStripMenuItem.Size = new System.Drawing.Size(151, 22); + this.saveVTFXInfoToolStripMenuItem.Text = "Save VTFX Info"; + // + // groupBox1 + // + this.groupBox1.AutoSize = true; + this.groupBox1.Controls.Add(this.MonsieurResizer); + this.groupBox1.Location = new System.Drawing.Point(77, 54); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(527, 553); + this.groupBox1.TabIndex = 5; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Preview"; + // + // MonsieurResizer + // + this.MonsieurResizer.AutoScroll = true; + this.MonsieurResizer.Controls.Add(this.PreviewBox); + this.MonsieurResizer.Location = new System.Drawing.Point(6, 19); + this.MonsieurResizer.Name = "MonsieurResizer"; + this.MonsieurResizer.Size = new System.Drawing.Size(515, 515); + this.MonsieurResizer.TabIndex = 10; + // + // PreviewBox + // + this.PreviewBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; + this.PreviewBox.Location = new System.Drawing.Point(0, 0); + this.PreviewBox.Name = "PreviewBox"; + this.PreviewBox.Size = new System.Drawing.Size(512, 512); + this.PreviewBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.PreviewBox.TabIndex = 0; + this.PreviewBox.TabStop = false; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(621, 86); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(74, 13); + this.label1.TabIndex = 6; + this.label1.Text = "Platform type: "; + // + // TxFmtLb + // + this.TxFmtLb.AutoSize = true; + this.TxFmtLb.Location = new System.Drawing.Point(621, 99); + this.TxFmtLb.Name = "TxFmtLb"; + this.TxFmtLb.Size = new System.Drawing.Size(81, 13); + this.TxFmtLb.TabIndex = 7; + this.TxFmtLb.Text = "Texture format: "; + // + // DimensionLb + // + this.DimensionLb.AutoSize = true; + this.DimensionLb.Location = new System.Drawing.Point(621, 112); + this.DimensionLb.Name = "DimensionLb"; + this.DimensionLb.Size = new System.Drawing.Size(67, 13); + this.DimensionLb.TabIndex = 8; + this.DimensionLb.Text = "Dimensions: "; + // + // groupBox2 + // + this.groupBox2.AutoSize = true; + this.groupBox2.Controls.Add(this.ResTbl); + this.groupBox2.Dock = System.Windows.Forms.DockStyle.Right; + this.groupBox2.Location = new System.Drawing.Point(867, 25); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(345, 598); + this.groupBox2.TabIndex = 9; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Resources"; + // + // ResTbl + // + this.ResTbl.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.ResTbl.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.ResType, + this.ResOffset}); + this.ResTbl.GridLines = true; + this.ResTbl.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.ResTbl.HideSelection = false; + this.ResTbl.Location = new System.Drawing.Point(7, 20); + this.ResTbl.Name = "ResTbl"; + this.ResTbl.Size = new System.Drawing.Size(332, 193); + this.ResTbl.TabIndex = 0; + this.ResTbl.UseCompatibleStateImageBehavior = false; + this.ResTbl.View = System.Windows.Forms.View.Details; + // + // ResType + // + this.ResType.Text = "Resource Type"; + this.ResType.Width = 189; + // + // ResOffset + // + this.ResOffset.Text = "Resource Offset (base 10)"; + this.ResOffset.Width = 137; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.AutoSize = true; + this.ClientSize = new System.Drawing.Size(1212, 623); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.DimensionLb); + this.Controls.Add(this.TxFmtLb); + this.Controls.Add(this.label1); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.toolStrip1); + this.Controls.Add(this.helloWorldLabel); + this.Margin = new System.Windows.Forms.Padding(2); + this.Name = "Form1"; + this.Text = "VTFXUtil"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.MonsieurResizer.ResumeLayout(false); + this.MonsieurResizer.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PreviewBox)).EndInit(); + this.groupBox2.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.Label helloWorldLabel; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton1; + private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton2; + private System.Windows.Forms.ToolStripMenuItem saveVTFXInfoToolStripMenuItem; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label TxFmtLb; + private System.Windows.Forms.Label DimensionLb; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.ListView ResTbl; + private System.Windows.Forms.ColumnHeader ResType; + private System.Windows.Forms.ColumnHeader ResOffset; + private System.Windows.Forms.PictureBox PreviewBox; + private System.Windows.Forms.Panel MonsieurResizer; + private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem; + } +} + diff --git a/VTFXUtil/Form1.cs b/VTFXUtil/Form1.cs new file mode 100644 index 0000000..6141420 --- /dev/null +++ b/VTFXUtil/Form1.cs @@ -0,0 +1,390 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; // image control +using System.Linq; // this might need to be tossed +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; // UI + + +namespace VTFXUtil +{ + public partial class Form1 : Form + { + public static ImageImportProperties MyCodeSucks = null; // i forced this to be classwide, so that importing would work correctly + // i really did not want to deal with returning tuples + private static VTFXHandler.VTFXFile FileInMem; // make this a classwide var, will use for exporting + private static byte[] UnscrewedTextureData; // will be used for exporting + private static byte[] UnscrewedMippedTextureData; // used for non-VTF exports + private static bool GlobalMipped; // non-VTF exports will use this + private static readonly string AppTempPath = System.IO.Path.GetTempPath() + @"\DONT TOUCH ME"; + private static int ExportMipCount; // also for exporting + string LabelPersistText = "Platform type: "; + string TexFormatLabelText = "Texture format: "; + string DLb = "Dimensions: "; + OpenFileDialog Opener = new OpenFileDialog(); + public Form1() + { + InitializeComponent(); + } + + private void openToolStripMenuItem_Click(object sender, EventArgs e) + { + + ImportAsVTFX(ImportAndClearTable(), null); // isolated this to make it cleaner here + } + + private string ImportAndClearTable() + { + ResTbl.Items.Clear(); + + + Opener.ShowDialog(); + if (Opener.FileName.Equals("")) + { + return ""; + } + string Path = Opener.FileName; + return Path; + } + + private void ImportAsVTFX(string Path, System.IO.MemoryStream MemStream) + { + if (Path.Equals("")) + { + return; + } + VTFXHandler.VTFXFile Imported; + if(MemStream == null) // checks to see if we are using this to import from a MemoryStream + { + Imported = VTFXHandler.ImportVTFX(Path); + } + else + { + Imported = VTFXHandler.ImportVTFX(MemStream); + } + byte[] VerMaj = new byte[4]; + byte[] VerMin = new byte[4]; + byte[] XBoxBytes = { 0, 0, 3, 96 }; + byte[] PS3Bytes = { 0, 0, 3, 51 }; + bool NeedLZMADecompress = false; + byte[] Texture; + Array.Copy(Imported.VersionNum, 0, VerMaj, 0, 4); + Array.Copy(Imported.VersionNum, 4, VerMin, 0, 4); + Array.Reverse(VerMin); + int VerMinInt = System.BitConverter.ToInt32(VerMin, 0); + string VerTextAppend = ""; + Console.WriteLine(VerMaj); + Console.WriteLine(VerMin); + foreach (object Thing in VerMaj) + { + Console.WriteLine(Thing); + } + foreach (object Thing in VerMin) + { + Console.WriteLine(Thing); + } + if (VerMaj.SequenceEqual(XBoxBytes)) + { + VerTextAppend = "Xbox 360"; + NeedLZMADecompress = true; + } + else if (VerMaj.SequenceEqual(PS3Bytes)) + { + VerTextAppend = "PlayStation 3"; + } + else + { + VerTextAppend = "Unknown"; + } + label1.Text = LabelPersistText + VerTextAppend + ", Revision " + VerMinInt.ToString(); + byte[] TxFmtLE = Imported.TextureFormat; + int TxFmtInt = System.BitConverter.ToInt32(TxFmtLE, 0); + TxFmtLb.Text = TexFormatLabelText + VTFGeneral.TexFmtStrArr[TxFmtInt]; + Console.WriteLine("Texture format of imported texture is: {0}.", VTFGeneral.TexFmtStrArr[TxFmtInt]); + DimensionLb.Text = DLb + Imported.ImageWidth.ToString() + "x" + Imported.ImageHeight.ToString(); + foreach (var Resource in Imported.Resources) + { + string[] ResArr = new string[2]; + ResArr[0] = VTFGeneral.GetResourceType(Resource.Key); + ResArr[1] = Resource.Value.ToString(); + ListViewItem ResourceItem = new ListViewItem(ResArr); + ResTbl.Items.Add(ResourceItem); + } + System.IO.Directory.CreateDirectory(AppTempPath); + if (NeedLZMADecompress) //Xbox 360 textures are LZMA compressed, so we need to decompress them into an uncompressed mess + { + string TempInPath = AppTempPath + @"\" + Opener.SafeFileName + ".ENC"; + string TempOutPath = AppTempPath + @"\" + Opener.SafeFileName + ".DEC"; + Texture = ImageImporter.LZMADecompress(Imported.FileData, TempInPath, TempOutPath); + } + else //just take the file data itself, will only be used in the case of PS3 formatted files + { + Texture = Imported.FileData; + } + VTFGeneral.VTFFormatProps TextureProperties = VTFGeneral.FormatTable[TxFmtInt]; + int ByteBufferLen = TextureProperties.ColorByteAmount; + if (!(TextureProperties.IsCompressed)) // endianswap for non-compressed textures + { + Texture = ImageImporter.EndianSwap(Texture, ByteBufferLen); + } + if (TextureProperties.IsCompressed && NeedLZMADecompress) //this will only trigger on files from the 360, as they will always be LZMA compressed + { + Console.WriteLine("This is a 360 texture, needing to fuck it up now!"); + Texture = ImageImporter.RearrangeCompressedTexture(Texture, TxFmtInt); + } + //STARTING HERE, MIPMAPS WILL BE REVERSED, AS DDS AND OTHER FORMATS HAVE THE BIGGEST MIP FIRST, WHILE VTF HAS SMALLEST MIP FIRST + + bool Mippable = MipMaker.IsMipped(Imported.ImageWidth, Imported.ImageHeight, TxFmtInt, Texture.Length); + GlobalMipped = Mippable; + + System.IO.MemoryStream CurrentTexture = new System.IO.MemoryStream(); + MipMaker.MipMap[] MipList; + int MipCount = 1; + if (Mippable) + { + //Console.WriteLine("hey we can mip this"); + MipList = MipMaker.GenMipInfo(Imported.ImageWidth, Imported.ImageHeight, TxFmtInt); + MipCount = MipList.Length; + CurrentTexture = ImageImporter.ReverseMipsIntoMemoryStream(Texture, Imported.ImageWidth, Imported.ImageHeight, TxFmtInt, MipList); + } + + UnscrewedTextureData = Texture; + if (Mippable) + { + Texture = CurrentTexture.ToArray(); + UnscrewedMippedTextureData = Texture; + } + ExportMipCount = MipCount; + System.IO.MemoryStream PNGStream = ImageImporter.GenerateImage(Texture, ExportMipCount, TxFmtInt, Imported); + Bitmap PreviewImage = new Bitmap(PNGStream); + PreviewBox.Image = PreviewImage; + FileInMem = Imported; // pass this through for export purposes + if (Imported.ImageWidth > MonsieurResizer.Width || Imported.ImageHeight > MonsieurResizer.Height) + { + PreviewBox.SizeMode = PictureBoxSizeMode.AutoSize; // enable autosizing to allow for scrollbars to appear if image is bigger than 512x512 + } + else + { + PreviewBox.Width = 512; + PreviewBox.Height = 512; // set picture box size to default, that way it properly recenters it + PreviewBox.SizeMode = PictureBoxSizeMode.CenterImage; // apply centering + } + GC.Collect(); // we're done here, clean the ram + } + + private void Form1_FormClosed(object sender, FormClosedEventArgs e) + { + if (System.IO.Directory.Exists(AppTempPath)) + { + System.IO.Directory.Delete(AppTempPath, true); // empty the temp directory that we have + } + } + + private void exportToolStripMenuItem_Click(object sender, EventArgs e) + { + SaveFileDialog SaveDlg = new SaveFileDialog(); + SaveDlg.Filter = "Valve Texture Format|*.vtf|Tagged Image Format|*.tif|DirectDraw Surface|*.dds"; // hehe filters + SaveDlg.Title = "Export File"; + SaveDlg.ShowDialog(); + if (SaveDlg.FileName.Equals("")) + { + return; + } + System.IO.FileStream OutputFile = (System.IO.FileStream)SaveDlg.OpenFile(); + switch (SaveDlg.FilterIndex) + { + case 1: // VTF + byte[] VTFString = { 0x56, 0x54, 0x46, 0x00 }; // "VTF" + 0x00 + byte[] VTFVer = { 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 }; // Defaults to 7.3 + int ResourceHeaderLength = 8; //only exports high res data and headers, as the console formats seem to only use it + int HeaderSize = 0x50 + ResourceHeaderLength; + byte[] StartFrame = { 0x00, 0x00 }; + byte[] FourBytePadding = { 0x00, 0x00, 0x00, 0x00 }; + byte[] HighRes = { 0x30, 0x00, 0x00, 0x00 }; + byte[] NOFORMAT = { 0xFF, 0xFF, 0xFF, 0xFF }; + int MipCount = ExportMipCount; // is set to whatever was calculated earlier on when importing + // holy fuck this feels like too much just to write one file + OutputFile.Write(VTFString, 0, VTFString.Length); + OutputFile.Write(VTFVer, 0, VTFVer.Length); + OutputFile.Write(BitConverter.GetBytes(HeaderSize), 0, 4); + OutputFile.Write(BitConverter.GetBytes(FileInMem.ImageWidth), 0, 2); + OutputFile.Write(BitConverter.GetBytes(FileInMem.ImageHeight), 0, 2); + OutputFile.Write(FileInMem.VTFFlags, 0, FileInMem.VTFFlags.Length); + OutputFile.Write(BitConverter.GetBytes(FileInMem.FrameCount), 0, 2); + OutputFile.Write(StartFrame, 0, 2); + OutputFile.Write(FourBytePadding, 0, 4); + OutputFile.Write(FileInMem.ReflectivityVec, 0, 12); + OutputFile.Write(FourBytePadding, 0, 4); + OutputFile.Write(BitConverter.GetBytes(FileInMem.BumpScale), 0, 4); + OutputFile.Write(FileInMem.TextureFormat, 0, FileInMem.TextureFormat.Length); + OutputFile.Write(BitConverter.GetBytes(MipCount), 0, 1); + OutputFile.Write(NOFORMAT, 0, 4); + OutputFile.Write(BitConverter.GetBytes(0), 0, 1); + OutputFile.Write(BitConverter.GetBytes(0), 0, 1); + OutputFile.Write(BitConverter.GetBytes(FileInMem.BitDepth), 0, 1); + OutputFile.Write(FourBytePadding, 0, 4); + OutputFile.Write(BitConverter.GetBytes(FileInMem.ResourceCount), 0, 4); + OutputFile.Write(FourBytePadding, 0, 4); + OutputFile.Write(FourBytePadding, 0, 4); + OutputFile.Write(HighRes, 0, 4); + OutputFile.Write(BitConverter.GetBytes(HeaderSize), 0, 4); + OutputFile.Write(UnscrewedTextureData, 0, UnscrewedTextureData.Length); + break; + case 2: // TIF + Console.WriteLine("Not implemented yet!!!"); + break; + case 3: // DDS + CSharpImageLibrary.ImageEngineFormat ParsedEnum = (CSharpImageLibrary.ImageEngineFormat)Enum.Parse(typeof(VTFGeneral.TEXTURE_FORMATS_INTEROP), Enum.GetName(typeof(VTFGeneral.TEXTURE_FORMATS), System.BitConverter.ToInt32(FileInMem.TextureFormat, 0))); + CSharpImageLibrary.Headers.DDS_Header newDDSHeader = new CSharpImageLibrary.Headers.DDS_Header(ExportMipCount, FileInMem.ImageHeight, FileInMem.ImageWidth, ParsedEnum, CSharpImageLibrary.Headers.DDS_Header.DXGI_FORMAT.DXGI_FORMAT_UNKNOWN); + byte[] DDSHeader = new byte[newDDSHeader.dwSize + 4]; + newDDSHeader.WriteToArray(DDSHeader, 0); + byte[] RealTexture = new byte[DDSHeader.Length + UnscrewedTextureData.Length]; + Array.Copy(DDSHeader, 0, RealTexture, 0, DDSHeader.Length); + if (GlobalMipped) + { + Array.Copy(UnscrewedMippedTextureData, 0, RealTexture, DDSHeader.Length, UnscrewedMippedTextureData.Length); + } + else + { + Array.Copy(UnscrewedTextureData, 0, RealTexture, DDSHeader.Length, UnscrewedTextureData.Length); + } + OutputFile.Write(RealTexture, 0, RealTexture.Length); + break; + } + OutputFile.Close(); + } + + + + private void importToolStripMenuItem_Click(object sender, EventArgs e) + { + // i wonder how well it can work with animated png's + // if i can't do that then i guess some other demuxing of other formats could do the job + + ImageProcessor.ImageFactory Factory = new ImageProcessor.ImageFactory(); + bool ReverseMips = false; + OpenFileDialog Opener = new OpenFileDialog(); + Opener.Multiselect = true; // we will need this for animated images!!!! + Opener.Filter = "DirectDraw Surface|*.dds|JPEG|*.jpg, *.jfif, *.jpeg|Portable Network Graphics|*.png|Tagged Image Format|*.tif|Targa|*.tga|Valve Texture Format|*.vtf"; + Opener.Title = "Import File"; + Opener.ShowDialog(); + if (Opener.FileName.Equals("")) + { + Console.WriteLine("whoops nothing!"); + return; + } + bool CanAcceptMultipleFrames = false; + // getting frames from an image seems to be dependant on c#'s internal methods + // so i hope to fuck that it can handle an animated png, considering how they've been around for over a decade + Form2 ImportDlg = new Form2(); + ImportDlg.ShowDialog(); + if (MyCodeSucks == null) + { + return; + } + System.IO.FileStream InputFile = (System.IO.FileStream)Opener.OpenFile(); + //Factory.Load(InputFile); // leave this out for now, need to figure out image shit + // anything that isn't png or vtf will have to have individual frames shoved in as seperate files + + VTFXHandler.VTFXFile TheCreation = new VTFXHandler.VTFXFile(); + TheCreation.FileMagic = "VTFX"; + + switch (Opener.FilterIndex) + { + case 1: // dds + ReverseMips = true; + // probably just do nothing but reverse our mips here + break; + case 2: // overly crunchy horrendous format that should never be used ever again + break; + case 3: // png + CanAcceptMultipleFrames = true; + break; + case 4: // tif + ReverseMips = true; + break; + case 5: // tga + break; + case 6: // vtf + CanAcceptMultipleFrames = true; + // converting into vtfx from vtf shouldn't be hard, as all that needs to be done seems to be fairly basic + break; + } + if(Opener.FilterIndex != 6) // non-vtf formats will need some special treatments, such as being forced into RGBA8888 to properly reverse our mipmaps, as RGBA8888 is a more malleable format + { + + } + else + { + Formats.VTFFile ImportVTF = new Formats.VTFFile(); + byte[] VTFTextureData; + using (InputFile) // convert our file data into an object, and fill the object with the file's data + { + InputFile.Position += 4; // skip file magic, we already told it to ensure that it is correct + InputFile.Read(ImportVTF.FileVersion, 0, 8); + byte[] TempByteConvert = new byte[4]; + InputFile.Read(TempByteConvert, 0, 4); + ImportVTF.HeaderLength = System.BitConverter.ToInt32(TempByteConvert, 0); + TempByteConvert = new byte[2]; + InputFile.Read(TempByteConvert, 0, 2); + ImportVTF.Width = System.BitConverter.ToInt16(TempByteConvert, 0); + InputFile.Read(TempByteConvert, 0, 2); + ImportVTF.Height = System.BitConverter.ToInt16(TempByteConvert, 0); + InputFile.Read(ImportVTF.Flags, 0, 4); + InputFile.Read(TempByteConvert, 0, 2); + ImportVTF.Frames = System.BitConverter.ToInt16(TempByteConvert, 0); + InputFile.Read(TempByteConvert, 0, 2); + ImportVTF.FirstFrame = System.BitConverter.ToInt16(TempByteConvert, 0); + InputFile.Position += 4; // skip over padding + InputFile.Read(ImportVTF.ReflectivityVector, 0, 12); + InputFile.Position += 4; // skip over more padding + TempByteConvert = new byte[4]; + InputFile.Read(TempByteConvert, 0, 4); + ImportVTF.BumpScale = System.BitConverter.ToSingle(TempByteConvert, 0); + InputFile.Read(ImportVTF.Format, 0, 4); + TempByteConvert = new byte[1]; + InputFile.Read(TempByteConvert, 0, 1); + ImportVTF.MipmapCount = TempByteConvert[0]; + InputFile.Read(ImportVTF.ThumbFormat, 0, 4); + InputFile.Read(TempByteConvert, 0, 1); + ImportVTF.ThumbWidth = TempByteConvert[0]; + InputFile.Read(TempByteConvert, 0, 1); + ImportVTF.ThumbHeight = TempByteConvert[0]; + InputFile.Read(TempByteConvert, 0, 1); + ImportVTF.ImageDepth = TempByteConvert[0]; + InputFile.Position += 4; // skip over even more padding + TempByteConvert = new byte[4]; + InputFile.Read(TempByteConvert, 0, 4); + ImportVTF.ResourceCount = System.BitConverter.ToInt32(TempByteConvert, 0); + int ResByteLength = ImportVTF.ResourceCount * 8; + while(ResByteLength > 0) // get those resources, boy + { + byte[] ResType = new byte[3]; + byte ResKind; + int ResOffset; + InputFile.Read(ResType, 0, 3); + ResByteLength -= 3; + TempByteConvert = new byte[1]; + InputFile.Read(TempByteConvert, 0, 1); + ResKind = TempByteConvert[0]; + ResByteLength--; + TempByteConvert = new byte[4]; + InputFile.Read(TempByteConvert, 0, 4); + ResOffset = System.BitConverter.ToInt32(TempByteConvert, 0); + ImportVTF.Resources.Add(new VTFGeneral.VTFResource(ResType, ResKind, ResOffset)); + ResByteLength -= 4; + } + VTFTextureData = new byte[InputFile.Length - ImportVTF.HeaderLength]; + InputFile.Read(VTFTextureData, 0, VTFTextureData.Length); + // need to make some crap here with endianswapping and byteswapping for texture data, which needs to happen before compression!!!! + System.IO.MemoryStream Compressed = ImageImporter.LZMACompress(VTFTextureData); + byte[] CompressedArray = Compressed.ToArray(); + } + } + Console.WriteLine("does not work yet!"); + } + } +} diff --git a/VTFXUtil/Form1.resx b/VTFXUtil/Form1.resx new file mode 100644 index 0000000..4c9758d --- /dev/null +++ b/VTFXUtil/Form1.resx @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/VTFXUtil/Form2.cs b/VTFXUtil/Form2.cs new file mode 100644 index 0000000..7f78798 --- /dev/null +++ b/VTFXUtil/Form2.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +// this will now be a new home for our texture import options + +namespace VTFXUtil +{ + public partial class Form2 : Form + { + public string OutAlphaFmt; + public string OutNoAlphaFmt; + public string OutTexType; + public bool DemandedResize; + public bool DemandedClamps; + public bool CanGenerateMips; + public string Ree; + public int ClampingWidth; + public int ClampingHeight; + public string Platform; + public Form2() + { + InitializeComponent(); + } + + private void OKButton_Click(object sender, EventArgs e) + { + DemandedResize = ResizeCheckbox.Checked; + DemandedClamps = ClampCheckbox.Checked; + CanGenerateMips = MakeMipCheckBox.Checked; + OutAlphaFmt = AlphaCombo.GetItemText(AlphaCombo.SelectedItem); + OutNoAlphaFmt = NonAlphaCombo.GetItemText(NonAlphaCombo.SelectedItem); + OutTexType = TexTypeCombo.GetItemText(TexTypeCombo.SelectedItem); + Ree = ResizeMethodCombo.GetItemText(ResizeMethodCombo.SelectedItem); + ClampingWidth = Int32.Parse(ClampWidth.GetItemText(ClampWidth.SelectedItem)); + ClampingHeight = Int32.Parse(ClampHeight.GetItemText(ClampHeight.SelectedItem)); + Platform = PlatformCombo.GetItemText(PlatformCombo.SelectedItem); // yoink our values, is used down below + Form1.MyCodeSucks = new ImageImportProperties(OutAlphaFmt, OutNoAlphaFmt, OutTexType, DemandedResize, DemandedClamps, CanGenerateMips, Ree, ClampingWidth, ClampingHeight, Platform); + if (!DemandedResize) + { + DialogResult Dresult; + + Dresult = MessageBox.Show("Since you disabled resizing, non power of 2 images may have issues ingame and/or while importing/exporting.\nWould you like to continue anyways?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); + if (Dresult == DialogResult.Yes) + { + Close(); + } + } + Close(); + } + + private void Form2_Load(object sender, EventArgs e) + { + Console.WriteLine("EYYY IM WALKIN HERE"); + PlatformTooltip.SetToolTip(PlatformCombo, "Selects the desired target platform for the texture."); + for (int i = 0; i < VTFGeneral.TexFmtStrArr.Length; i++) // init the format comboboxes + { + NonAlphaCombo.Items.Add(VTFGeneral.TexFmtStrArr[i]); + AlphaCombo.Items.Add(VTFGeneral.TexFmtStrArr[i]); + } + List PowsOf2 = new List(); // did this to make our clamp values easily made, so i didn't have to manually slap them in + PowsOf2.Add(1); + PowsOf2.Add(2); + int CounterVar = 2; + while (CounterVar < 4096) + { + CounterVar = CounterVar * 2; + PowsOf2.Add(CounterVar); + } + int[] Array2Pows = PowsOf2.ToArray(); + for (int i = 0; i < Array2Pows.Length; i++) + { + ClampWidth.Items.Add(Array2Pows[i]); + ClampHeight.Items.Add(Array2Pows[i]); + } + ClampCheckbox.Checked = true; // force enable our checkboxes, it makes the greying out code work correctly + ClampWidth.SelectedIndex = ClampWidth.Items.Count - 1; // default to highest possible dimension + ClampHeight.SelectedIndex = ClampWidth.Items.Count - 1; + ResizeCheckbox.Checked = true; + ResizeMethodCombo.SelectedIndex = 0; // set default values for comboboxes + NonAlphaCombo.SelectedIndex = 2; + AlphaCombo.SelectedIndex = 0; + TexTypeCombo.SelectedIndex = 0; + PlatformCombo.SelectedIndex = 0; + } + + private void ResizeCheckbox_CheckedChanged(object sender, EventArgs e) + { + if (!ResizeCheckbox.Checked) // quit touching my shit bro + { + ResizeMethodCombo.Enabled = false; + } + else + { + ResizeMethodCombo.Enabled = true; + } + } + + private void ClampCheckbox_CheckedChanged(object sender, EventArgs e) + { + if (!ClampCheckbox.Checked) // grey that shit out + { + ClampWidth.Enabled = false; + ClampHeight.Enabled = false; + } + else + { + ClampWidth.Enabled = true; + ClampHeight.Enabled = true; + } + } + + private void CancelButton_Click(object sender, EventArgs e) + { + Close(); // release the user from this janky window + } + } +}