//Return a boolean, test if the file should be excluded public bool IsFileExcluded(string sFilePath, FolderProcessingParams cfg) { var extension = Path.GetExtension(sFilePath); if (!cfg.ProcessMBMs && extension == ".mbm") { return(true); } if (!cfg.ProcessTGAs && extension == ".tga") { return(true); } if (!cfg.ProcessPNGs && extension == ".png") { return(true); } var b = false; //No idea what this does for (var i = 0; i <= excludedList.Count - 1; i++) { if (sFilePath.Contains(excludedList[i])) { i = excludedList.Count - 1; b = true; } } return(b); }
//a custom function to call ShowDialog(), so parameters can be updated before the window is closed public DialogResult CustomShowDialog(string sPath, FolderProcessingParams CFG) { if (ShowDialog() == DialogResult.OK) { //(assume CFG is already instantiated) //Format CFG.Compressed = RB_format_compressed.Checked; CFG.ProcessMBMs = CB_format_incMBM.Checked; CFG.ProcessTGAs = CB_format_incTGA.Checked; CFG.ProcessPNGs = CB_format_incPNG.Checked; //normals CFG.NormalsManagement = CB_normal_ConvSelect.SelectedIndex; //mipmaps CFG.GenerateMipmaps = CB_mipmap_Generate.Checked; //resize if (CB_resize_MinResolution.Checked) { CFG.MinRes_Resize_Width = Convert.ToInt32(NUD_resize_MinWidth.Value); CFG.MinRes_Resize_Height = Convert.ToInt32(NUD_resize_MinHeight.Value); } else { CFG.MinRes_Resize_Width = 1; CFG.MinRes_Resize_Height = 1; } switch (CB_resize_Ratio.SelectedIndex) { case 0: CFG.ResizeRatio = 1; break; case 1: CFG.ResizeRatio = 0.75; break; case 2: CFG.ResizeRatio = 0.5; break; case 3: CFG.ResizeRatio = 0.25; break; default: CFG.ResizeRatio = 1; break; } //misc CFG.MinRes_Process_Width = Convert.ToInt32(NUD_misc_MinWidth.Value); CFG.MinRes_Process_Height = Convert.ToInt32(NUD_misc_MinHeight.Value); CFG.DeleteFilesOnSuccess = RB_misc_DeleteFiles.Checked; CFG.BackupFile = RB_misc_KeepBackups.Checked; CFG.IgnoreExceptions = CB_misc_IgnoreExceptions.Checked; return(DialogResult.OK); } else { return(DialogResult.Cancel); } }
//resetting the controls to something accurate private void ResetWindow() { //create a new cfg to reset automatic parameters var folderCFG = new FolderProcessingParams(); //Format RB_format_compressed.Checked = folderCFG.Compressed; CB_format_incMBM.Checked = folderCFG.ProcessMBMs; CB_format_incTGA.Checked = folderCFG.ProcessTGAs; CB_format_incPNG.Checked = folderCFG.ProcessPNGs; //normals CB_normal_ConvSelect.SelectedIndex = folderCFG.NormalsManagement; //mipmaps CB_mipmap_Generate.Checked = folderCFG.GenerateMipmaps; //resize CB_resize_Ratio.SelectedIndex = 0; CB_resize_MinResolution.Checked = true; NUD_resize_MinWidth.Value = folderCFG.MinRes_Resize_Width; NUD_resize_MinHeight.Value = folderCFG.MinRes_Resize_Height; //misc NUD_misc_MinWidth.Value = folderCFG.MinRes_Process_Height; NUD_misc_MinHeight.Value = folderCFG.MinRes_Process_Width; RB_misc_DeleteFiles.Checked = folderCFG.DeleteFilesOnSuccess; RB_misc_KeepBackups.Checked = folderCFG.BackupFile; CB_misc_IgnoreExceptions.Checked = folderCFG.IgnoreExceptions; }
//Return a boolean, test if the file should be excluded public bool IsFileExcluded(string sFilePath, FolderProcessingParams cfg) { var extension = Path.GetExtension(sFilePath); if (!cfg.ProcessMBMs && extension == ".mbm") { return(true); } if (!cfg.ProcessTGAs && extension == ".tga") { return(true); } if (!cfg.ProcessPNGs && extension == ".png") { return(true); } var b = false; //No idea what this does for (var i = 0; i <= excludedList.Count - 1; i++) { if (sFilePath.Contains(excludedList[i])) { i = excludedList.Count - 1; b = true; // performance optimization with long exclude lists: // after first match dont check rest of exclusions return(b); } } return(b); }
//Folder/export all private void ExportAllToDDSToolStripMenuItem_Click(Object sender, EventArgs e) { var folderCFG = new FolderProcessingParams(); var dlgFolder = new FolderDialog(); if (dlgFolder.CustomShowDialog(loadedFolder, folderCFG) == DialogResult.OK) { PB_main.Visible = true; lbl_PBInfos.Visible = true; lbl_PBInfos.Text = ""; PB_main.Value = 0; FolderLoader.ProcessFileLists(loadedFolder, folderCFG); PB_main.Visible = false; lbl_PBInfos.Visible = false; } }
//Convert a mbm file to dds public static void ConvertMBMtoDDS(ConversionParameters convParams, FolderProcessingParams cfg) { //get a new filepath with a dds extension var fpNew = Path.ChangeExtension(convParams.FilePath, ".dds"); //open a new mbm file var mbmTemp = new MBMLoader.MBMFile(convParams.FilePath); //resize ratio var dRatio = cfg.ResizeRatio; if (convParams.ResizeSetting == ResizeSetting.DontAllowResize) { dRatio = 1; } //mipmaps level var mipmapLevel = 0; if (convParams.MipmapSetting == MipmapSetting.DontGenerate) { mipmapLevel = 1; } //output format var form = default(Format); switch (convParams.OutputFormat) { case OutputFormat.AutoUncompressed: if (mbmTemp.IsNormal) { form = Format.A8R8G8B8; } else if (mbmTemp.ColorDepth == 24) { form = Format.R8G8B8; } else { form = Format.A8R8G8B8; } break; case OutputFormat.AutoCompressed: form = mbmTemp.ColorDepth == 24 ? Format.Dxt1 : Format.Dxt5; break; case OutputFormat.ForceArgb8: form = Format.A8R8G8B8; break; case OutputFormat.ForceRgb8: form = Format.R8G8B8; break; case OutputFormat.ForceDXT5: form = Format.Dxt5; break; case OutputFormat.ForceDXT1: form = Format.Dxt1; break; } //force normal, or automatic detection var bNormal = false; switch (convParams.NormalMapConversion) { case NormalMapConversion.Automatic: bNormal = mbmTemp.IsNormal; break; case NormalMapConversion.ForceNormal: bNormal = true; break; } //conversion using (var gs = new MemoryStream()) { mbmTemp.AsBitmap().Save(gs, ImageFormat.Bmp); MainForm.Log_WriteLine("LOG : Converting " + convParams.FilePath + " to " + fpNew); MainForm.Log_WriteLine(" Format : " + form + ", normalmap : " + bNormal + ", res: " + (mbmTemp.Width * dRatio) + "x" + (mbmTemp.Height * dRatio)); if ((((mbmTemp.Width < cfg.MinRes_Resize_Width) | (mbmTemp.Height < cfg.MinRes_Resize_Height)) & (Math.Abs(dRatio - 1) > 0.0001f))) { MainForm.Log_WriteLine("LOG : " + convParams.FilePath.Split('.').Last() + ", resolution is too low to be resized."); dRatio = 1; } gs.Position = 0; using (var t = TextureLoader.FromStream(dev, gs, (int)(mbmTemp.Width * dRatio), (int)(mbmTemp.Height * dRatio), mipmapLevel, Usage.None, form, Pool.SystemMemory, Filter.Triangle | Filter.Dither, Filter.Triangle | Filter.Dither, 0)) { TextureLoader.Save(fpNew, ImageFileFormat.Dds, t); } } //set flag for dxt5nm if (bNormal) { MarkAsNormal(fpNew); } //flush textures mbmTemp.Flush(); var ddsifiedFile = convParams.FilePath + ".ddsified"; //delete file after successful conversion if (File.Exists(fpNew)) { if (cfg.BackupFile) { if (File.Exists(ddsifiedFile)) { File.Delete(ddsifiedFile); } File.Move(convParams.FilePath, convParams.FilePath + ".ddsified"); } else if (cfg.DeleteFilesOnSuccess) { File.Delete(convParams.FilePath); } } }
//convert a non-mbm file to dds public static void ConvertFileToDDS(ConversionParameters convParams, FolderProcessingParams cfg) { var sw = Stopwatch.StartNew(); //test: to avoid memory leak, reset the device before every conversion... As this program can't compile on for x64 OSs, large texture hit memory lmit quite fast... //there's a known bug with DirectX9 and his way to load TGA files, image buffer is kept in memory even when the texture is disposed. And, of course, .NET's GarbageCollector is not useful AT ALL here... ResetDevice(); ///// //normals. Since the AssumeNormalMap() function is able to determine if a file failed to load, this function should be called before anything else var bNormal = false; var bLoadFail = false; switch (convParams.NormalMapConversion) { case NormalMapConversion.Automatic: bNormal = AssumeNormalMap(convParams.FilePath, out bLoadFail); break; case NormalMapConversion.ForceNormal: bNormal = true; break; } //skip the file if it failed to load if (bLoadFail) { return; } //get a new filepath for our newly created dds var fpNew = Path.ChangeExtension(convParams.FilePath, ".dds"); //retrive infos from the original file var iInfos = TextureLoader.ImageInformationFromFile(convParams.FilePath); //resize ratio var dRatio = cfg.ResizeRatio; if (convParams.ResizeSetting == ResizeSetting.DontAllowResize) { dRatio = 1; } //Mipmaps level var mipmapLevel = 0; if (convParams.MipmapSetting == MipmapSetting.DontGenerate) { mipmapLevel = 1; } //Output format var form = default(Format); switch (convParams.OutputFormat) { case OutputFormat.AutoUncompressed: if (bNormal) { form = Format.A8R8G8B8; } else { form = Is32BPP(iInfos) ? Format.A8R8G8B8 : Format.R8G8B8; } break; case OutputFormat.AutoCompressed: if (bNormal) { form = Format.Dxt5; } else { form = Is32BPP(iInfos) ? Format.Dxt5 : Format.Dxt1; } break; case OutputFormat.ForceArgb8: form = Format.A8R8G8B8; break; case OutputFormat.ForceRgb8: form = Format.R8G8B8; break; case OutputFormat.ForceDXT5: form = Format.Dxt5; break; case OutputFormat.ForceDXT1: form = Format.Dxt1; break; } //info for log MainForm.Log_WriteLine("LOG : Converting " + convParams.FilePath + " to " + fpNew); //keep small images uncompressed. This is independent from any parameters, the value of 64 is hard-coded if (((iInfos.Width < MinHeightForCompressed) | (iInfos.Height < MinHeightForCompressed))) { if (((form == Format.Dxt1) | (form == Format.Dxt5))) { MainForm.Log_WriteLine("LOG : Resolution is considered too low for DXT compression. Switching to uncompressed format for better quality."); } form = Format.A8R8G8B8; mipmapLevel = 1; } //skip file if the resolution is not correct if (((iInfos.Width < cfg.MinRes_Process_Width) | (iInfos.Height < cfg.MinRes_Process_Width))) { MainForm.Log_WriteLine("LOG : Skipping " + convParams.FilePath + ", resolution is too low."); FolderLoader.FileSkipCount += 1; return; } //check if the file is large enough to be resized if ((((iInfos.Width < cfg.MinRes_Resize_Width) | (iInfos.Height < cfg.MinRes_Resize_Height)) & (Math.Abs(dRatio - 1) > 0.0001f))) { MainForm.Log_WriteLine("LOG : " + convParams.FilePath.Split('.').Last() + ", resolution is too low to be resized."); dRatio = 1; } //corrected width and height, we want them to be multiple of 4 var iCorWidth = iInfos.Width; var iCorHeight = iInfos.Height; if (((iCorWidth % 4) != 0)) { iCorWidth += (4 - (iCorWidth % 4)); } if (((iCorHeight % 4) != 0)) { iCorHeight += (4 - (iCorHeight % 4)); } //bmp format for flipping Texture texture; if (bppFormats24.Contains(iInfos.Format)) { texture = TextureLoader.FromFile(dev, convParams.FilePath, iCorWidth, iCorHeight, 1, Usage.None, Format.R8G8B8, Pool.SystemMemory, Filter.None, Filter.None, 0); //t = TextureLoader.FromFile(dev, convParams.FilePath, iCorWidth, iCorHeight, 1, Usage.None, form, Pool.SystemMemory, Filter.None, Filter.None, 0) } else if (bppFormats32.Contains(iInfos.Format)) { texture = TextureLoader.FromFile(dev, convParams.FilePath, iCorWidth, iCorHeight, 1, Usage.None, Format.A8B8G8R8, Pool.SystemMemory, Filter.None, Filter.None, 0); } else { MainForm.Log_WriteLine("ERR : Unknown file format " + iInfos.Format + ", skipping conversion for " + convParams.FilePath); FolderLoader.FileSkipCount += 1; return; } //info for log MainForm.Log_WriteLine(" Format : " + form + ", normalmap : " + bNormal + ", res: " + (iCorWidth * dRatio) + "x" + (iCorHeight * dRatio)); //the output is saved in a graphicStream, but a memorystream could work just as well. var gs = TextureLoader.SaveToStream(ImageFileFormat.Bmp, texture); texture.Dispose(); //flip FlipImage(gs); //switch to tga format if swizzling if (bNormal) { var sw2 = Stopwatch.StartNew(); texture.Dispose(); texture = TextureLoader.FromStream(dev, gs); gs.Close(); gs.Dispose(); gs = TextureLoader.SaveToStream(ImageFileFormat.Tga, texture); texture.Dispose(); SwizzleImage(gs, iCorWidth, iCorHeight, Is32BPP(iInfos)); sw.Stop(); MainForm.Log_WriteLine(String.Format("SwizzleImage took {0}ms", sw2.Elapsed.TotalMilliseconds)); } //another attempt to flush memory: the program tend to crash if too much large textures are converted //though, if some smaller textures are converted in between, memory is flushed correctly... dev.Reset(pParameters); //saving the texture texture = TextureLoader.FromStream(dev, gs, (int)(iCorWidth * dRatio), (int)(iCorHeight * dRatio), mipmapLevel, Usage.None, form, Pool.SystemMemory, Filter.Triangle | Filter.DitherDiffusion, Filter.Triangle | Filter.DitherDiffusion, 0); TextureLoader.Save(fpNew, ImageFileFormat.Dds, texture); //delete unused stuff texture.Dispose(); gs.Close(); gs.Dispose(); //set flag for normals if (bNormal) { MarkAsNormal(fpNew); } var ddsifiedFile = convParams.FilePath + ".ddsified"; //remove/Backup original file after successful conversion if (File.Exists(fpNew)) { if (cfg.BackupFile) { if (File.Exists(ddsifiedFile)) { File.Delete(ddsifiedFile); } File.Move(convParams.FilePath, ddsifiedFile); } else if (cfg.DeleteFilesOnSuccess) { File.Delete(convParams.FilePath); } } sw.Stop(); MainForm.Log_WriteLine(String.Format("Image conversion took {0}ms", sw.Elapsed.TotalMilliseconds)); }
//processing files lists public static void ProcessFileLists(string sFolderPath, FolderProcessingParams cfg) { RefreshInfo(sFolderPath, false, false); FileSkipCount = 0; var iExcludeCount = 0; var argHandler = new ArgumentsHandler(); var lConvParms = new List <ImageManager.ConversionParameters>(); foreach (var s in fileList) { if (!argHandler.IsFileExcluded(s, cfg)) { lConvParms.Add(argHandler.GetConversionParameters(s, cfg)); } else { iExcludeCount += 1; } } var iStep = 0; MainForm.Log_WriteLine("-----"); MainForm.Log_WriteLine("Starting conversion of " + fileList.Count + " files."); MainForm.Log_WriteLine(" MBM count : " + argHandler.Count_MBM + "."); MainForm.Log_WriteLine(" TGA count : " + argHandler.Count_TGA + "."); MainForm.Log_WriteLine(" PNG count : " + argHandler.Count_PNG + "."); MainForm.Log_WriteLine(iExcludeCount + " files excluded, " + argHandler.Count_NoMipmaps + " files without mipmaps. " + (argHandler.Count_ForceNormal + argHandler.Count_ForceNotNormal) + " files will skip normal detection." + argHandler.Count_NoResize + " files will not be resized."); MainForm.Log_WriteLine("-----"); var sw = Stopwatch.StartNew(); //processing foreach (var c in lConvParms) { if (c.FileType == ImageManager.FileType.MBM) { ImageManager.ConvertMBMtoDDS(c, cfg); } else { ImageManager.ConvertFileToDDS(c, cfg); } iStep += 1; MainForm.ReportProgress(Convert.ToInt32((iStep / lConvParms.Count) * 100), "Processing " + Path.GetFileName(c.FilePath) + ", file " + iStep + "\\" + lConvParms.Count); MainForm.Log_WriteLine("---"); Application.DoEvents(); } sw.Stop(); MainForm.Log_WriteLine("-----"); MainForm.Log_WriteLine(String.Format("Conversion done! {0} files processed in {1}ms.", lConvParms.Count, sw.Elapsed.TotalMilliseconds)); if (FileSkipCount > 0) { MainForm.Log_WriteLine(FileSkipCount + " files skipped, check log.txt for more informations."); } MainForm.Log_WriteLine("-----"); }
//return a conversion parameter for a single file, according to modsExceptions.txt public ImageManager.ConversionParameters GetConversionParameters(string sFilePath, FolderProcessingParams folderParams) { //resfresh counts var extension = Path.GetExtension(sFilePath); switch (extension) { case ".mbm": Count_MBM += 1; break; case ".tga": Count_TGA += 1; break; case ".png": Count_PNG += 1; break; } //resfresh parameters var cpRet = new ImageManager.ConversionParameters(sFilePath); if (folderParams.IgnoreExceptions) { //normals flag switch (folderParams.NormalsManagement) { case 0: cpRet.NormalMapConversion = ImageManager.NormalMapConversion.Automatic; break; case 1: cpRet.NormalMapConversion = ImageManager.NormalMapConversion.ForceNormal; Count_ForceNormal += 1; break; case 2: cpRet.NormalMapConversion = ImageManager.NormalMapConversion.ForceNotNormal; Count_ForceNotNormal += 1; break; } //mipmaps flag cpRet.MipmapSetting = folderParams.GenerateMipmaps ? ImageManager.MipmapSetting.Generate : ImageManager.MipmapSetting.DontGenerate; cpRet.ResizeSetting = ImageManager.ResizeSetting.AllowResize; } else { //normals flag var bB = false; for (var i = 0; i <= forceNormalList.Count - 1; i++) { if (sFilePath.Contains(forceNormalList[i])) { cpRet.NormalMapConversion = ImageManager.NormalMapConversion.ForceNormal; Count_ForceNormal += 1; i = forceNormalList.Count - 1; bB = true; } } if (!bB) { for (var i = 0; i <= forceNotNormalList.Count - 1; i++) { if (sFilePath.Contains(forceNotNormalList[i])) { cpRet.NormalMapConversion = ImageManager.NormalMapConversion.ForceNotNormal; Count_ForceNotNormal += 1; i = forceNotNormalList.Count - 1; bB = true; } } } if (!bB) { switch (folderParams.NormalsManagement) { case 0: cpRet.NormalMapConversion = ImageManager.NormalMapConversion.Automatic; break; case 1: cpRet.NormalMapConversion = ImageManager.NormalMapConversion.ForceNormal; Count_ForceNormal += 1; break; case 2: cpRet.NormalMapConversion = ImageManager.NormalMapConversion.ForceNotNormal; Count_ForceNotNormal += 1; break; } } //no mipmaps flag bB = false; for (var i = 0; i <= noMipmapList.Count - 1; i++) { if (sFilePath.Contains(noMipmapList[i])) { cpRet.MipmapSetting = ImageManager.MipmapSetting.DontGenerate; Count_NoMipmaps += 1; i = noMipmapList.Count - 1; bB = true; } } if (!bB) { if (folderParams.GenerateMipmaps) { cpRet.MipmapSetting = ImageManager.MipmapSetting.Generate; } else { cpRet.MipmapSetting = ImageManager.MipmapSetting.DontGenerate; Count_NoMipmaps += 1; } } //resize flag cpRet.ResizeSetting = ImageManager.ResizeSetting.AllowResize; for (var i = 0; i <= noResizeList.Count - 1; i++) { if (sFilePath.Contains(noResizeList[i])) { cpRet.ResizeSetting = ImageManager.ResizeSetting.DontAllowResize; Count_NoResize += 1; } } } return(cpRet); }
//Custom function to call ShowDialog public DialogResult CustomShowDialog(string sFilePath) { sLoadedFile = sFilePath; AutomaticDetection(sFilePath); if (ShowDialog() == DialogResult.OK) { var imgCFG = new ImageManager.ConversionParameters(sFilePath); var folderCFG = new FolderProcessingParams(); if (CheckBox1.Checked) { imgCFG.MipmapSetting = ImageManager.MipmapSetting.Generate; folderCFG.GenerateMipmaps = true; } else { imgCFG.MipmapSetting = ImageManager.MipmapSetting.DontGenerate; folderCFG.GenerateMipmaps = false; } if (CheckBox2.Checked) { imgCFG.NormalMapConversion = ImageManager.NormalMapConversion.ForceNormal; folderCFG.NormalsManagement = 1; } else { imgCFG.NormalMapConversion = ImageManager.NormalMapConversion.ForceNotNormal; folderCFG.NormalsManagement = 2; } switch ((Formats)ComboBox1.SelectedIndex) { case Formats.DXT1: imgCFG.OutputFormat = ImageManager.OutputFormat.ForceDXT1; folderCFG.Compressed = true; break; case Formats.DXT5: imgCFG.OutputFormat = ImageManager.OutputFormat.ForceDXT5; folderCFG.Compressed = true; break; case Formats.R8G8B8: imgCFG.OutputFormat = ImageManager.OutputFormat.ForceRgb8; folderCFG.Compressed = false; break; case Formats.A8R8G8B8: imgCFG.OutputFormat = ImageManager.OutputFormat.ForceArgb8; folderCFG.Compressed = false; break; } imgCFG.ResizeSetting = ImageManager.ResizeSetting.AllowResize; switch (ComboBox2.SelectedIndex) { case 0: folderCFG.ResizeRatio = 1; break; case 1: folderCFG.ResizeRatio = 0.75; break; case 2: folderCFG.ResizeRatio = 0.5; break; case 3: folderCFG.ResizeRatio = 0.25; break; default: folderCFG.ResizeRatio = 1; break; } folderCFG.DeleteFilesOnSuccess = CheckBox3.Checked; folderCFG.BackupFile = false; if (imgCFG.FileType == ImageManager.FileType.MBM) { ImageManager.ConvertMBMtoDDS(imgCFG, folderCFG); } else { ImageManager.ConvertFileToDDS(imgCFG, folderCFG); } return(DialogResult.OK); } return(DialogResult.Cancel); }